diff --git a/src/blenderbim/blenderbim/bim/data/pset/EPset_Drawing.ifc b/src/blenderbim/blenderbim/bim/data/pset/EPset_Drawing.ifc new file mode 100644 index 0000000000..49a45176d1 --- /dev/null +++ b/src/blenderbim/blenderbim/bim/data/pset/EPset_Drawing.ifc @@ -0,0 +1,16 @@ +ISO-10303-21; +HEADER; +FILE_DESCRIPTION((),'2;1'); +FILE_NAME('EPset_Drawing.ifc','2020-01-01T00:00:00',(),(),'EPset_Drawing','EPset_Drawing',$); +FILE_SCHEMA(('IFC4')); +ENDSEC; +DATA; +#1=IFCPROPERTYSETTEMPLATE('2JhNIvqZrFnAgxfhK0XVQX',$,'EPset_Drawing','',.PSET_OCCURRENCEDRIVEN.,'IfcAnnotation',(#2,#3,#4,#5,#6,#7)); +#2=IFCSIMPLEPROPERTYTEMPLATE('23JavTMk98ZxXhrUEnjAcf',$,'TargetView','',.P_SINGLEVALUE.,'IfcLabel',$,$,$,$,$,.READWRITE.); +#3=IFCSIMPLEPROPERTYTEMPLATE('1yVWUt5H9DAOuu0OaMMLpe',$,'Scale','',.P_SINGLEVALUE.,'IfcLabel',$,$,$,$,$,.READWRITE.); +#4=IFCSIMPLEPROPERTYTEMPLATE('3gsuPBtU93b8f0gg1pjkq6',$,'HumanScale','',.P_SINGLEVALUE.,'IfcLabel',$,$,$,$,$,.READWRITE.); +#5=IFCSIMPLEPROPERTYTEMPLATE('0AK5C2UpL4$eaac2LszAx$',$,'HasUnderlay','',.P_SINGLEVALUE.,'IfcBoolean',$,$,$,$,$,.READWRITE.); +#6=IFCSIMPLEPROPERTYTEMPLATE('2j2ZEZR8X5tONm7kli5hM6',$,'HasLinework','',.P_SINGLEVALUE.,'IfcBoolean',$,$,$,$,$,.READWRITE.); +#7=IFCSIMPLEPROPERTYTEMPLATE('1ttChRysH9UuEX2FeMj5Hu',$,'HasAnnotation','',.P_SINGLEVALUE.,'IfcBoolean',$,$,$,$,$,.READWRITE.); +ENDSEC; +END-ISO-10303-21; diff --git a/src/blenderbim/blenderbim/bim/data/styles/default.css b/src/blenderbim/blenderbim/bim/data/styles/default.css index 4495940bd8..2a5aadf779 100644 --- a/src/blenderbim/blenderbim/bim/data/styles/default.css +++ b/src/blenderbim/blenderbim/bim/data/styles/default.css @@ -23,10 +23,19 @@ text { fill: black; stroke: none; } .cut { fill: black; stroke: black; stroke-linecap: 'round'; stroke-width: 0.35; fill-rule: evenodd; } .projection { fill: white; 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; } .solid {} -.leader { marker-end: url(#leader-marker); } -.stair { marker-start: url(#stair-marker-start); marker-end: url(#stair-marker-end); } +.IfcAnnotation { fill: none; stroke: black; stroke-linecap: 'round'; stroke-width: 0.25; } +.PredefinedType-MISC { fill: red; stroke: blue; stroke-width: 1; } +.PredefinedType-GRID { marker-start: url(#grid-marker); marker-end: url(#grid-marker); } +.PredefinedType-SECTIONLEVEL { marker-start: url(#section-level-marker); stroke-dasharray: 12.5, 3, 3, 3; } +.PredefinedType-PLANLEVEL { marker-end: url(#plan-level-marker); } +.PredefinedType-DIMENSION { marker-start: url(#dimension-marker-start); marker-end: url(#dimension-marker-end); } +.PredefinedType-HIDDENLINE { stroke-dasharray: 3, 2; } +.PredefinedType-STAIR { marker-start: url(#stair-marker-start); marker-end: url(#stair-marker-end); } +.PredefinedType-BOUNDARY { fill: none; stroke: red; stroke-width: 1; stroke-dasharray: 12, 4, 3, 4, 3, 4; } +.PredefinedType-TEXT { fill: black; stroke: none; } +path.PredefinedType-TEXTLEADER { marker-end: url(#leader-marker); } +text.PredefinedType-TEXTLEADER { fill: black; stroke: none; } .break { fill: white; } .breakline { fill: none; stroke: black; stroke-linecap: 'round'; stroke-width: 0.25; marker-mid: url(#breakline-marker); } .material-blank { fill: white; } @@ -44,5 +53,4 @@ text { fill: black; stroke: none; } .material-honeycomb { fill: url(#honeycomb); } .material-sand { fill: url(#sand); } .material-concrete { fill: url(#concrete); stroke-width: 0.5; } -.material-boundary { fill: none; stroke: red; stroke-width: 1; stroke-dasharray: 12,4,3,4,3,4; } .IfcSpace { fill: none; stroke: none; } diff --git a/src/blenderbim/blenderbim/bim/handler.py b/src/blenderbim/blenderbim/bim/handler.py index 9f615158ab..1f208585bf 100644 --- a/src/blenderbim/blenderbim/bim/handler.py +++ b/src/blenderbim/blenderbim/bim/handler.py @@ -157,12 +157,12 @@ def loadIfcStore(scene): if not IfcStore.get_file(): return IfcStore.get_schema() - IfcStore.reload_linked_elements() + IfcStore.relink_all_objects() @persistent def undo_pre(scene): - IfcStore.update_undo_redo_stack_objects() + IfcStore.track_undo_redo_stack_object_map() @persistent @@ -171,13 +171,13 @@ def undo_post(scene): IfcStore.last_transaction = bpy.context.scene.BIMProperties.last_transaction IfcStore.undo() purge_module_data() - IfcStore.update_undo_redo_stack_objects() - IfcStore.reload_linked_elements(objects=[bpy.data.objects.get(o) for o in IfcStore.undo_redo_stack_objects]) + IfcStore.track_undo_redo_stack_selected_objects() + IfcStore.reload_undo_redo_stack_objects() @persistent def redo_pre(scene): - IfcStore.update_undo_redo_stack_objects() + IfcStore.track_undo_redo_stack_object_map() @persistent @@ -186,8 +186,8 @@ def redo_post(scene): IfcStore.last_transaction = bpy.context.scene.BIMProperties.last_transaction IfcStore.redo() purge_module_data() - IfcStore.update_undo_redo_stack_objects() - IfcStore.reload_linked_elements(objects=[bpy.data.objects.get(o) for o in IfcStore.undo_redo_stack_objects]) + IfcStore.track_undo_redo_stack_selected_objects() + IfcStore.reload_undo_redo_stack_objects() @persistent diff --git a/src/blenderbim/blenderbim/bim/ifc.py b/src/blenderbim/blenderbim/bim/ifc.py index f5be2ea01f..e4b86ede7f 100644 --- a/src/blenderbim/blenderbim/bim/ifc.py +++ b/src/blenderbim/blenderbim/bim/ifc.py @@ -43,6 +43,7 @@ class IfcStore: library_file = None element_listeners = set() undo_redo_stack_objects = set() + undo_redo_stack_object_names = {} current_transaction = "" last_transaction = "" history = [] @@ -147,14 +148,32 @@ class IfcStore: IfcStore.element_listeners.add(callback) @staticmethod - def update_undo_redo_stack_objects(): + def track_undo_redo_stack_object_map(): + """Keeps track of currently mapped object names, typically during undo and redo + + When any Blender object is stored outside a Blender PointerProperty, such as + in a regular Python list, there is the likely probability that the object + will be invalidated when undo or redo occurs. Object invalidation seems to + occur whenever an object is affected during an operation. + + For example, if an operator deletes a modifier on o1, then o1 will be invalidated. + """ + for key, value in IfcStore.id_map.items(): + try: + IfcStore.undo_redo_stack_object_names[key] = value.name + except: + continue + + @staticmethod + def track_undo_redo_stack_selected_objects(): """Keeps track of selected object names, typically during undo and redo When any Blender object is stored outside a Blender PointerProperty, such as in a regular Python list, there is the likely probability that the object will be invalidated when undo or redo occurs. Object invalidation seems to - only occur for selected objects either pre/post undo/redo event, including - selected objects for consecutive undo/redos, and all children. + occur for selected objects either pre/post undo/redo event, including + selected objects for consecutive undo/redos, and all children. This is + important because selected objects are often deleted from the scene. So if I first select o1, then o2, then o3, then press undo, o3 will be invalidated. If instead I press undo twice, o3 and o2 will be invalidated. @@ -169,14 +188,23 @@ class IfcStore: IfcStore.undo_redo_stack_objects |= objects @staticmethod - def reload_linked_elements(objects=None): + def reload_undo_redo_stack_objects(): + """Reloads any invalidated objects after undo or redo + + After an undo or redo operation, objects may have been invalidated in + our id_map and guid_map. Invalidated objects are typically those that + have been manipulated or deleted. This checks the cache of mapped and + selected objects prior to the operation and ensures that if the object + is invalidated, they are reloaded based on the object name that was + tracked prior to the undo / redo. + """ file = IfcStore.get_file() if not file: return - if objects is None: - objects = bpy.data.objects - for obj in objects: + # First, reload objects that were selected or active + for name in IfcStore.undo_redo_stack_objects: + obj = bpy.data.objects.get(name) if not obj: continue if not obj.BIMObjectProperties.ifc_definition_id: @@ -187,6 +215,38 @@ class IfcStore: data["guid"] = element.GlobalId IfcStore.commit_link_element(data) + # Scan for any straggling invalidated objects which were indirectly affected and reload them too. + for key, value in IfcStore.id_map.items(): + try: + value.name + except: + obj = bpy.data.objects.get(IfcStore.undo_redo_stack_object_names[key]) + if not obj or not obj.BIMObjectProperties.ifc_definition_id: + continue + element = file.by_id(obj.BIMObjectProperties.ifc_definition_id) + data = {"id": element.id(), "obj": obj.name} + if hasattr(element, "GlobalId"): + data["guid"] = element.GlobalId + IfcStore.commit_link_element(data) + + + @staticmethod + def relink_all_objects(): + file = IfcStore.get_file() + if not file: + return + for obj in bpy.data.objects: + if not obj: + continue + if not obj.BIMObjectProperties.ifc_definition_id: + continue + element = file.by_id(obj.BIMObjectProperties.ifc_definition_id) + data = {"id": element.id(), "obj": obj.name} + if hasattr(element, "GlobalId"): + data["guid"] = element.GlobalId + IfcStore.commit_link_element(data) + + @staticmethod def delete_element(element): IfcStore.deleted_ids.add(element.id()) @@ -312,6 +372,7 @@ class IfcStore: @staticmethod def begin_transaction(operator): IfcStore.undo_redo_stack_objects = set() + IfcStore.undo_redo_stack_object_names = {} IfcStore.current_transaction = str(uuid.uuid4()) operator.transaction_key = IfcStore.current_transaction diff --git a/src/blenderbim/blenderbim/bim/import_ifc.py b/src/blenderbim/blenderbim/bim/import_ifc.py index 31563eaa9f..cb41036dd8 100644 --- a/src/blenderbim/blenderbim/bim/import_ifc.py +++ b/src/blenderbim/blenderbim/bim/import_ifc.py @@ -1682,6 +1682,12 @@ class IfcImporter: else: camera.BIMCameraProperties.diagram_scale = "CUSTOM" camera.BIMCameraProperties.custom_diagram_scale = pset["Scale"] + if "HasUnderlay" in pset: + camera.BIMCameraProperties.has_underlay = pset["HasUnderlay"] + if "HasLinework" in pset: + camera.BIMCameraProperties.has_linework = pset["HasLinework"] + if "HasAnnotation" in pset: + camera.BIMCameraProperties.has_annotation = pset["HasAnnotation"] return camera def create_curve(self, element, shape): diff --git a/src/blenderbim/blenderbim/bim/module/drawing/operator.py b/src/blenderbim/blenderbim/bim/module/drawing/operator.py index aeadfaff80..940afb575f 100644 --- a/src/blenderbim/blenderbim/bim/module/drawing/operator.py +++ b/src/blenderbim/blenderbim/bim/module/drawing/operator.py @@ -119,9 +119,10 @@ class CreateDrawing(bpy.types.Operator): start = time.time() self.profile_code("Start drawing generation process") self.props = context.scene.DocProperties + self.cprops = self.camera.data.BIMCameraProperties self.drawing_name = self.file.by_id(self.camera.BIMObjectProperties.ifc_definition_id).Name self.get_scale() - if self.camera.data.BIMCameraProperties.update_representation(self.camera): + if self.cprops.update_representation(self.camera): bpy.ops.bim.update_representation(obj=self.camera.name, ifc_representation_class="") underlay_svg = self.generate_underlay(context) self.profile_code("Generate underlay") @@ -186,12 +187,12 @@ class CreateDrawing(bpy.types.Operator): return svg_path def generate_underlay(self, context): - if not self.props.has_underlay: + if not self.cprops.has_underlay: return svg_path = os.path.join(context.scene.BIMProperties.data_dir, "cache", self.drawing_name + "-underlay.svg") context.scene.render.filepath = svg_path[0:-4] + ".png" drawing_style = context.scene.DocProperties.drawing_styles[ - self.camera.data.BIMCameraProperties.active_drawing_style_index + self.cprops.active_drawing_style_index ] if drawing_style.render_type == "DEFAULT": @@ -246,7 +247,7 @@ class CreateDrawing(bpy.types.Operator): return svg_path def generate_linework(self, context): - if not self.props.has_linework: + if not self.cprops.has_linework: return svg_path = os.path.join(context.scene.BIMProperties.data_dir, "cache", self.drawing_name + "-linework.svg") if os.path.isfile(svg_path) and self.props.should_use_linework_cache: @@ -410,7 +411,7 @@ class CreateDrawing(bpy.types.Operator): return re.sub("[^0-9a-zA-Z]+", "", name) def generate_annotation(self, context): - if not self.props.has_annotation: + if not self.cprops.has_annotation: return svg_path = os.path.join(context.scene.BIMProperties.data_dir, "cache", self.drawing_name + "-annotation.svg") if os.path.isfile(svg_path) and self.props.should_use_annotation_cache: @@ -420,7 +421,7 @@ class CreateDrawing(bpy.types.Operator): svg_writer = svgwriter.SvgWriter() drawing_style = context.scene.DocProperties.drawing_styles[ - camera.data.BIMCameraProperties.active_drawing_style_index + self.cprops.active_drawing_style_index ] render = context.scene.render @@ -473,7 +474,7 @@ class CreateDrawing(bpy.types.Operator): svg_writer.annotations["section_level_obj"] = obj elif element.ObjectType == "TEXT": svg_writer.annotations.setdefault("text_objs", []).append(obj) - elif element.ObjectType == "MISC": + else: svg_writer.annotations.setdefault("misc_objs", []).append(obj) svg_writer.annotations["attributes"] = [a.name for a in drawing_style.attributes] diff --git a/src/blenderbim/blenderbim/bim/module/drawing/prop.py b/src/blenderbim/blenderbim/bim/module/drawing/prop.py index c56e6b9262..a959f4e7a5 100644 --- a/src/blenderbim/blenderbim/bim/module/drawing/prop.py +++ b/src/blenderbim/blenderbim/bim/module/drawing/prop.py @@ -153,6 +153,30 @@ def update_drawing_name(self, context): core.update_drawing_name(tool.Ifc, tool.Drawing, drawing=drawing, name=self.name) +def update_has_underlay(self, context): + update_layer(self, context, "HasUnderlay", self.has_underlay) + + +def update_has_linework(self, context): + update_layer(self, context, "HasLinework", self.has_linework) + + +def update_has_annotation(self, context): + update_layer(self, context, "HasAnnotation", self.has_annotation) + + +def update_layer(self, context, name, value): + element = tool.Ifc.get_entity(context.active_object) + if not element: + return + pset = ifcopenshell.util.element.get_psets(element).get("EPset_Drawing") + if pset: + pset = tool.Ifc.get().by_id(pset["id"]) + else: + pset = ifcopenshell.api.run("pset.add_pset", tool.Ifc.get(), product=element, name="EPset_Drawing") + ifcopenshell.api.run("pset.edit_pset", tool.Ifc.get(), pset=pset, properties={name: value}) + + def getTitleblocks(self, context): global titleblocks_enum if len(titleblocks_enum) < 1: @@ -276,9 +300,6 @@ class RasterStyleProperty(enum.Enum): class DocProperties(PropertyGroup): - has_underlay: BoolProperty(name="Underlay", default=False) - has_linework: BoolProperty(name="Linework", default=True) - has_annotation: BoolProperty(name="Annotation", default=True) should_use_underlay_cache: BoolProperty(name="Use Underlay Cache", default=False) should_use_linework_cache: BoolProperty(name="Use Linework Cache", default=False) should_use_annotation_cache: BoolProperty(name="Use Annotation Cache", default=False) @@ -320,6 +341,9 @@ class DocProperties(PropertyGroup): class BIMCameraProperties(PropertyGroup): + has_underlay: BoolProperty(name="Underlay", default=False, update=update_has_underlay) + has_linework: BoolProperty(name="Linework", default=True, update=update_has_linework) + has_annotation: BoolProperty(name="Annotation", default=True, update=update_has_annotation) representation: StringProperty(name="Representation") view_name: StringProperty(name="View Name") diagram_scale: EnumProperty(items=get_diagram_scales, name="Drawing Scale", update=update_diagram_scale) diff --git a/src/blenderbim/blenderbim/bim/module/drawing/svgwriter.py b/src/blenderbim/blenderbim/bim/module/drawing/svgwriter.py index b7e3b80a6e..b6e3407daf 100644 --- a/src/blenderbim/blenderbim/bim/module/drawing/svgwriter.py +++ b/src/blenderbim/blenderbim/bim/module/drawing/svgwriter.py @@ -24,6 +24,7 @@ import pystache import xml.etree.ElementTree as ET import svgwrite import ifcopenshell +import ifcopenshell.util.element import ifcopenshell.util.representation import blenderbim.tool as tool import blenderbim.bim.module.drawing.helper as helper @@ -153,8 +154,8 @@ class SvgWriter: for grid_obj in self.annotations.get("grid_objs", []): matrix_world = grid_obj.matrix_world + classes = self.get_attribute_classes(grid_obj) for edge in grid_obj.data.edges: - classes = ["annotation", "grid"] v0_global = matrix_world @ grid_obj.data.vertices[edge.vertices[0]].co.xyz v1_global = matrix_world @ grid_obj.data.vertices[edge.vertices[1]].co.xyz v0 = self.project_point_onto_camera(v0_global) @@ -167,8 +168,6 @@ class SvgWriter: start=tuple(start * self.scale), end=tuple(end * self.scale), class_=" ".join(classes) ) ) - line["marker-start"] = "url(#grid-marker)" - line["marker-end"] = "url(#grid-marker)" line["stroke-dasharray"] = "12.5, 3, 3, 3" axis_tag = tool.Ifc.get_entity(grid_obj).Name self.svg.add( @@ -201,13 +200,13 @@ class SvgWriter: self.draw_ifc_annotation() for obj in self.annotations.get("misc_objs", []): - self.draw_misc_annotation(obj, ["IfcAnnotation"]) + self.draw_misc_annotation(obj) for obj_data in self.annotations.get("hidden_objs", []): - self.draw_line_annotation(obj_data, ["hidden"]) + self.draw_line_annotation(obj_data) for obj_data in self.annotations.get("solid_objs", []): - self.draw_line_annotation(obj_data, ["solid"]) + self.draw_line_annotation(obj_data) self.draw_leader_annotations() @@ -216,8 +215,8 @@ class SvgWriter: if self.annotations.get("section_level_obj"): matrix_world = self.annotations["section_level_obj"].matrix_world + classes = self.get_attribute_classes(self.annotations["section_level_obj"]) for spline in self.annotations["section_level_obj"].data.splines: - classes = ["annotation", "section-level"] points = self.get_spline_points(spline) projected_points = [self.project_point_onto_camera(matrix_world @ p.co.xyz) for p in points] d = " ".join( @@ -228,8 +227,6 @@ class SvgWriter: ) d = "M{}".format(d[1:]) path = self.svg.add(self.svg.path(d=d, class_=" ".join(classes))) - path["marker-start"] = "url(#section-level-marker)" - path["stroke-dasharray"] = "12.5, 3, 3, 3" text_position = Vector( ( (x_offset + projected_points[0].x) * self.scale, @@ -258,8 +255,8 @@ class SvgWriter: if self.annotations.get("stair_obj"): matrix_world = self.annotations["stair_obj"].matrix_world + classes = self.get_attribute_classes(self.annotations["stair_obj"]) for spline in self.annotations["stair_obj"].data.splines: - classes = ["annotation", "stair"] points = self.get_spline_points(spline) projected_points = [self.project_point_onto_camera(matrix_world @ p.co.xyz) for p in points] d = " ".join( @@ -316,13 +313,13 @@ class SvgWriter: ) ) - def draw_misc_annotation(self, obj, classes): + def draw_misc_annotation(self, obj): # We have to decide whether this should come from Blender or from IFC. # For the moment, for convenience of experimenting with ideas, it comes # from Blender. In the future, it should probably come from IFC. if not isinstance(obj.data, bpy.types.Mesh): return - classes.extend(self.get_attribute_classes(obj)) + classes = self.get_attribute_classes(obj) if len(obj.data.polygons) == 0: self.draw_edge_annotation(obj, classes) return @@ -332,6 +329,7 @@ class SvgWriter: for polygon in obj.data.polygons: points = [obj.data.vertices[v] for v in polygon.vertices] projected_points = [self.project_point_onto_camera(matrix_world @ p.co.xyz) for p in points] + projected_points.append(projected_points[0]) d = " ".join( [ "L {} {}".format((x_offset + p.x) * self.scale, (y_offset - p.y) * self.scale) @@ -342,12 +340,12 @@ class SvgWriter: path = self.svg.add(self.svg.path(d=d, class_=" ".join(classes))) def get_attribute_classes(self, obj): - classes = [obj.name.split("/")[0]] - for slot in obj.material_slots: - if slot.material: - classes.append("material-{}".format(re.sub("[^0-9a-zA-Z]+", "", slot.material.name))) - global_id = IfcStore.get_file().by_id(obj.BIMObjectProperties.ifc_definition_id).GlobalId - classes.append("globalid-{}".format(global_id)) + element = tool.Ifc.get_entity(obj) + global_id = "GlobalId-{}".format(element.GlobalId) + predefined_type = "PredefinedType-" + self.canonicalise_class_name( + str(ifcopenshell.util.element.get_predefined_type(element)) + ) + classes = [global_id, element.is_a(), predefined_type] for attribute in self.annotations.get("attributes", []): result = self.get_obj_value(obj, attribute) if result: @@ -356,6 +354,9 @@ class SvgWriter: ) return classes + def canonicalise_class_name(self, name): + return re.sub("[^0-9a-zA-Z]+", "", name) + def get_obj_value(self, obj, key): # This is a duplicate implementation of the IFC selector key in Blender # In the future if all this becomes purely IFC based this can be deleted @@ -381,14 +382,14 @@ class SvgWriter: if result: return result.string_value - def draw_line_annotation(self, obj_data, classes): + def draw_line_annotation(self, obj_data): # TODO: properly scope these offsets x_offset = self.raw_width / 2 y_offset = self.raw_height / 2 obj, data = obj_data - classes.extend(["annotation"]) + classes = self.get_attribute_classes(obj) matrix_world = obj.matrix_world if isinstance(data, bpy.types.Curve): @@ -424,7 +425,7 @@ class SvgWriter: def draw_leader_annotations(self): for obj in self.annotations.get("leader_objs", []): - self.draw_line_annotation((obj, obj.data), ["leader"]) + self.draw_line_annotation((obj, obj.data)) spline = obj.data.splines[0] spline_points = spline.bezier_points if spline.bezier_points else spline.points if spline_points: @@ -437,7 +438,7 @@ class SvgWriter: x_offset = self.raw_width / 2 y_offset = self.raw_height / 2 - self.draw_line_annotation((obj, obj.data), ["solid"]) + self.draw_line_annotation((obj, obj.data)) v1 = self.project_point_onto_camera(obj.matrix_world @ Vector((0, 0, 0))) v2 = self.project_point_onto_camera(obj.matrix_world @ Vector((0, 0, -1))) @@ -632,8 +633,8 @@ class SvgWriter: x_offset = self.raw_width / 2 y_offset = self.raw_height / 2 matrix_world = obj.matrix_world + classes = self.get_attribute_classes(obj) for spline in obj.data.splines: - classes = ["annotation", "plan-level"] points = self.get_spline_points(spline) projected_points = [self.project_point_onto_camera(matrix_world @ p.co.xyz) for p in points] d = " ".join( @@ -644,7 +645,6 @@ class SvgWriter: ) d = "M{}".format(d[1:]) path = self.svg.add(self.svg.path(d=d, class_=" ".join(classes))) - path["marker-end"] = "url(#plan-level-marker)" text_position = Vector( ( (x_offset + projected_points[0].x) * self.scale, @@ -676,6 +676,7 @@ class SvgWriter: ) def draw_dimension_annotations(self, dimension_obj, text_override=None): + classes = self.get_attribute_classes(dimension_obj) matrix_world = dimension_obj.matrix_world for spline in dimension_obj.data.splines: points = self.get_spline_points(spline) @@ -684,7 +685,7 @@ class SvgWriter: continue v0_global = matrix_world @ points[i].co.xyz v1_global = matrix_world @ points[i + 1].co.xyz - self.draw_dimension_annotation(v0_global, v1_global, text_override) + self.draw_dimension_annotation(v0_global, v1_global, classes, text_override) def draw_measureit_arch_dimension_annotations(self): try: @@ -694,10 +695,11 @@ class SvgWriter: except: return for coord in coords: - self.draw_dimension_annotation(Vector(coord[0]), Vector(coord[1])) + self.draw_dimension_annotation( + Vector(coord[0]), Vector(coord[1]), ["IfcAnnotation", "PredefinedType-DIMENSION"] + ) - def draw_dimension_annotation(self, v0_global, v1_global, text_override=None): - classes = ["annotation", "dimension"] + def draw_dimension_annotation(self, v0_global, v1_global, classes, text_override=None): x_offset = self.raw_width / 2 y_offset = self.raw_height / 2 v0 = self.project_point_onto_camera(v0_global) @@ -719,8 +721,6 @@ class SvgWriter: line = self.svg.add( self.svg.line(start=tuple(start * self.scale), end=tuple(end * self.scale), class_=" ".join(classes)) ) - line["marker-start"] = "url(#dimension-marker-start)" - line["marker-end"] = "url(#dimension-marker-end)" if text_override is not None: text = text_override else: diff --git a/src/blenderbim/blenderbim/bim/module/drawing/ui.py b/src/blenderbim/blenderbim/bim/module/drawing/ui.py index 55cc14b092..e21b9d6006 100644 --- a/src/blenderbim/blenderbim/bim/module/drawing/ui.py +++ b/src/blenderbim/blenderbim/bim/module/drawing/ui.py @@ -47,13 +47,13 @@ class BIM_PT_camera(Panel): col = layout.column(align=True) row = col.row(align=True) - row.prop(dprops, "has_underlay", icon="OUTLINER_OB_IMAGE") + row.prop(props, "has_underlay", icon="OUTLINER_OB_IMAGE") row.prop(dprops, "should_use_underlay_cache", text="", icon="FILE_REFRESH") row = col.row(align=True) - row.prop(dprops, "has_linework", icon="IMAGE_DATA") + row.prop(props, "has_linework", icon="IMAGE_DATA") row.prop(dprops, "should_use_linework_cache", text="", icon="FILE_REFRESH") row = col.row(align=True) - row.prop(dprops, "has_annotation", icon="MOD_EDGESPLIT") + row.prop(props, "has_annotation", icon="MOD_EDGESPLIT") row.prop(dprops, "should_use_annotation_cache", text="", icon="FILE_REFRESH") row = layout.row()