From 3f24d54e8fb90fb9e51b7ac80663dd73421c8c6c Mon Sep 17 00:00:00 2001 From: carlos Date: Thu, 14 Jul 2022 13:40:57 +0200 Subject: [PATCH] Distinguish bt active and selected constr type + renaming ifc_class -> constr_type --- .../blenderbim/bim/module/model/__init__.py | 8 +- .../blenderbim/bim/module/model/data.py | 169 +++++++++------- .../blenderbim/bim/module/model/product.py | 184 ++++++++---------- .../blenderbim/bim/module/model/prop.py | 118 ++++++----- .../blenderbim/bim/module/model/workspace.py | 37 ++-- 5 files changed, 268 insertions(+), 248 deletions(-) diff --git a/src/blenderbim/blenderbim/bim/module/model/__init__.py b/src/blenderbim/blenderbim/bim/module/model/__init__.py index 3aecc33fc7..2cd8a2c6fe 100644 --- a/src/blenderbim/blenderbim/bim/module/model/__init__.py +++ b/src/blenderbim/blenderbim/bim/module/model/__init__.py @@ -22,7 +22,7 @@ from . import handler, prop, ui, grid, product, wall, slab, stair, opening, pie, classes = ( product.AddEmptyType, product.AddTypeInstance, - product.DisplayIFCTypes, + product.DisplayConstrTypes, product.SelectTypeInstance, product.TypeInstanceHelp, product.AlignProduct, @@ -35,7 +35,7 @@ classes = ( opening.AddElementOpening, profile.ExtendProfile, prop.BIMModelProperties, - prop.IfcTypeInfo, + prop.ConstrTypeInfo, ui.BIM_PT_authoring, grid.BIM_OT_add_object, stair.BIM_OT_add_object, @@ -54,7 +54,7 @@ def register(): if not bpy.app.background: bpy.utils.register_tool(workspace.BimTool, after={"builtin.scale_cage"}, separator=True, group=True) bpy.types.Scene.BIMModelProperties = bpy.props.PointerProperty(type=prop.BIMModelProperties) - bpy.types.Scene.IfcTypeInfo = bpy.props.CollectionProperty(type=prop.IfcTypeInfo) + bpy.types.Scene.ConstrTypeInfo = bpy.props.CollectionProperty(type=prop.ConstrTypeInfo) bpy.types.VIEW3D_MT_mesh_add.append(grid.add_object_button) bpy.types.VIEW3D_MT_mesh_add.append(stair.add_object_button) bpy.types.VIEW3D_MT_mesh_add.append(opening.add_object_button) @@ -72,7 +72,7 @@ def unregister(): if not bpy.app.background: bpy.utils.unregister_tool(workspace.BimTool) del bpy.types.Scene.BIMModelProperties - del bpy.types.Scene.IfcTypeInfo + del bpy.types.Scene.ConstrTypeInfo bpy.app.handlers.load_post.remove(handler.load_post) bpy.types.VIEW3D_MT_mesh_add.remove(grid.add_object_button) bpy.types.VIEW3D_MT_mesh_add.remove(stair.add_object_button) diff --git a/src/blenderbim/blenderbim/bim/module/model/data.py b/src/blenderbim/blenderbim/bim/module/model/data.py index 13dd02d98b..b27d49963f 100644 --- a/src/blenderbim/blenderbim/bim/module/model/data.py +++ b/src/blenderbim/blenderbim/bim/module/model/data.py @@ -31,31 +31,35 @@ def refresh(): class AuthoringData: data = {} is_loaded = False - updating = False @classmethod def load(cls): cls.is_loaded = True if not hasattr(cls, "data"): cls.data = {} - cls.load_ifc_classes() - cls.load_relating_types() - cls.load_preview_ifc_types() + cls.load_constr_classes() + cls.load_constr_types() + cls.load_constr_types_browser() + cls.load_preview_constr_types() @classmethod - def load_ifc_classes(cls): - cls.data["ifc_classes"] = cls.ifc_classes() + def load_constr_classes(cls): + cls.data["constr_classes"] = cls.constr_classes() @classmethod - def load_relating_types(cls): - cls.data["relating_types"] = cls.relating_types() + def load_constr_types(cls): + cls.data["constr_types_ids"] = cls.constr_types() @classmethod - def load_preview_ifc_types(cls): - cls.data["preview_ifc_types"] = preview_icon_ids + def load_constr_types_browser(cls): + cls.data["constr_types_ids_browser"] = cls.constr_types_browser() @classmethod - def ifc_classes(cls): + def load_preview_constr_types(cls): + cls.data["preview_constr_types"] = preview_icon_ids + + @classmethod + def constr_classes(cls): results = [] classes = { e.is_a() @@ -67,102 +71,133 @@ class AuthoringData: return results @classmethod - def ifc_class_entities(cls, ifc_class=None): - ifc_classes = cls.data["ifc_classes"] - if not ifc_classes: + def constr_class_entities(cls, constr_class=None): + constr_classes = cls.data["constr_classes"] + if not constr_classes: return [] results = [] - if ifc_class is None: - ifc_class = bpy.context.scene.BIMModelProperties.ifc_class - if not ifc_class and ifc_classes: - ifc_class = ifc_classes[0][0] - if ifc_class: - elements = sorted(tool.Ifc.get().by_type(ifc_class), key=lambda s: s.Name) + if constr_class is None: + props = bpy.context.scene.BIMModelProperties + constr_class = props.constr_class + if not constr_class and constr_classes: + constr_class = constr_classes[0][0] + if constr_class: + elements = sorted(tool.Ifc.get().by_type(constr_class), key=lambda s: s.Name) results.extend(elements) return results return [] @classmethod - def relating_types(cls, ifc_class=None): - return [(str(e.id()), e.Name, e.Description or "") for e in cls.ifc_class_entities(ifc_class=ifc_class)] + def constr_types(cls, constr_class=None): + return [ + (str(e.id()), e.Name, e.Description or "") for e in cls.constr_class_entities(constr_class=constr_class) + ] + + @classmethod + def constr_types_browser(cls): + props = bpy.context.scene.BIMModelProperties + return cls.constr_types(constr_class=props.constr_class_browser) @staticmethod - def new_ifc_type_info(ifc_class): - ifc_type_info = bpy.context.scene.IfcTypeInfo.add() - ifc_type_info.name = ifc_class - return ifc_type_info + def new_constr_type_info(constr_class): + constr_type_info = bpy.context.scene.ConstrTypeInfo.add() + constr_type_info.name = constr_class + return constr_type_info @classmethod - def assetize_ifc_class(cls, ifc_class=None): - if ifc_class is None: + def assetize_constr_class(cls, constr_class=None): + if constr_class is None: props = bpy.context.scene.BIMModelProperties - ifc_class = props.ifc_class - ifc_type_info = cls.ifc_type_info(ifc_class) - _ = cls.new_ifc_type_info(ifc_class) if ifc_type_info is None else ifc_type_info - ifc_class_occurrences = cls.ifc_class_entities(ifc_class) - for ifc_class_entity in ifc_class_occurrences: - obj = tool.Ifc.get_object(ifc_class_entity) - cls.assetize_object(obj, ifc_class, ifc_class_entity) - ifc_type_info = cls.ifc_type_info(ifc_class) - ifc_type_info.fully_loaded = True + constr_class = props.constr_class + constr_type_info = cls.constr_type_info(constr_class) + _ = cls.new_constr_type_info(constr_class) if constr_type_info is None else constr_type_info + constr_class_occurrences = cls.constr_class_entities(constr_class) + for constr_class_entity in constr_class_occurrences: + preview_constr_types = cls.data["preview_constr_types"] + + ### handle asset regeneration when library entity is updated ¿? + if (constr_class not in preview_constr_types + or str(constr_class_entity.id()) not in preview_constr_types[constr_class]): + obj = tool.Ifc.get_object(constr_class_entity) + cls.assetize_object(obj, constr_class, constr_class_entity) + constr_type_info = cls.constr_type_info(constr_class) + constr_type_info.fully_loaded = True @classmethod - def assetize_object(cls, obj, ifc_class, ifc_class_entity, from_selection=False): - relating_type = ifc_class_entity.Name + def assetize_object(cls, obj, constr_class, constr_class_entity, from_selection=False): + constr_type_id = constr_class_entity.id() to_be_deleted = False if obj.type == 'EMPTY': - kwargs = {} if from_selection else {'ifc_class': ifc_class, 'relating_type_id': ifc_class_entity.id()} - new_obj = cls.new_ifc_type_instance(**kwargs) + kwargs = {} + if not from_selection: + kwargs.update({'constr_class': constr_class, 'constr_type_id': constr_type_id}) + new_obj = cls.new_constr_type_instance(**kwargs) if new_obj is not None: to_be_deleted = True obj = new_obj obj.asset_mark() obj.asset_generate_preview() icon_id = obj.preview.icon_id - if ifc_class not in cls.data["preview_ifc_types"]: - cls.data["preview_ifc_types"][ifc_class] = {} - cls.data["preview_ifc_types"][ifc_class][relating_type] = {"icon_id": icon_id, "object": obj} + if constr_class not in cls.data["preview_constr_types"]: + cls.data["preview_constr_types"][constr_class] = {} + cls.data["preview_constr_types"][constr_class][str(constr_type_id)] = {"icon_id": icon_id, "object": obj} if to_be_deleted: for col in obj.users_collection: col.objects.unlink(obj) @classmethod - def assetize_relating_type_from_selection(cls): + def assetize_constr_type_from_selection(cls): props = bpy.context.scene.BIMModelProperties - ifc_class = props.ifc_class - relating_type_id = props.relating_type - ifc_class_occurrences = cls.ifc_class_entities(ifc_class=ifc_class) - ifc_class_occurrences = [entity for entity in ifc_class_occurrences if entity.id() == int(relating_type_id)] - if len(ifc_class_occurrences) == 0: + constr_class_browser = props.constr_class_browser + constr_type_id_browser = props.constr_type_id_browser + constr_class_occurrences = cls.constr_class_entities(constr_class=constr_class_browser) + constr_class_occurrences = [ + entity for entity in constr_class_occurrences if entity.id() == int(constr_type_id_browser) + ] + if len(constr_class_occurrences) == 0: return False - ifc_class_entity = ifc_class_occurrences[0] - obj = tool.Ifc.get_object(ifc_class_entity) + constr_class_entity = constr_class_occurrences[0] + obj = tool.Ifc.get_object(constr_class_entity) if obj is None: return False - cls.assetize_object(obj, ifc_class, ifc_class_entity, from_selection=True) + cls.assetize_object(obj, constr_class_browser, constr_class_entity, from_selection=True) return True @staticmethod - def ifc_type_info(ifc_class): - ifc_type_infos = [element for element in bpy.context.scene.IfcTypeInfo if element.name == ifc_class] - return None if len(ifc_type_infos) == 0 else ifc_type_infos[0] + def constr_type_info(constr_class): + constr_type_infos = [element for element in bpy.context.scene.ConstrTypeInfo if element.name == constr_class] + return None if len(constr_type_infos) == 0 else constr_type_infos[0] @classmethod - def new_ifc_type_instance(cls, ifc_class=None, relating_type_id=None): - if ifc_class is not None: - cls.updating = True - props = bpy.context.scene.BIMModelProperties - props.ifc_class = ifc_class - props.relating_type = str(relating_type_id) - cls.updating = False - bpy.ops.bim.add_type_instance() + def new_constr_type_instance(cls, constr_class=None, constr_type_id=None): + props = bpy.context.scene.BIMModelProperties + if constr_class is None: + bpy.ops.bim.add_type_instance( + constr_class=props.constr_class_browser, constr_type_id=int(props.constr_type_id_browser) + ) + else: + props.constr_class = constr_class + props.constr_type_id = str(constr_type_id) + bpy.ops.bim.add_type_instance() return bpy.context.selected_objects[-1] @staticmethod - def relating_type_name_by_id(ifc_class, relating_type_id): + def constr_type_name_by_id(constr_class, constr_type_id): file = IfcStore.get_file() try: - ifc_class_entity = file.by_id(int(relating_type_id)) + constr_class_entity = file.by_id(int(constr_type_id)) except (RuntimeError, ValueError): return None - return ifc_class_entity.Name if ifc_class_entity.is_a() == ifc_class else None + return constr_class_entity.Name if constr_class_entity.is_a() == constr_class else None + + @classmethod + def consolidate_constr_type(cls): + props = bpy.context.scene.BIMModelProperties + props.constr_class = props.constr_class_browser + props.constr_type_id = props.constr_type_id_browser + + @classmethod + def setup_constr_type_browser(cls): + props = bpy.context.scene.BIMModelProperties + props.constr_class_browser = props.constr_class + props.constr_type_id_browser = props.constr_type_id diff --git a/src/blenderbim/blenderbim/bim/module/model/product.py b/src/blenderbim/blenderbim/bim/module/model/product.py index 90c7663171..fc5d7ec2aa 100644 --- a/src/blenderbim/blenderbim/bim/module/model/product.py +++ b/src/blenderbim/blenderbim/bim/module/model/product.py @@ -69,8 +69,8 @@ class AddTypeInstance(bpy.types.Operator): bl_label = "Add" bl_options = {"REGISTER", "UNDO"} bl_description = "Add Type Instance to the model" - ifc_class: bpy.props.StringProperty() - relating_type: bpy.props.IntProperty() + constr_class: bpy.props.StringProperty() + constr_type_id: bpy.props.IntProperty() from_invoke: bpy.props.BoolProperty(default=False) def invoke(self, context, event): @@ -83,25 +83,29 @@ class AddTypeInstance(bpy.types.Operator): def _execute(self, context): props = context.scene.BIMModelProperties - ifc_class = self.ifc_class or props.ifc_class - relating_type_id = self.relating_type or props.relating_type + constr_class = self.constr_class or props.constr_class + constr_type_id = self.constr_type_id or props.constr_type_id - if not ifc_class or not relating_type_id: + if not constr_class or not constr_type_id: return {"FINISHED"} + if self.from_invoke: + props.constr_class = self.constr_class + props.constr_type_id = str(self.constr_type_id) + self.file = IfcStore.get_file() - instance_class = ifcopenshell.util.type.get_applicable_entities(ifc_class, self.file.schema)[0] - relating_type = self.file.by_id(int(relating_type_id)) - material = ifcopenshell.util.element.get_material(relating_type) + instance_class = ifcopenshell.util.type.get_applicable_entities(constr_class, self.file.schema)[0] + constr_type = self.file.by_id(int(constr_type_id)) + material = ifcopenshell.util.element.get_material(constr_type) if material and material.is_a("IfcMaterialProfileSet"): - if profile.DumbProfileGenerator(relating_type).generate(): + if profile.DumbProfileGenerator(constr_type).generate(): return {"FINISHED"} elif material and material.is_a("IfcMaterialLayerSet"): - if self.generate_layered_element(ifc_class, relating_type): + if self.generate_layered_element(constr_class, constr_type): return {"FINISHED"} - if relating_type.is_a("IfcFlowSegmentType") and not relating_type.RepresentationMaps: - if mep.MepGenerator(relating_type).generate(): + if constr_type.is_a("IfcFlowSegmentType") and not constr_type.RepresentationMaps: + if mep.MepGenerator(constr_type).generate(): return {"FINISHED"} building_obj = None @@ -130,14 +134,14 @@ class AddTypeInstance(bpy.types.Operator): ] mesh = bpy.data.meshes.new(name="Instance") mesh.from_pydata(verts, edges, faces) - obj = bpy.data.objects.new(tool.Model.generate_occurrence_name(relating_type, instance_class), mesh) + obj = bpy.data.objects.new(tool.Model.generate_occurrence_name(constr_type, instance_class), mesh) obj.location = context.scene.cursor.location collection = context.view_layer.active_layer_collection.collection collection.objects.link(obj) collection_obj = bpy.data.objects.get(collection.name) bpy.ops.bim.assign_class(obj=obj.name, ifc_class=instance_class) element = tool.Ifc.get_entity(obj) - blenderbim.core.type.assign_type(tool.Ifc, tool.Type, element=element, type=relating_type) + blenderbim.core.type.assign_type(tool.Ifc, tool.Type, element=element, type=constr_type) if building_obj: if instance_class in ["IfcWindow", "IfcDoor"]: @@ -152,7 +156,7 @@ class AddTypeInstance(bpy.types.Operator): obj.location[2] = collection_obj.location[2] - min([v[2] for v in obj.bound_box]) unit_scale = ifcopenshell.util.unit.calculate_unit_scale(tool.Ifc.get()) - for port in ifcopenshell.util.system.get_ports(relating_type): + for port in ifcopenshell.util.system.get_ports(constr_type): mat = ifcopenshell.util.placement.get_local_placement(port.ObjectPlacement) mat[0][3] *= unit_scale mat[1][3] *= unit_scale @@ -190,11 +194,11 @@ class AddTypeInstance(bpy.types.Operator): pass # Dumb block generator? Eh? :) -class DisplayIFCTypes(bpy.types.Operator): - bl_idname = "bim.display_ifc_types" - bl_label = "Browse Element Types" +class DisplayConstrTypes(bpy.types.Operator): + bl_idname = "bim.display_constr_types" + bl_label = "Browse Construction Types" bl_options = {"REGISTER", "UNDO"} - bl_description = "Display all possible IFC types for new instances" + bl_description = "Display all available Construction Types to add new instances" def execute(self, context): bpy.ops.object.mode_set(mode="OBJECT") @@ -203,14 +207,15 @@ class DisplayIFCTypes(bpy.types.Operator): def invoke(self, context, event): if not AuthoringData.is_loaded: AuthoringData.load() + AuthoringData.setup_constr_type_browser() props = context.scene.BIMModelProperties if props.unfold_relating_type: - ifc_class = props.ifc_class - ifc_type_info = AuthoringData.ifc_type_info(ifc_class) - if ifc_type_info is None or not ifc_type_info.fully_loaded: - AuthoringData.assetize_ifc_class(ifc_class) + constr_class = props.constr_class_browser + constr_type_info = AuthoringData.constr_type_info(constr_class) + if constr_type_info is None or not constr_type_info.fully_loaded: + AuthoringData.assetize_constr_class(constr_class) else: - prop.update_relating_type(props, context) + prop.update_constr_type(props, context) min_width = 250 width_scaling = 5 ** -1 width = max([min_width, int(width_scaling * context.region.width)]) @@ -219,9 +224,9 @@ class DisplayIFCTypes(bpy.types.Operator): def draw(self, context): props = context.scene.BIMModelProperties if props.unfold_relating_type: - self.draw_by_class(props) + self.draw_by_constr_class(props) else: - self.draw_by_class_and_relating_type(props) + self.draw_by_constr_class_and_type(props) def draw_header(self, props): layout = self.layout @@ -230,16 +235,16 @@ class DisplayIFCTypes(bpy.types.Operator): split = inner_layout.split(align=True, factor=2./3) col1 = split.column(align=True) row = col1.row() - row.prop(data=props, property="unfold_relating_type", text="Preview All Relating Types") + row.prop(data=props, property="unfold_relating_type", text="Preview All Construction Types") col1.row().separator(factor=1) row = col1.row() - row.label(text="Select Element Type:") + row.label(text="Select Construction Type:") col1.row().separator(factor=1.5) enabled = True - if AuthoringData.data["ifc_classes"]: + if AuthoringData.data["constr_classes"]: subsplit = col1.split(factor=1./3) - subsplit.column().row().label(text="IfcElementType:", icon="FILE_VOLUME") - prop_with_search(subsplit.column(), props, "ifc_class", text="") + subsplit.column().row().label(text="Construction Class:", icon="FILE_VOLUME") + prop_with_search(subsplit.column(), props, "constr_class_browser", text="") col1.row().separator() else: enabled = False @@ -250,18 +255,18 @@ class DisplayIFCTypes(bpy.types.Operator): col2.row().separator(factor=1) return {"enabled": enabled, "layout": inner_layout, "col1": col1, "col2": col2} - def draw_by_class(self, props): + def draw_by_constr_class(self, props): header_data = self.draw_header(props) enabled, layout = [header_data[key] for key in ["enabled", "layout"]] - ifc_class = props.ifc_class + constr_class_browser = props.constr_class_browser num_cols = 3 layout.row().separator(factor=0.25) - layout.row().label(text=f"Available {ifc_class}(s):", icon="FILE_3D") + layout.row().label(text="Construction Types:", icon="FILE_3D") layout.row().separator(factor=0.25) flow = layout.grid_flow(row_major=True, columns=num_cols, even_columns=True, even_rows=True, align=True) - relating_types = AuthoringData.relating_types() - num_types = len(relating_types) - for idx, (rt_id, name, desc) in enumerate(relating_types): + constr_types_browser = AuthoringData.constr_types_browser() + num_types = len(constr_types_browser) + for idx, (constr_type_id_browser, name, desc) in enumerate(constr_types_browser): outer_col = flow.column() box = outer_col.box() row = box.row() @@ -269,26 +274,25 @@ class DisplayIFCTypes(bpy.types.Operator): row.alignment = "CENTER" row = box.row() if enabled: - preview_ifc_types = AuthoringData.data["preview_ifc_types"] - if ifc_class in preview_ifc_types: - preview_ifc_class = preview_ifc_types[ifc_class] - if name in preview_ifc_class: - icon_id = preview_ifc_class[name]["icon_id"] + preview_constr_types = AuthoringData.data["preview_constr_types"] + if constr_class_browser in preview_constr_types: + preview_constr_class = preview_constr_types[constr_class_browser] + if constr_type_id_browser in preview_constr_class: + icon_id = preview_constr_class[constr_type_id_browser]["icon_id"] row.template_icon(icon_value=icon_id, scale=6.) - box.row().separator(factor=0.25) + box.row().separator(factor=0.2) row = box.row() split = row.split(factor=0.5) col = split.column() op = col.operator("bim.select_type_instance", icon="RIGHTARROW_THIN") - op.ifc_class = ifc_class - op.relating_type_id = rt_id + op.constr_class = constr_class_browser + op.constr_type_id = constr_type_id_browser col = split.column() op = col.operator("bim.add_type_instance", icon="ADD") op.from_invoke = True - op.ifc_class = ifc_class - if rt_id.isnumeric(): - op.relating_type = int(rt_id) - box.row().separator(factor=0.05) + op.constr_class = constr_class_browser + if constr_type_id_browser.isnumeric(): + op.constr_type_id = int(constr_type_id_browser) factor = 2 if idx + 1 < math.ceil(num_types / num_cols) else 1.5 outer_col.row().separator(factor=factor) last_row_cols = num_types % num_cols @@ -296,14 +300,15 @@ class DisplayIFCTypes(bpy.types.Operator): for _ in range(num_cols - last_row_cols): flow.column() - def draw_by_class_and_relating_type(self, props): + def draw_by_constr_class_and_type(self, props): header_data = self.draw_header(props) enabled, col1, col2 = [header_data[key] for key in ["enabled", "col1", "col2"]] - ifc_class = props.ifc_class - if AuthoringData.data["relating_types"]: + constr_class_browser = props.constr_class_browser + constr_type_id_browser = props.constr_type_id_browser + if AuthoringData.data["constr_types_ids_browser"]: subsplit = col1.split(factor=1. / 3) - subsplit.column().row().label(text=f"{ifc_class}:", icon="FILE_3D") - prop_with_search(subsplit.column(), props, "relating_type", text="") + subsplit.column().row().label(text="Construction Type:", icon="FILE_3D") + prop_with_search(subsplit.column(), props, "constr_type_id_browser", text="") col1.row().separator() else: enabled = False @@ -311,14 +316,13 @@ class DisplayIFCTypes(bpy.types.Operator): row = col1.row() row.enabled = enabled op = row.operator("bim.select_type_instance", icon="RIGHTARROW_THIN") - op.ifc_class = ifc_class - op.relating_type_id = props.relating_type + op.constr_class = constr_class_browser + op.constr_type_id = constr_type_id_browser op = row.operator("bim.add_type_instance", icon="ADD") op.from_invoke = True - op.ifc_class = ifc_class - relating_type = props.relating_type - if relating_type.isnumeric(): - op.relating_type = int(relating_type) + op.constr_class = constr_class_browser + if constr_type_id_browser.isnumeric(): + op.constr_type_id = int(constr_type_id_browser) col2.row().separator(factor=1.25) split = col2.split(factor=0.025) col = [split.column() for _ in range(2)][-1] @@ -333,8 +337,8 @@ class SelectTypeInstance(bpy.types.Operator): bl_label = "Select" bl_options = {"REGISTER", "UNDO"} bl_description = "Pick Type Instance as selection for subsequent operations" - ifc_class: bpy.props.StringProperty() - relating_type_id: bpy.props.StringProperty() + constr_class: bpy.props.StringProperty() + constr_type_id: bpy.props.StringProperty() def invoke(self, context, event): close_operator_panel(event) @@ -342,16 +346,17 @@ class SelectTypeInstance(bpy.types.Operator): def execute(self, context): props = context.scene.BIMModelProperties - if self.ifc_class != "": - props.ifc_class = self.ifc_class - if self.relating_type_id != "": - props.relating_type = self.relating_type_id + if self.constr_class != "": + props.constr_class = self.constr_class + AuthoringData.load_constr_types() + if self.constr_type_id != "": + props.constr_type_id = self.constr_type_id return {"FINISHED"} class TypeInstanceHelp(bpy.types.Operator): bl_idname = "bim.type_instance_help" - bl_label = "Element Types Help" + bl_label = "Construction Types Help" bl_options = {"REGISTER", "UNDO"} bl_description = "Click to read some contextual help" @@ -367,22 +372,13 @@ class TypeInstanceHelp(bpy.types.Operator): row = layout.row() row.alignment = "CENTER" row.label(text="BlenderBIM Help", icon="BLENDER") - row = layout.row() - row.alignment = "CENTER" - row.label(text="[Element Type Browser]") layout.row().separator(factor=0.5) + row = col_with_margins(layout.row()).row() - row.label(text="When to use:", icon="KEYTYPE_MOVING_HOLD_VEC") - self.draw_lines(layout, self.message_purpose) + row.label(text="Overview:", icon="KEYTYPE_MOVING_HOLD_VEC") + self.draw_lines(layout, self.message_summary) layout.row().separator() - row = col_with_margins(layout.row()).row() - row.label(text="Overall workflow:", icon="KEYTYPE_MOVING_HOLD_VEC") - self.draw_lines(layout, self.message_overall) - layout.row().separator() - row = col_with_margins(layout.row()).row() - row.label(text="UI panel hints:", icon="KEYTYPE_MOVING_HOLD_VEC") - self.draw_lines(layout, self.message_ui) - layout.row().separator(factor=1.5) + row = col_with_margins(layout.row()).row() row.label(text="Further support:", icon="KEYTYPE_MOVING_HOLD_VEC") layout.row().separator(factor=0.5) @@ -404,32 +400,10 @@ class TypeInstanceHelp(bpy.types.Operator): row.label(text=f" {line}") @property - def message_purpose(self): + def message_summary(self): return [ - 'Available Element Types can be previewed and added through the button "Browse', - 'Element Types", which appears when an IfcProjectLibrary, containing in turn', - 'IfcElementType entities, is loaded. In order to manage loaded libraries, navigate', - 'to [Scene Properties] -> [IFC Project Setup] -> [IFC Project Library], under the', - 'Properties panel.' - ] - - @property - def message_overall(self): - return [ - 'Choose a certain Element Type by determining:', - ' 1) An existing subtype of IfcElementType.', - ' 2) Its entity name, as stored within the IfcProjectLibrary.', - 'Then, click on the "Add" button to directly add one instance of the chosen type to ', - 'the model, or alternatively click on the "Select" button to be able to later add', - 'several instances with SHIFT + A.' - ] - - @property - def message_ui(self): - return [ - 'If "Preview All Relating Types" is marked, previews for every existing entity of', - 'the selected IFC class will be shown at once. Not advisable on large projects, with', - 'dozens of entities for a given IfcElementType.' + 'The Construction Type Browser allows to preview and add new instances to the model.', + 'For further support, please click on the Documentation link below.' ] diff --git a/src/blenderbim/blenderbim/bim/module/model/prop.py b/src/blenderbim/blenderbim/bim/module/model/prop.py index 0276c6e13e..788aac4d14 100644 --- a/src/blenderbim/blenderbim/bim/module/model/prop.py +++ b/src/blenderbim/blenderbim/bim/module/model/prop.py @@ -17,97 +17,107 @@ # along with BlenderBIM Add-on. If not, see . import bpy -import ifcopenshell.util.type from blenderbim.bim.module.model.data import AuthoringData -from blenderbim.bim.prop import StrProperty, Attribute -from blenderbim.bim.ifc import IfcStore -import blenderbim.tool as tool from bpy.types import PropertyGroup -def get_ifc_class(self, context): +def get_constr_class(self, context): if not AuthoringData.is_loaded: AuthoringData.load() - return AuthoringData.data["ifc_classes"] + return AuthoringData.data["constr_classes"] -def get_relating_type(self, context): +def get_constr_type(self, context): if not AuthoringData.is_loaded: AuthoringData.load() - return AuthoringData.data["relating_types"] + return AuthoringData.data["constr_types_ids"] + + +def get_constr_type_browser(self, context): + if not AuthoringData.is_loaded: + AuthoringData.load() + return AuthoringData.data["constr_types_ids_browser"] def update_icon_id(self, context): - ifc_class = self.ifc_class - relating_type_id = self.relating_type - relating_type = AuthoringData.relating_type_name_by_id(ifc_class, relating_type_id) - if ((ifc_class not in AuthoringData.data["preview_ifc_types"] - or relating_type not in AuthoringData.data["preview_ifc_types"][ifc_class]) - and relating_type is not None): - if not AuthoringData.assetize_relating_type_from_selection(): + constr_class_browser = self.constr_class_browser + constr_type_id_browser = self.constr_type_id_browser + constr_type_browser = AuthoringData.constr_type_name_by_id(constr_class_browser, constr_type_id_browser) + if ((constr_class_browser not in AuthoringData.data["preview_constr_types"] + or constr_type_id_browser not in AuthoringData.data["preview_constr_types"][constr_class_browser]) + and constr_type_browser is not None): + if not AuthoringData.assetize_constr_type_from_selection(): return props = bpy.context.scene.BIMModelProperties - props.icon_id = AuthoringData.data["preview_ifc_types"][ifc_class][relating_type]["icon_id"] + props.icon_id = AuthoringData.data["preview_constr_types"][constr_class_browser][constr_type_id_browser]["icon_id"] -def update_ifc_class(self, context): - if not AuthoringData.updating: - AuthoringData.load_ifc_classes() - AuthoringData.load_relating_types() - props = context.scene.BIMModelProperties - if props.unfold_relating_type: - ifc_class = props.ifc_class - ifc_type_info = AuthoringData.ifc_type_info(ifc_class) - if ifc_type_info is None or not ifc_type_info.fully_loaded: - AuthoringData.assetize_ifc_class(ifc_class) - else: - self.relating_type = AuthoringData.data["relating_types"][0][0] - update_icon_id(self, context) +def update_constr_class(self, context): + AuthoringData.load_constr_classes() + AuthoringData.load_constr_types() + self.constr_type_id = AuthoringData.data["constr_types_ids"][0][0] -def update_relating_type(self, context): - AuthoringData.load_relating_types() +def update_constr_class_browser(self, context): + AuthoringData.load_constr_classes() + AuthoringData.load_constr_types_browser() + props = context.scene.BIMModelProperties + if props.unfold_relating_type: + constr_class_browser = props.constr_class_browser + constr_type_info = AuthoringData.constr_type_info(constr_class_browser) + if constr_type_info is None or not constr_type_info.fully_loaded: + curr_selection = props.constr_class, props.constr_type_id + AuthoringData.assetize_constr_class(constr_class_browser) + props.constr_class, props.constr_type_id = curr_selection + else: + self.constr_type_id_browser = AuthoringData.data["constr_types_ids_browser"][0][0] + + +def update_constr_type(self, context): + AuthoringData.load_constr_types() + + +def update_constr_type_browser(self, context): + AuthoringData.load_constr_types_browser() update_icon_id(self, context) -def update_unfold_relating_type(self, context): - update_ifc_class(self, context) - - # if self.unfold_relating_type: - # props = context.scene.BIMModelProperties - # ifc_class = props.ifc_class - # ifc_type_info = AuthoringData.ifc_type_info(ifc_class) - # if ifc_type_info is None or not ifc_type_info.fully_loaded: - # AuthoringData.assetize_ifc_class(ifc_class) - # else: - # update_ifc_class(self, context) +def update_unfold_constr_type(self, context): + update_constr_class_browser(self, context) class BIMModelProperties(PropertyGroup): - ifc_class: bpy.props.EnumProperty(items=get_ifc_class, name="IFC Class", update=update_ifc_class) - relating_type: bpy.props.EnumProperty(items=get_relating_type, name="Relating Type", update=update_relating_type) + constr_class: bpy.props.EnumProperty(items=get_constr_class, name="Construction Class", update=update_constr_class) + constr_class_browser: bpy.props.EnumProperty( + items=get_constr_class, name="Construction Class", update=update_constr_class_browser + ) + constr_type_id: bpy.props.EnumProperty( + items=get_constr_type, name="Construction Type", update=update_constr_type + ) + constr_type_id_browser: bpy.props.EnumProperty( + items=get_constr_type_browser, name="Construction Type", update=update_constr_type_browser + ) icon_id: bpy.props.IntProperty() - unfold_relating_type: bpy.props.BoolProperty(update=update_unfold_relating_type) + unfold_relating_type: bpy.props.BoolProperty(update=update_unfold_constr_type) occurrence_name_style: bpy.props.EnumProperty( items=[("CLASS", "By Class", ""), ("TYPE", "By Type", ""), ("CUSTOM", "Custom", "")], name="Occurrence Name Style", ) occurrence_name_function: bpy.props.StringProperty(name="Occurrence Name Function") getter_enum = { - "ifc_class": get_ifc_class, - "relating_type": get_relating_type + "constr_class_browser": get_constr_class, + "constr_type_browser": get_constr_type_browser } -def get_ifc_type_info_relating_types(self, context): - ifc_class = self.name - return AuthoringData.relating_types(ifc_class=ifc_class) +def get_constr_type_info(self, context): + return AuthoringData.relating_types(constr_class=self.name) -class IfcTypeInfo(PropertyGroup): - name: bpy.props.StringProperty(name="IFC class", description="IFC class") - relating_type: bpy.props.EnumProperty( - name="Relating type", description="Relating type", items=get_ifc_type_info_relating_types +class ConstrTypeInfo(PropertyGroup): + name: bpy.props.StringProperty(name="Construction class") + constr_type: bpy.props.EnumProperty( + name="Construction type", items=get_constr_type_info ) fully_loaded: bpy.props.BoolProperty(default=False) diff --git a/src/blenderbim/blenderbim/bim/module/model/workspace.py b/src/blenderbim/blenderbim/bim/module/model/workspace.py index 003ea26aa3..1531dad146 100644 --- a/src/blenderbim/blenderbim/bim/module/model/workspace.py +++ b/src/blenderbim/blenderbim/bim/module/model/workspace.py @@ -57,53 +57,54 @@ class BimTool(WorkSpaceTool): props = context.scene.BIMModelProperties is_tool_header = context.region.type == "TOOL_HEADER" - ifc_classes = AuthoringData.data["ifc_classes"] - relating_types = AuthoringData.data["relating_types"] - row = layout.row(align=True) if not IfcStore.get_file(): row.label(text="No IFC Project", icon="ERROR") return + constr_classes = AuthoringData.data["constr_classes"] + constr_types_ids = AuthoringData.data["constr_types_ids"] + if is_tool_header: row.operator("bim.type_instance_help", text="", icon="QUESTION") - if ifc_classes and is_tool_header: + if constr_classes and is_tool_header: row.label(text="", icon="BLANK1") - row.operator("bim.display_ifc_types", icon="COLLAPSEMENU") + row.operator("bim.display_constr_types", icon="COLLAPSEMENU") - ifc_class = props.ifc_class - relating_type = AuthoringData.relating_type_name_by_id(ifc_class, props.relating_type) + constr_class = props.constr_class + constr_type_id = props.constr_type_id + constr_type = AuthoringData.constr_type_name_by_id(constr_class, constr_type_id) if is_tool_header: row.label(text="", icon="BLANK1") row = layout.row(align=True) row.label(text="", icon="EVENT_SHIFT") row.label(text="", icon="EVENT_A") - if ifc_classes: + if constr_classes: row.label(text=f" Add") row.label(text="", icon="FILE_VOLUME") - row.label(text=ifc_class) + row.label(text=constr_class) row.label(text="", icon="FILE_3D") - row.label(text=f"{relating_type} ") + row.label(text=f"{constr_type} ") else: row.label(text=f" Add instance") else: - txt_ifc_class = ifc_class if ifc_classes else "No IFC Class" - txt_relating_type = relating_type if relating_types else "No Relating Type" + txt_constr_class = constr_class if constr_classes else "No Construction Class" + txt_constr_type = constr_type if constr_types_ids else "No Construction Type" row = layout.row(align=True) - row.label(text="Selected IFC Type:") + row.label(text="Selected Construction Type:") row = layout.row(align=True) - row.label(text=txt_ifc_class, icon="FILE_VOLUME") + row.label(text=txt_constr_class, icon="FILE_VOLUME") row = layout.row(align=True) - row.label(text=txt_relating_type, icon="FILE_3D") + row.label(text=txt_constr_type, icon="FILE_3D") row = layout.row(align=True) row.label(text="", icon="EVENT_SHIFT") row.label(text="", icon="EVENT_A") row.label(text=f" Add Type Instance") - if AuthoringData.data["ifc_classes"]: - if props.ifc_class == "IfcWallType": + if AuthoringData.data["constr_classes"]: + if constr_class == "IfcWallType": row = layout.row() row.label(text="Join") row = layout.row(align=True) @@ -125,7 +126,7 @@ class BimTool(WorkSpaceTool): row.label(text="", icon="EVENT_SHIFT") row.label(text="Split", icon="EVENT_S") - if props.ifc_class in ("IfcColumnType", "IfcBeamType", "IfcMemberType"): + if constr_class in ("IfcColumnType", "IfcBeamType", "IfcMemberType"): row = layout.row() row.label(text="Join") row = layout.row(align=True)