From a1cbf9a055df94446bc7dde2e580b69d1abae23c Mon Sep 17 00:00:00 2001 From: Kristoffer Date: Sun, 8 Nov 2020 13:52:20 +0100 Subject: [PATCH] minor improvements in ui,export and operator --- .../blenderbim/bim/__init__.py | 1 + .../blenderbim/bim/export_ifc.py | 105 ++++++++++-------- .../blenderbim/bim/operator.py | 50 ++++++--- src/ifcblenderexport/blenderbim/bim/prop.py | 4 +- src/ifcblenderexport/blenderbim/bim/ui.py | 26 +++-- 5 files changed, 114 insertions(+), 72 deletions(-) diff --git a/src/ifcblenderexport/blenderbim/bim/__init__.py b/src/ifcblenderexport/blenderbim/bim/__init__.py index b696551ffb..7998d73aaa 100644 --- a/src/ifcblenderexport/blenderbim/bim/__init__.py +++ b/src/ifcblenderexport/blenderbim/bim/__init__.py @@ -206,6 +206,7 @@ if bpy is not None: operator.AddPresentationLayer, operator.AddToPresentationLayer, operator.RemovePresentationLayer, + operator.UpdatePresentationLayer, operator.AddDrawingStyleAttribute, operator.RemoveDrawingStyleAttribute, operator.CopyPropertyToSelection, diff --git a/src/ifcblenderexport/blenderbim/bim/export_ifc.py b/src/ifcblenderexport/blenderbim/bim/export_ifc.py index e6086060a3..8ad5f9a3d2 100644 --- a/src/ifcblenderexport/blenderbim/bim/export_ifc.py +++ b/src/ifcblenderexport/blenderbim/bim/export_ifc.py @@ -404,7 +404,7 @@ class IfcParser: ) if obj.instance_type == "COLLECTION" and self.is_a_rel_aggregates( - self.get_ifc_class(obj.instance_collection.name) + self.get_ifc_class(obj.instance_collection.name) ): self.rel_aggregates[self.product_index] = obj.name @@ -434,7 +434,7 @@ class IfcParser: elif obj.BIMObjectProperties.material_type == "IfcMaterialLayerSet": self.rel_associates_material_layer_set[self.product_index] = obj.BIMObjectProperties.material_set elif obj.BIMObjectProperties.material_type == "IfcMaterialProfileSet": - pass # TODO + pass # TODO return product @@ -981,12 +981,10 @@ class IfcParser: for representation in self.representations.values(): if representation["presentation_layer"]: pl = representation["presentation_layer"] - print('Presentation load: ', pl.name) - defaults = [[], pl.description, pl.identifier, pl.layer_on, pl.layer_frozen, pl.layer_blocked, - pl.layer_styles] - self.presentation_layer_assignments.setdefault(pl.name, defaults)[0].append( - representation - ) + if pl.name == '': + continue + print("Presentation load: ", pl.name) + self.presentation_layer_assignments.setdefault(pl.name, []).append(representation) def load_representations(self): if not self.ifc_export_settings.has_representations: @@ -1003,9 +1001,9 @@ class IfcParser: def prevent_data_name_duplicates(self, product): if ( - product["raw"].data - and bpy.data.meshes.get(product["raw"].data.name) - and bpy.data.curves.get(product["raw"].data.name) + product["raw"].data + and bpy.data.meshes.get(product["raw"].data.name) + and bpy.data.curves.get(product["raw"].data.name) ): product["raw"].data.name += "~" @@ -1078,8 +1076,7 @@ class IfcParser: "Model/Box/MODEL_VIEW/{}".format(mesh_name.split("/")[3]) ] = self.get_representation(obj.data, obj, "Model", "Box", "MODEL_VIEW") elif ( - context_prefix == "Model/Body/MODEL_VIEW" and obj.data and not self.is_mesh_context_sensitive( - obj.data.name) + context_prefix == "Model/Body/MODEL_VIEW" and obj.data and not self.is_mesh_context_sensitive(obj.data.name) ): self.append_default_representation(obj) elif context_prefix == "Model/Body/MODEL_VIEW" and self.is_point_cloud(obj): @@ -1119,9 +1116,7 @@ class IfcParser: "is_native": mesh.BIMMeshProperties.is_native if hasattr(mesh, "BIMMeshProperties") else False, "is_swept_solid": mesh.BIMMeshProperties.is_swept_solid if hasattr(mesh, "BIMMeshProperties") else False, "is_generated": False, - "presentation_layer": mesh.BIMMeshProperties.presentation_layer - if hasattr(mesh, "BIMMeshProperties") - else None, + "presentation_layer": obj.BIMObjectProperties.presentation_layer if hasattr(obj, "BIMObjectProperties") else None, "attributes": {"Name": mesh.name}, } @@ -1250,15 +1245,15 @@ class IfcParser: return children for reference, element in enumerate(self.spatial_structure_elements): if ( # A convention is established that spatial elements may be - # an object placed in a collection of the same name - element["raw"].name == element["raw"].users_collection[0].name - and element["raw"].users_collection[0].name - in [c.name for c in bpy.data.collections[parent["raw"].name].children] + # an object placed in a collection of the same name + element["raw"].name == element["raw"].users_collection[0].name + and element["raw"].users_collection[0].name + in [c.name for c in bpy.data.collections[parent["raw"].name].children] ) or ( # We allow finer grain spatial elements such as IfcSpace to - # break the convention to prevent collection overload in Blender - element["raw"].name != element["raw"].users_collection[0].name - and element["raw"].users_collection[0].name - in [o.name for o in bpy.data.collections[parent["raw"].name].objects] + # break the convention to prevent collection overload in Blender + element["raw"].name != element["raw"].users_collection[0].name + and element["raw"].users_collection[0].name + in [o.name for o in bpy.data.collections[parent["raw"].name].objects] ): children.append({"reference": reference, "children": self.get_spatial_structure_elements_tree(element)}) return children @@ -1316,7 +1311,7 @@ class IfcParser: def is_a_type(self, class_name): return (class_name[0:3] == "Ifc" and class_name[-4:] == "Type") or ( - class_name[0:3] == "Ifc" and class_name[-5:] == "Style" + class_name[0:3] == "Ifc" and class_name[-5:] == "Style" ) @@ -1393,10 +1388,10 @@ class IfcExporter: self.file.wrapped_data.header.file_name.name = os.path.basename(self.ifc_export_settings.output_file) self.file.wrapped_data.header.file_name.time_stamp = ( datetime.datetime.utcnow() - .replace(tzinfo=datetime.timezone.utc) - .astimezone() - .replace(microsecond=0) - .isoformat() + .replace(tzinfo=datetime.timezone.utc) + .astimezone() + .replace(microsecond=0) + .isoformat() ) self.file.wrapped_data.header.file_name.preprocessor_version = "IfcOpenShell {}".format(ifcopenshell.version) self.file.wrapped_data.header.file_name.originating_system = "{} {}".format( @@ -1420,10 +1415,10 @@ class IfcExporter: [ str(x) for x in [ - addon.bl_info.get("version", (-1, -1, -1)) - for addon in addon_utils.modules() - if addon.bl_info["name"] == "BlenderBIM" - ][0] + addon.bl_info.get("version", (-1, -1, -1)) + for addon in addon_utils.modules() + if addon.bl_info["name"] == "BlenderBIM" + ][0] ] ) @@ -1618,8 +1613,8 @@ class IfcExporter: def create_document_references(self): for reference in self.ifc_parser.document_references.values(): if ( - reference["referenced_document"] - and reference["referenced_document"] in self.ifc_parser.document_information + reference["referenced_document"] + and reference["referenced_document"] in self.ifc_parser.document_information ): reference["attributes"]["ReferencedDocument"] = self.ifc_parser.document_information[ reference["referenced_document"] @@ -2028,12 +2023,26 @@ class IfcExporter: return self.file.createIfcStyledItem(representation_item, [surface_style], item["attributes"]["Name"]) def create_presentation_layer_assignments(self): - for name, props in self.ifc_parser.presentation_layer_assignments.items(): - assigned_items, description, identifier, layer_on, layer_frozen, layer_blocked, layer_styles = props - print('Presentation Export: ', name, assigned_items) - self.file.createIfcPresentationLayerAssignment( - name, description, [i["ifc"].MappedRepresentation for i in assigned_items], identifier - ) + scene_props = bpy.context.scene.BIMProperties + for name, assigned_items in self.ifc_parser.presentation_layer_assignments.items(): + if name == '': + continue + pl = scene_props.presentation_layers[name] + print("Presentation Export: ", name, pl.identifier, pl.layer_on) + + with_style = False + if pl.layer_on is False: + with_style = True + + if with_style is False: + self.file.createIfcPresentationLayerAssignment( + name, pl.description, [i["ifc"].MappedRepresentation for i in assigned_items], pl.identifier + ) + else: + self.file.createIfcPresentationLayerWithStyle( + name, pl.description, [i["ifc"].MappedRepresentation for i in assigned_items], pl.identifier, + pl.layer_on, pl.layer_frozen, pl.layer_blocked, pl.layer_styles + ) def create_materials(self): for material in self.ifc_parser.materials.values(): @@ -2108,9 +2117,9 @@ class IfcExporter: def get_rendering_attributes(self, material): if ( - not material.use_nodes - or not hasattr(material.node_tree, "nodes") - or "Principled BSDF" not in material.node_tree.nodes + not material.use_nodes + or not hasattr(material.node_tree, "nodes") + or "Principled BSDF" not in material.node_tree.nodes ): return {} bsdf = material.node_tree.nodes["Principled BSDF"] @@ -3223,7 +3232,10 @@ class IfcExporter: return results def relate_spaces_to_boundary_elements(self): - for (relating_space_index, relationships,) in self.ifc_parser.rel_space_boundaries.items(): + for ( + relating_space_index, + relationships, + ) in self.ifc_parser.rel_space_boundaries.items(): for relationship in relationships: relationship["attributes"]["GlobalId"] = ifcopenshell.guid.new() relationship["attributes"]["RelatedBuildingElement"] = self.ifc_parser.products[ @@ -3337,8 +3349,7 @@ class IfcExporter: tmp_file = os.path.join(unzipped_path, tmp_name) self.file.write(tmp_file) with zipfile.ZipFile( - self.ifc_export_settings.output_file, mode="w", compression=zipfile.ZIP_DEFLATED, - compresslevel=9 + self.ifc_export_settings.output_file, mode="w", compression=zipfile.ZIP_DEFLATED, compresslevel=9 ) as zf: zf.write(tmp_file) elif extension == "ifc": diff --git a/src/ifcblenderexport/blenderbim/bim/operator.py b/src/ifcblenderexport/blenderbim/bim/operator.py index d5c924320b..04394361a5 100644 --- a/src/ifcblenderexport/blenderbim/bim/operator.py +++ b/src/ifcblenderexport/blenderbim/bim/operator.py @@ -4288,8 +4288,9 @@ class AddToPresentationLayer(bpy.types.Operator): def execute(self, context): name = bpy.context.scene.BIMProperties.presentation_layers[self.index].name bpy.context.active_object.BIMObjectProperties.presentation_layer.name = name - - print(f'Adding "{self.index} - {name}" to "{bpy.context.scene.BIMProperties.name}"') + bpy.context.active_object.BIMObjectProperties.presentation_layer.name = name + elem_name = bpy.context.active_object.BIMObjectProperties.attributes["Name"].string_value + print(f'Adding "({self.index} - {name})" to "{elem_name}"') return {"FINISHED"} @@ -4298,21 +4299,16 @@ class AddPresentationLayer(bpy.types.Operator): bl_idname = "bim.add_presentation_layer" bl_label = "Add Presentation Layer" - _name = 'New Presentation Layer' - descript = 'A Description' - identifier = 'Something' - layer_on = True - layer_frozen = False - layer_blocked = False - def execute(self, context): new = bpy.context.scene.BIMProperties.presentation_layers.add() - new.name = self._name - new.description = self.descript - new.identifier = self.identifier - new.layer_on = self.layer_on - new.layer_frozen = self.layer_frozen - new.layer_blocked = self.layer_blocked + + # Default values of a new presentation layer + new.name = "New Presentation Layer" + new.description = "A Description" + new.identifier = "Something" + new.layer_on = True + new.layer_frozen = False + new.layer_blocked = False return {"FINISHED"} @@ -4322,11 +4318,35 @@ class RemovePresentationLayer(bpy.types.Operator): bl_label = "Remove Presentation Layer" index: bpy.props.IntProperty() + def execute(self, context): bpy.context.scene.BIMProperties.presentation_layers.remove(self.index) return {"FINISHED"} +class UpdatePresentationLayer(bpy.types.Operator): + bl_idname = "bim.update_presentation_layer" + bl_label = "Update Presentation Layer" + index: bpy.props.IntProperty() + pl_name = bpy.props.StringProperty() + pl_description = bpy.props.StringProperty() + pl_identifier = bpy.props.StringProperty() + pl_layer_on = bpy.props.BoolProperty() + pl_layer_frozen = bpy.props.BoolProperty() + pl_layer_blocked = bpy.props.BoolProperty() + + def execute(self, context): + pl = bpy.context.scene.BIMProperties.presentation_layers[self.index] + pl.name = self.pl_name + pl.description = self.pl_description + pl.identifier = self.pl_identifier + pl.layer_on = self.pl_layer_on + pl.layer_frozen = self.pl_layer_frozen + pl.layer_blocked = self.pl_layer_blocked + + return {"FINISHED"} + + class AddDrawingStyleAttribute(bpy.types.Operator): bl_idname = "bim.add_drawing_style_attribute" bl_label = "Add Drawing Style Attribute" diff --git a/src/ifcblenderexport/blenderbim/bim/prop.py b/src/ifcblenderexport/blenderbim/bim/prop.py index 7c4096a1e6..932b1041de 100644 --- a/src/ifcblenderexport/blenderbim/bim/prop.py +++ b/src/ifcblenderexport/blenderbim/bim/prop.py @@ -799,8 +799,8 @@ class PresentationLayer(PropertyGroup): description: StringProperty(name="Description") identifier: StringProperty(name="Identifier") layer_on: BoolProperty(name="LayerOn", default=True) - layer_frozen: BoolProperty(name="LayerFrozen") - layer_blocked: BoolProperty(name="LayerBlocked") + layer_frozen: BoolProperty(name="LayerFrozen", default=False) + layer_blocked: BoolProperty(name="LayerBlocked", default=False) layer_styles: EnumProperty(items=[], name="LayerStyles") diff --git a/src/ifcblenderexport/blenderbim/bim/ui.py b/src/ifcblenderexport/blenderbim/bim/ui.py index 90ddfb31d8..e69490b3e6 100644 --- a/src/ifcblenderexport/blenderbim/bim/ui.py +++ b/src/ifcblenderexport/blenderbim/bim/ui.py @@ -788,7 +788,7 @@ class BIM_PT_presentation_layer_data(Panel): elem_props = context.active_object.data.BIMMeshProperties.presentation_layer scene_props = context.scene.BIMProperties - if elem_props.name != '': + if elem_props.name != "": layout.row(align=True).prop(elem_props, "name") layout.row().prop(elem_props, "description") layout.row().prop(elem_props, "identifier") @@ -797,11 +797,17 @@ class BIM_PT_presentation_layer_data(Panel): layout.row().prop(elem_props, "layer_blocked") layout.row().prop(elem_props, "layer_styles") else: - layout.label(text='Not included in any presentation layer') + layout.label(text="Not included in any presentation layer") if scene_props.presentation_layers: - layout.template_list("BIM_UL_presentation_layers", "", scene_props, "presentation_layers", scene_props, - "active_presentation_layer_index") + layout.template_list( + "BIM_UL_presentation_layers", + "", + scene_props, + "presentation_layers", + scene_props, + "active_presentation_layer_index", + ) pres_layer = scene_props.presentation_layers[scene_props.active_presentation_layer_index] if pres_layer.name in bpy.context.scene.BIMProperties.presentation_layers: op = layout.row().operator("bim.add_to_presentation_layer") @@ -950,8 +956,9 @@ class BIM_PT_presentation_layers(Panel): layout.row().operator("bim.add_presentation_layer") if props.presentation_layers: - layout.template_list("BIM_UL_presentation_layers", "", props, "presentation_layers", props, - "active_presentation_layer_index") + layout.template_list( + "BIM_UL_presentation_layers", "", props, "presentation_layers", props, "active_presentation_layer_index" + ) pres_layer = props.presentation_layers[props.active_presentation_layer_index] row = layout.row(align=True) @@ -963,8 +970,6 @@ class BIM_PT_presentation_layers(Panel): ).index = props.active_presentation_layer_index row = layout.row() row.prop(pres_layer, "description") - # row = layout.row() - # row.prop(pres_layer, "assigned_items") row = layout.row() row.prop(pres_layer, "identifier") row = layout.row() @@ -975,6 +980,11 @@ class BIM_PT_presentation_layers(Panel): row.prop(pres_layer, "layer_blocked") row = layout.row() row.prop(pres_layer, "layer_styles") + + op = layout.row().operator("bim.update_presentation_layer") + op.index = props.active_presentation_layer_index + op.pl_name = pres_layer.name + op.pl_description = pres_layer.description else: layout.label(text="Presentation Layer is invalid")