mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-09-27 10:51:13 +00:00
Basic reimplementation of the 2D representation support without PythonOCC. See #1153.
This commit is contained in:
@@ -1,6 +1,6 @@
|
|||||||
* { stroke-linecap: round; }
|
* { stroke-linecap: round; stroke-linejoin: round; }
|
||||||
.cut { fill: black; stroke: black; stroke-linecap: 'round'; stroke-width: 0.35; }
|
*[id] { fill: black; stroke: black; stroke-linecap: 'round'; stroke-width: 0.35; }
|
||||||
.background { fill: white; stroke: black; stroke-linecap: 'round'; stroke-width: 0.25; }
|
.projection { fill: white; stroke: black; stroke-linecap: 'round'; stroke-width: 0.25; }
|
||||||
.annotation { fill: none; stroke: black; stroke-linecap: 'round'; stroke-width: 0.25; }
|
.annotation { fill: none; stroke: black; stroke-linecap: 'round'; stroke-width: 0.25; }
|
||||||
.hidden { stroke-dasharray: 3, 2; }
|
.hidden { stroke-dasharray: 3, 2; }
|
||||||
.solid {}
|
.solid {}
|
||||||
|
|||||||
@@ -88,15 +88,6 @@ def parse_diagram_scale(camera):
|
|||||||
return float(numerator) / float(denominator)
|
return float(numerator) / float(denominator)
|
||||||
|
|
||||||
|
|
||||||
def get_project_collection(scene):
|
|
||||||
"""Get main project collection"""
|
|
||||||
|
|
||||||
colls = [c for c in scene.collection.children if c.name.startswith("IfcProject")]
|
|
||||||
if len(colls) != 1:
|
|
||||||
raise RuntimeError("project collection missing or not unique")
|
|
||||||
return colls[0]
|
|
||||||
|
|
||||||
|
|
||||||
def ortho_view_frame(camera, margin=0.015):
|
def ortho_view_frame(camera, margin=0.015):
|
||||||
"""Calculates 2d bounding box of camera view area.
|
"""Calculates 2d bounding box of camera view area.
|
||||||
|
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ import multiprocessing
|
|||||||
import zipfile
|
import zipfile
|
||||||
import tempfile
|
import tempfile
|
||||||
import numpy as np
|
import numpy as np
|
||||||
import blenderbim.bim.prop
|
from blenderbim.bim.module.drawing.prop import getDiagramScales
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from itertools import cycle
|
from itertools import cycle
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
@@ -1218,7 +1218,8 @@ class IfcImporter:
|
|||||||
if not view_collection:
|
if not view_collection:
|
||||||
view_collection = bpy.data.collections.new("Views")
|
view_collection = bpy.data.collections.new("Views")
|
||||||
bpy.context.scene.collection.children.link(view_collection)
|
bpy.context.scene.collection.children.link(view_collection)
|
||||||
drawing_collection = bpy.data.collections.new(obj.name)
|
group = [r for r in element.HasAssignments if r.is_a("IfcRelAssignsToGroup")][0].RelatingGroup
|
||||||
|
drawing_collection = bpy.data.collections.new("IfcGroup/" + group.Name)
|
||||||
view_collection.children.link(drawing_collection)
|
view_collection.children.link(drawing_collection)
|
||||||
drawing_collection.objects.link(obj)
|
drawing_collection.objects.link(obj)
|
||||||
else:
|
else:
|
||||||
@@ -1342,7 +1343,7 @@ class IfcImporter:
|
|||||||
camera.BIMCameraProperties.target_view = pset["TargetView"]
|
camera.BIMCameraProperties.target_view = pset["TargetView"]
|
||||||
if "Scale" in pset:
|
if "Scale" in pset:
|
||||||
valid_scales = [
|
valid_scales = [
|
||||||
i[0] for i in blenderbim.bim.prop.getDiagramScales(None, None) if pset["Scale"] == i[0].split("|")[-1]
|
i[0] for i in getDiagramScales(None, None) if pset["Scale"] == i[0].split("|")[-1]
|
||||||
]
|
]
|
||||||
if valid_scales:
|
if valid_scales:
|
||||||
camera.BIMCameraProperties.diagram_scale = valid_scales[0]
|
camera.BIMCameraProperties.diagram_scale = valid_scales[0]
|
||||||
|
|||||||
@@ -1,5 +1,102 @@
|
|||||||
import bpy
|
import bpy
|
||||||
import math
|
import math
|
||||||
|
import mathutils.geometry
|
||||||
|
from mathutils import Vector
|
||||||
|
|
||||||
|
# Code taken and updated from https://blenderartists.org/t/detecting-intersection-of-bounding-boxes/457520/2
|
||||||
|
|
||||||
|
|
||||||
|
class BoundingEdge:
|
||||||
|
def __init__(self, v0, v1):
|
||||||
|
self.vertex = (v0, v1)
|
||||||
|
self.vector = v1 - v0
|
||||||
|
|
||||||
|
|
||||||
|
class BoundingFace:
|
||||||
|
def __init__(self, v0, v1, v2):
|
||||||
|
self.vertex = (v0, v1, v2)
|
||||||
|
self.normal = mathutils.geometry.normal(v0, v1, v2)
|
||||||
|
|
||||||
|
|
||||||
|
class BoundingBox:
|
||||||
|
def __init__(self, ob, vertex=None):
|
||||||
|
self.vertex = vertex or [ob.matrix_world @ Vector(v) for v in ob.bound_box]
|
||||||
|
if self.vertex != None:
|
||||||
|
self.edge = [
|
||||||
|
BoundingEdge(self.vertex[0], self.vertex[1]),
|
||||||
|
BoundingEdge(self.vertex[1], self.vertex[2]),
|
||||||
|
BoundingEdge(self.vertex[2], self.vertex[3]),
|
||||||
|
BoundingEdge(self.vertex[3], self.vertex[0]),
|
||||||
|
BoundingEdge(self.vertex[4], self.vertex[5]),
|
||||||
|
BoundingEdge(self.vertex[5], self.vertex[6]),
|
||||||
|
BoundingEdge(self.vertex[6], self.vertex[7]),
|
||||||
|
BoundingEdge(self.vertex[7], self.vertex[4]),
|
||||||
|
BoundingEdge(self.vertex[0], self.vertex[4]),
|
||||||
|
BoundingEdge(self.vertex[1], self.vertex[5]),
|
||||||
|
BoundingEdge(self.vertex[2], self.vertex[6]),
|
||||||
|
BoundingEdge(self.vertex[3], self.vertex[7]),
|
||||||
|
]
|
||||||
|
self.face = [
|
||||||
|
BoundingFace(self.vertex[0], self.vertex[1], self.vertex[3]),
|
||||||
|
BoundingFace(self.vertex[0], self.vertex[4], self.vertex[1]),
|
||||||
|
BoundingFace(self.vertex[0], self.vertex[3], self.vertex[4]),
|
||||||
|
BoundingFace(self.vertex[6], self.vertex[5], self.vertex[7]),
|
||||||
|
BoundingFace(self.vertex[6], self.vertex[7], self.vertex[2]),
|
||||||
|
BoundingFace(self.vertex[6], self.vertex[2], self.vertex[5]),
|
||||||
|
]
|
||||||
|
|
||||||
|
def whichSide(self, vtxs, normal, faceVtx):
|
||||||
|
retVal = 0
|
||||||
|
positive = 0
|
||||||
|
negative = 0
|
||||||
|
for v in vtxs:
|
||||||
|
t = normal.dot(v - faceVtx)
|
||||||
|
if t > 0:
|
||||||
|
positive = positive + 1
|
||||||
|
elif t < 0:
|
||||||
|
negative = negative + 1
|
||||||
|
|
||||||
|
if positive != 0 and negative != 0:
|
||||||
|
return 0
|
||||||
|
|
||||||
|
if positive != 0:
|
||||||
|
retVal = 1
|
||||||
|
else:
|
||||||
|
retVal = -1
|
||||||
|
return retVal
|
||||||
|
|
||||||
|
# Taken from: http://www.geometrictools.com/Documentation/MethodOfSeparatingAxes.pdf
|
||||||
|
def intersect(self, bb):
|
||||||
|
retVal = False
|
||||||
|
if self.vertex != None and bb.vertex != None:
|
||||||
|
# check all the faces of this object for a seperation axis
|
||||||
|
for i, f in enumerate(self.face):
|
||||||
|
d = f.normal
|
||||||
|
if self.whichSide(bb.vertex, d, f.vertex[0]) > 0:
|
||||||
|
return False # all the vertexes are on the +ve side of the face
|
||||||
|
|
||||||
|
# now do it again for the other objects faces
|
||||||
|
for i, f in enumerate(bb.face):
|
||||||
|
d = f.normal
|
||||||
|
if self.whichSide(self.vertex, d, f.vertex[0]) > 0:
|
||||||
|
return False # all the vertexes are on the +ve side of the face
|
||||||
|
|
||||||
|
# do edge checks
|
||||||
|
for e1 in self.edge:
|
||||||
|
for e2 in bb.edge:
|
||||||
|
d = e1.vector.cross(e2.vector)
|
||||||
|
side0 = self.whichSide(self.vertex, d, e1.vertex[0])
|
||||||
|
if side0 == 0:
|
||||||
|
continue
|
||||||
|
side1 = self.whichSide(bb.vertex, d, e1.vertex[0])
|
||||||
|
if side1 == 0:
|
||||||
|
continue
|
||||||
|
|
||||||
|
if (side0 * side1) < 0:
|
||||||
|
return False
|
||||||
|
|
||||||
|
retVal = True
|
||||||
|
return retVal
|
||||||
|
|
||||||
|
|
||||||
# This function stolen from https://github.com/kevancress/MeasureIt_ARCH/blob/dcf607ce0896aa2284463c6b4ae9cd023fc54cbe/measureit_arch_baseclass.py
|
# This function stolen from https://github.com/kevancress/MeasureIt_ARCH/blob/dcf607ce0896aa2284463c6b4ae9cd023fc54cbe/measureit_arch_baseclass.py
|
||||||
@@ -151,3 +248,12 @@ def get_active_drawing(scene):
|
|||||||
return scene.collection.children["Views"].children[f"IfcGroup/{drawing.name}"], drawing.camera
|
return scene.collection.children["Views"].children[f"IfcGroup/{drawing.name}"], drawing.camera
|
||||||
except (KeyError, IndexError):
|
except (KeyError, IndexError):
|
||||||
raise RuntimeError("missing drawing collection")
|
raise RuntimeError("missing drawing collection")
|
||||||
|
|
||||||
|
|
||||||
|
def get_project_collection(scene):
|
||||||
|
"""Get main project collection"""
|
||||||
|
|
||||||
|
colls = [c for c in scene.collection.children if c.name.startswith("IfcProject")]
|
||||||
|
if len(colls) != 1:
|
||||||
|
raise RuntimeError("project collection missing or not unique")
|
||||||
|
return colls[0]
|
||||||
|
|||||||
@@ -1,6 +1,8 @@
|
|||||||
import os
|
import os
|
||||||
|
import re
|
||||||
import bpy
|
import bpy
|
||||||
import json
|
import json
|
||||||
|
import time
|
||||||
import bmesh
|
import bmesh
|
||||||
import subprocess
|
import subprocess
|
||||||
import webbrowser
|
import webbrowser
|
||||||
@@ -8,9 +10,10 @@ import ifcopenshell.util.selector
|
|||||||
import ifcopenshell.util.representation
|
import ifcopenshell.util.representation
|
||||||
import blenderbim.bim.module.drawing.svgwriter as svgwriter
|
import blenderbim.bim.module.drawing.svgwriter as svgwriter
|
||||||
import blenderbim.bim.module.drawing.annotation as annotation
|
import blenderbim.bim.module.drawing.annotation as annotation
|
||||||
import blenderbim.bim.module.drawing.cut_ifc as cut_ifc # TODO: deprecate
|
import blenderbim.bim.module.drawing.cut_ifc as cut_ifc # TODO: deprecate
|
||||||
import blenderbim.bim.module.drawing.sheeter as sheeter
|
import blenderbim.bim.module.drawing.sheeter as sheeter
|
||||||
import blenderbim.bim.module.drawing.scheduler as scheduler
|
import blenderbim.bim.module.drawing.scheduler as scheduler
|
||||||
|
import blenderbim.bim.module.drawing.helper as helper
|
||||||
from mathutils import Vector, Matrix, Euler, geometry
|
from mathutils import Vector, Matrix, Euler, geometry
|
||||||
from blenderbim.bim.ifc import IfcStore
|
from blenderbim.bim.ifc import IfcStore
|
||||||
from ifcopenshell.api.group.data import Data as GroupData
|
from ifcopenshell.api.group.data import Data as GroupData
|
||||||
@@ -33,6 +36,7 @@ class AddDrawing(bpy.types.Operator):
|
|||||||
bl_label = "Add Drawing"
|
bl_label = "Add Drawing"
|
||||||
|
|
||||||
def execute(self, context):
|
def execute(self, context):
|
||||||
|
self.file = IfcStore.get_file()
|
||||||
new = context.scene.DocProperties.drawings.add()
|
new = context.scene.DocProperties.drawings.add()
|
||||||
new.name = "DRAWING {}".format(len(context.scene.DocProperties.drawings))
|
new.name = "DRAWING {}".format(len(context.scene.DocProperties.drawings))
|
||||||
if not bpy.data.collections.get("Views"):
|
if not bpy.data.collections.get("Views"):
|
||||||
@@ -58,7 +62,9 @@ class AddDrawing(bpy.types.Operator):
|
|||||||
bpy.ops.bim.activate_drawing_style()
|
bpy.ops.bim.activate_drawing_style()
|
||||||
|
|
||||||
bpy.ops.bim.add_group()
|
bpy.ops.bim.add_group()
|
||||||
bpy.ops.bim.assign_group(product=camera.name, group=sorted(GroupData.groups.keys())[-1])
|
group = self.file.by_id(sorted(GroupData.groups.keys())[-1])
|
||||||
|
ifcopenshell.api.run("group.edit_group", self.file, **{"group": group, "attributes": {"Name": new.name}})
|
||||||
|
bpy.ops.bim.assign_group(product=camera.name, group=group.id())
|
||||||
bpy.ops.bim.add_pset(obj=camera.name, obj_type="Object", pset_name="EPset_Drawing")
|
bpy.ops.bim.add_pset(obj=camera.name, obj_type="Object", pset_name="EPset_Drawing")
|
||||||
pset_id = sorted(PsetData.products[camera.BIMObjectProperties.ifc_definition_id]["psets"])[-1]
|
pset_id = sorted(PsetData.products[camera.BIMObjectProperties.ifc_definition_id]["psets"])[-1]
|
||||||
bpy.ops.bim.edit_pset(
|
bpy.ops.bim.edit_pset(
|
||||||
@@ -81,22 +87,45 @@ class CreateDrawing(bpy.types.Operator):
|
|||||||
or not self.camera.BIMObjectProperties.ifc_definition_id
|
or not self.camera.BIMObjectProperties.ifc_definition_id
|
||||||
):
|
):
|
||||||
return
|
return
|
||||||
|
self.file = IfcStore.get_file()
|
||||||
|
self.time = None
|
||||||
|
start = time.time()
|
||||||
|
self.profile_code("Start drawing generation process")
|
||||||
self.props = context.scene.DocProperties
|
self.props = context.scene.DocProperties
|
||||||
self.drawing_name = IfcStore.get_file().by_id(self.camera.BIMObjectProperties.ifc_definition_id).Name
|
self.drawing_name = IfcStore.get_file().by_id(self.camera.BIMObjectProperties.ifc_definition_id).Name
|
||||||
base_svg = self.ifc_to_svg(context)
|
base_svg = self.ifc_to_svg(context)
|
||||||
|
self.profile_code("Generate base layer")
|
||||||
annotation_svg = self.annotation_to_svg(context)
|
annotation_svg = self.annotation_to_svg(context)
|
||||||
|
self.profile_code("Generate annotation layer")
|
||||||
svg_path = self.combine_svgs(context, base_svg, annotation_svg)
|
svg_path = self.combine_svgs(context, base_svg, annotation_svg)
|
||||||
|
self.profile_code("Combine SVG layers")
|
||||||
open_with_user_command(bpy.context.preferences.addons["blenderbim"].preferences.svg_command, svg_path)
|
open_with_user_command(bpy.context.preferences.addons["blenderbim"].preferences.svg_command, svg_path)
|
||||||
|
print("Total Time: {:.2f}".format(time.time() - start))
|
||||||
return {"FINISHED"}
|
return {"FINISHED"}
|
||||||
|
|
||||||
|
def profile_code(self, message):
|
||||||
|
if not self.time:
|
||||||
|
self.time = time.time()
|
||||||
|
print("{} :: {:.2f}".format(message, time.time() - self.time))
|
||||||
|
self.time = time.time()
|
||||||
|
|
||||||
def combine_svgs(self, context, base, annotation):
|
def combine_svgs(self, context, base, annotation):
|
||||||
# Hacky :)
|
# Hacky :)
|
||||||
svg_path = os.path.join(context.scene.BIMProperties.data_dir, "diagrams", self.drawing_name + ".svg")
|
svg_path = os.path.join(context.scene.BIMProperties.data_dir, "diagrams", self.drawing_name + ".svg")
|
||||||
with open(svg_path, "w") as outfile:
|
with open(svg_path, "w") as outfile:
|
||||||
with open(base) as infile:
|
with open(base) as infile:
|
||||||
|
should_skip = False
|
||||||
for line in infile:
|
for line in infile:
|
||||||
if "</svg>" in line:
|
if "</svg>" in line:
|
||||||
continue
|
continue
|
||||||
|
elif "<defs>" in line:
|
||||||
|
should_skip = True
|
||||||
|
continue
|
||||||
|
elif "</style>" in line:
|
||||||
|
should_skip = False
|
||||||
|
continue
|
||||||
|
elif should_skip:
|
||||||
|
continue
|
||||||
outfile.write(line)
|
outfile.write(line)
|
||||||
with open(annotation) as infile:
|
with open(annotation) as infile:
|
||||||
for i, line in enumerate(infile):
|
for i, line in enumerate(infile):
|
||||||
@@ -127,6 +156,8 @@ class CreateDrawing(bpy.types.Operator):
|
|||||||
"entities",
|
"entities",
|
||||||
"IfcSpace",
|
"IfcSpace",
|
||||||
"IfcOpeningElement",
|
"IfcOpeningElement",
|
||||||
|
"IfcDoor",
|
||||||
|
"IfcWindow",
|
||||||
]
|
]
|
||||||
)
|
)
|
||||||
return svg_path
|
return svg_path
|
||||||
@@ -205,6 +236,7 @@ class CreateDrawing(bpy.types.Operator):
|
|||||||
svg_writer.annotations.setdefault("misc_objs", []).append(obj)
|
svg_writer.annotations.setdefault("misc_objs", []).append(obj)
|
||||||
|
|
||||||
svg_writer.annotations["attributes"] = [a.name for a in drawing_style.attributes]
|
svg_writer.annotations["attributes"] = [a.name for a in drawing_style.attributes]
|
||||||
|
svg_writer.annotations["annotation_objs"] = self.get_annotation(svg_writer)
|
||||||
|
|
||||||
svg_writer.write()
|
svg_writer.write()
|
||||||
return svg_writer.output
|
return svg_writer.output
|
||||||
@@ -212,6 +244,75 @@ class CreateDrawing(bpy.types.Operator):
|
|||||||
def is_landscape(self):
|
def is_landscape(self):
|
||||||
return bpy.context.scene.render.resolution_x > bpy.context.scene.render.resolution_y
|
return bpy.context.scene.render.resolution_x > bpy.context.scene.render.resolution_y
|
||||||
|
|
||||||
|
def get_annotation(self, svg_writer):
|
||||||
|
results = []
|
||||||
|
x = svg_writer.camera_width / 2
|
||||||
|
y = svg_writer.camera_height / 2
|
||||||
|
z = 0.01
|
||||||
|
camera_box = helper.BoundingBox(
|
||||||
|
self.camera,
|
||||||
|
[
|
||||||
|
self.camera.matrix_world @ Vector((-x, -y, -z)),
|
||||||
|
self.camera.matrix_world @ Vector((-x, -y, 0)),
|
||||||
|
self.camera.matrix_world @ Vector((-x, y, 0)),
|
||||||
|
self.camera.matrix_world @ Vector((-x, y, -z)),
|
||||||
|
self.camera.matrix_world @ Vector((x, -y, -z)),
|
||||||
|
self.camera.matrix_world @ Vector((x, -y, 0)),
|
||||||
|
self.camera.matrix_world @ Vector((x, y, 0)),
|
||||||
|
self.camera.matrix_world @ Vector((x, y, -z)),
|
||||||
|
],
|
||||||
|
)
|
||||||
|
# This should probably be also part of IfcConvert in the future, here is a Python prototype
|
||||||
|
settings_2d = ifcopenshell.geom.settings()
|
||||||
|
settings_2d.set(settings_2d.INCLUDE_CURVES, True)
|
||||||
|
for obj in bpy.data.objects:
|
||||||
|
if not obj.BIMObjectProperties.ifc_definition_id:
|
||||||
|
continue
|
||||||
|
if obj == self.camera:
|
||||||
|
continue
|
||||||
|
element = self.file.by_id(obj.BIMObjectProperties.ifc_definition_id)
|
||||||
|
representation = ifcopenshell.util.representation.get_representation(
|
||||||
|
element, "Plan", "Annotation", self.camera.data.BIMCameraProperties.target_view
|
||||||
|
)
|
||||||
|
if not representation:
|
||||||
|
continue
|
||||||
|
if not camera_box.intersect(helper.BoundingBox(obj)):
|
||||||
|
continue
|
||||||
|
shape = ifcopenshell.geom.create_shape(settings_2d, representation)
|
||||||
|
geometry = shape
|
||||||
|
e = geometry.edges
|
||||||
|
v = geometry.verts
|
||||||
|
results.append(
|
||||||
|
{
|
||||||
|
"raw": element,
|
||||||
|
"classes": self.get_classes(element, "annotation", svg_writer),
|
||||||
|
"edges": [[e[i], e[i + 1]] for i in range(0, len(e), 2)],
|
||||||
|
"vertices": [obj.matrix_world @ Vector((v[i], v[i + 1], v[i + 2])) for i in range(0, len(v), 3)],
|
||||||
|
}
|
||||||
|
)
|
||||||
|
return results
|
||||||
|
|
||||||
|
def get_classes(self, element, position, svg_writer):
|
||||||
|
classes = [position, element.is_a()]
|
||||||
|
material = ifcopenshell.util.element.get_material(element)
|
||||||
|
if material:
|
||||||
|
classes.append("material-{}".format(re.sub("[^0-9a-zA-Z]+", "", self.get_material_name(material))))
|
||||||
|
classes.append("globalid-{}".format(element.GlobalId))
|
||||||
|
for attribute in svg_writer.annotations["attributes"]:
|
||||||
|
result = self.selector.get_element_value(element, attribute)
|
||||||
|
if result:
|
||||||
|
classes.append(
|
||||||
|
"{}-{}".format(re.sub("[^0-9a-zA-Z]+", "", attribute), re.sub("[^0-9a-zA-Z]+", "", result))
|
||||||
|
)
|
||||||
|
return classes
|
||||||
|
|
||||||
|
def get_material_name(self, element):
|
||||||
|
if hasattr(element, "Name") and element.Name:
|
||||||
|
return element.Name
|
||||||
|
elif hasattr(element, "LayerSetName") and element.LayerSetName:
|
||||||
|
return element.LayerSetName
|
||||||
|
return "mat-" + str(element.id())
|
||||||
|
|
||||||
|
|
||||||
class AddAnnotation(bpy.types.Operator):
|
class AddAnnotation(bpy.types.Operator):
|
||||||
bl_idname = "bim.add_annotation"
|
bl_idname = "bim.add_annotation"
|
||||||
|
|||||||
@@ -38,10 +38,10 @@ def getDiagramScales(self, context):
|
|||||||
global diagram_scales_enum
|
global diagram_scales_enum
|
||||||
if (
|
if (
|
||||||
len(diagram_scales_enum) < 1
|
len(diagram_scales_enum) < 1
|
||||||
or (context.scene.unit_settings.system == "IMPERIAL" and len(diagram_scales_enum) == 13)
|
or (bpy.context.scene.unit_settings.system == "IMPERIAL" and len(diagram_scales_enum) == 13)
|
||||||
or (context.scene.unit_settings.system == "METRIC" and len(diagram_scales_enum) == 31)
|
or (bpy.context.scene.unit_settings.system == "METRIC" and len(diagram_scales_enum) == 31)
|
||||||
):
|
):
|
||||||
if context.scene.unit_settings.system == "IMPERIAL":
|
if bpy.context.scene.unit_settings.system == "IMPERIAL":
|
||||||
diagram_scales_enum = [
|
diagram_scales_enum = [
|
||||||
("CUSTOM", "Custom", ""),
|
("CUSTOM", "Custom", ""),
|
||||||
("1'=1'-0\"|1/1", "1'=1'-0\"", ""),
|
("1'=1'-0\"|1/1", "1'=1'-0\"", ""),
|
||||||
|
|||||||
@@ -106,8 +106,7 @@ class BIM_PT_camera(Panel):
|
|||||||
row.operator("bim.activate_drawing_style")
|
row.operator("bim.activate_drawing_style")
|
||||||
|
|
||||||
row = layout.row(align=True)
|
row = layout.row(align=True)
|
||||||
row.operator("bim.cut_section", text="Create Drawing")
|
row.operator("bim.create_drawing", text="Create Drawing")
|
||||||
row.operator("bim.create_drawing", text="Create Drawing 2.0")
|
|
||||||
op = row.operator("bim.open_view", icon="URL", text="")
|
op = row.operator("bim.open_view", icon="URL", text="")
|
||||||
op.view = context.active_object.name.split("/")[1]
|
op.view = context.active_object.name.split("/")[1]
|
||||||
|
|
||||||
|
|||||||
@@ -24,7 +24,7 @@ class BIM_PT_groups(Panel):
|
|||||||
row.label(text="{} Groups Found".format(len(Data.groups)), icon="OUTLINER")
|
row.label(text="{} Groups Found".format(len(Data.groups)), icon="OUTLINER")
|
||||||
if self.props.is_editing:
|
if self.props.is_editing:
|
||||||
row.operator("bim.add_group", text="", icon="ADD")
|
row.operator("bim.add_group", text="", icon="ADD")
|
||||||
row.operator("bim.disable_group_editing_ui", text="", icon="CHECKMARK")
|
row.operator("bim.disable_group_editing_ui", text="", icon="CANCEL")
|
||||||
else:
|
else:
|
||||||
row.operator("bim.load_groups", text="", icon="GREASEPENCIL")
|
row.operator("bim.load_groups", text="", icon="GREASEPENCIL")
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user