From 05070c3758ac39e99a66214ceb7fb10edacc9aba Mon Sep 17 00:00:00 2001 From: Carlos Villagrasa Date: Thu, 29 Sep 2022 02:00:39 +0200 Subject: [PATCH] Construction Types - Attempt to solve repeated object creation (#2450) * Constr types dicts to Blender props * Reduce update interval * Base for not linking dummy asset objects to collections --- .../blenderbim/bim/module/model/__init__.py | 5 +- .../blenderbim/bim/module/model/data.py | 72 +++++++++---------- .../blenderbim/bim/module/model/mep.py | 19 ++--- .../blenderbim/bim/module/model/product.py | 35 ++++----- .../blenderbim/bim/module/model/profile.py | 18 ++--- .../blenderbim/bim/module/model/prop.py | 58 +++++++++------ .../blenderbim/bim/module/model/root.py | 5 ++ .../blenderbim/bim/module/model/slab.py | 23 +++--- .../blenderbim/bim/module/model/ui.py | 9 ++- .../blenderbim/bim/module/model/wall.py | 23 +++--- 10 files changed, 143 insertions(+), 124 deletions(-) diff --git a/src/blenderbim/blenderbim/bim/module/model/__init__.py b/src/blenderbim/blenderbim/bim/module/model/__init__.py index 9238e7abeb..f16f9a42ad 100644 --- a/src/blenderbim/blenderbim/bim/module/model/__init__.py +++ b/src/blenderbim/blenderbim/bim/module/model/__init__.py @@ -47,8 +47,9 @@ classes = ( slab.EnableEditingSketchExtrusionProfile, slab.ResetVertex, slab.SetArcIndex, - prop.BIMModelProperties, prop.ConstrTypeInfo, + prop.ConstrClassInfo, + prop.BIMModelProperties, ui.BIM_PT_authoring, ui.DisplayConstrTypesUI, ui.HelpConstrTypes, @@ -69,7 +70,6 @@ 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.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) @@ -87,7 +87,6 @@ def unregister(): if not bpy.app.background: bpy.utils.unregister_tool(workspace.BimTool) del bpy.types.Scene.BIMModelProperties - 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 1ab42e2533..5dc751ef8c 100644 --- a/src/blenderbim/blenderbim/bim/module/model/data.py +++ b/src/blenderbim/blenderbim/bim/module/model/data.py @@ -20,10 +20,7 @@ import functools import bpy import blenderbim.tool as tool from blenderbim.bim.ifc import IfcStore - - -preview_icon_ids = {} -attempts = 0 +from blenderbim.bim.module.model.root import ConstrTypeEntityNotFound def refresh(): @@ -43,7 +40,6 @@ class AuthoringData: cls.load_ifc_classes() cls.load_relating_types() cls.load_relating_types_browser() - cls.load_preview_constr_types() @classmethod def load_ifc_classes(cls): @@ -57,10 +53,6 @@ class AuthoringData: def load_relating_types_browser(cls): cls.data["relating_types_ids_browser"] = cls.relating_types_browser() - @classmethod - def load_preview_constr_types(cls): - cls.data["preview_constr_types"] = preview_icon_ids - @classmethod def ifc_classes(cls): results = [] @@ -97,11 +89,11 @@ class AuthoringData: def relating_types_browser(cls): return cls.relating_types(ifc_class=cls.props.ifc_class_browser) - @staticmethod - def new_relating_type_info(ifc_class): - relating_type_info = bpy.context.scene.ConstrTypeInfo.add() - relating_type_info.name = ifc_class - return relating_type_info + @classmethod + def new_constr_class_info(cls, ifc_class): + if ifc_class not in cls.props.constr_classes: + cls.props.constr_classes.add().name = ifc_class + return cls.props.constr_classes[ifc_class] @classmethod def assetize_constr_class(cls, ifc_class=None): @@ -109,21 +101,19 @@ class AuthoringData: selected_relating_type_id = cls.props.relating_type_id if ifc_class is None: ifc_class = cls.props.ifc_class_browser - relating_type_info = cls.relating_type_info(ifc_class) - _ = cls.new_relating_type_info(ifc_class) if relating_type_info is None else relating_type_info + if cls.constr_class_info(ifc_class) is None: + cls.new_constr_class_info(ifc_class) constr_class_occurrences = cls.constr_class_entities(ifc_class) - preview_constr_types = cls.data["preview_constr_types"] - for constr_class_entity in constr_class_occurrences: + constr_classes = cls.props.constr_classes - ### handle asset regeneration when library entity is updated ¿? + for constr_class_entity in constr_class_occurrences: if ( - ifc_class not in preview_constr_types - or str(constr_class_entity.id()) not in preview_constr_types[ifc_class] + ifc_class not in constr_classes + or constr_class_entity.Name not in constr_classes[ifc_class].constr_types ): obj = tool.Ifc.get_object(constr_class_entity) cls.assetize_object(obj, ifc_class, constr_class_entity) - relating_type_info = cls.relating_type_info(ifc_class) - relating_type_info.fully_loaded = True + cls.constr_class_info(ifc_class).fully_loaded = True cls.props.updating = True cls.props.ifc_class = selected_ifc_class cls.props.relating_type_id = selected_relating_type_id @@ -144,21 +134,25 @@ class AuthoringData: obj.asset_mark() obj.asset_generate_preview() - def wait_for_asset_previews_generation(check_interval_seconds=0.001): + def wait_for_asset_previews_generation(check_interval_seconds=0.0001): if bpy.app.is_job_running("RENDER_PREVIEW"): return check_interval_seconds else: - icon_id = obj.preview.icon_id - if ifc_class not in cls.data["preview_constr_types"]: - cls.data["preview_constr_types"][ifc_class] = {} - cls.data["preview_constr_types"][ifc_class][str(relating_type_id)] = {"icon_id": icon_id, "object": obj} + if ifc_class not in cls.props.constr_classes: + cls.props.constr_classes.add().name = ifc_class + constr_class_info = cls.props.constr_classes[ifc_class] + # relating_type = cls.relating_type_name_by_id(ifc_class, relating_type_id) + if str(relating_type_id) not in constr_class_info.constr_types: + constr_class_info.constr_types.add().name = str(relating_type_id) + relating_type_info = constr_class_info.constr_types[str(relating_type_id)] + relating_type_info.object = obj + relating_type_info.icon_id = obj.preview.icon_id + if to_be_deleted: element = tool.Ifc.get_entity(obj) if element: tool.Ifc.delete(element) tool.Ifc.unlink(obj=obj) - # We do not delete the object from the scene, as that breaks Blender's asset system. - # Instead, we only "hide" it by unlinking it from all collections. for collection in obj.users_collection: collection.objects.unlink(obj) return None @@ -174,31 +168,29 @@ class AuthoringData: entity for entity in constr_class_occurrences if entity.id() == int(relating_type_id) ] if len(constr_class_occurrences) == 0: - return False + raise ConstrTypeEntityNotFound() constr_class_entity = constr_class_occurrences[0] - obj = tool.Ifc.get_object(constr_class_entity) - if obj is None: - return False + if (obj := tool.Ifc.get_object(constr_class_entity)) is None: + raise ConstrTypeEntityNotFound() cls.assetize_object(obj, ifc_class, constr_class_entity, from_selection=True) - return True @staticmethod - def relating_type_info(ifc_class): - relating_type_infos = [element for element in bpy.context.scene.ConstrTypeInfo if element.name == ifc_class] - return None if len(relating_type_infos) == 0 else relating_type_infos[0] + def constr_class_info(ifc_class): + props = bpy.context.scene.BIMModelProperties + return props.constr_classes[ifc_class] if ifc_class in props.constr_classes else None @classmethod def new_relating_type(cls, ifc_class=None, relating_type_id=None): if ifc_class is None: bpy.ops.bim.add_constr_type_instance( - ifc_class=cls.props.ifc_class, relating_type_id=int(cls.props.relating_type_id) + ifc_class=cls.props.ifc_class, relating_type_id=int(cls.props.relating_type_id), link_to_scene=True ) else: cls.props.updating = True cls.props.ifc_class = ifc_class cls.props.relating_type_id = str(relating_type_id) cls.props.updating = False - bpy.ops.bim.add_constr_type_instance() + bpy.ops.bim.add_constr_type_instance(link_to_scene=True) return bpy.context.selected_objects[-1] @staticmethod diff --git a/src/blenderbim/blenderbim/bim/module/model/mep.py b/src/blenderbim/blenderbim/bim/module/model/mep.py index eeeaff9aee..1e6f3019d4 100644 --- a/src/blenderbim/blenderbim/bim/module/model/mep.py +++ b/src/blenderbim/blenderbim/bim/module/model/mep.py @@ -38,7 +38,7 @@ class MepGenerator: def __init__(self, relating_type): self.relating_type = relating_type - def generate(self): + def generate(self, link_to_scene=True): self.file = tool.Ifc.get() self.collection = bpy.context.view_layer.active_layer_collection.collection @@ -55,15 +55,15 @@ class MepGenerator: self.height = dimensions.get("NominalHeight") self.length = 1 - return self.derive_from_cursor() + return self.derive_from_cursor(link_to_scene=link_to_scene) elif self.relating_type.is_a("IfcPipeSegmentType"): pass - def derive_from_cursor(self): + def derive_from_cursor(self, link_to_scene): self.location = bpy.context.scene.cursor.location - return self.create_rectangle_segment() + return self.create_rectangle_segment(link_to_scene) - def create_rectangle_segment(self): + def create_rectangle_segment(self, link_to_scene): verts = [ Vector((-self.width / 2, self.height / 2, 0)), Vector((-self.width / 2, -self.height / 2, 0)), @@ -89,10 +89,11 @@ class MepGenerator: ifc_class = ifc_classes[0] obj = bpy.data.objects.new(tool.Model.generate_occurrence_name(self.relating_type, ifc_class), mesh) - obj.location = self.location - obj.rotation_euler[0] = math.pi / 2 - obj.rotation_euler[2] = math.pi / 2 - self.collection.objects.link(obj) + if link_to_scene: + obj.location = self.location + obj.rotation_euler[0] = math.pi / 2 + obj.rotation_euler[2] = math.pi / 2 + self.collection.objects.link(obj) bpy.ops.bim.assign_class( obj=obj.name, diff --git a/src/blenderbim/blenderbim/bim/module/model/product.py b/src/blenderbim/blenderbim/bim/module/model/product.py index a731d504fa..424539c4c9 100644 --- a/src/blenderbim/blenderbim/bim/module/model/product.py +++ b/src/blenderbim/blenderbim/bim/module/model/product.py @@ -63,6 +63,7 @@ class AddConstrTypeInstance(bpy.types.Operator): ifc_class: bpy.props.StringProperty() relating_type_id: bpy.props.IntProperty() from_invoke: bpy.props.BoolProperty(default=False) + link_to_scene: bpy.props.BoolProperty(default=True) def invoke(self, context, event): return self.execute(context) @@ -88,13 +89,13 @@ class AddConstrTypeInstance(bpy.types.Operator): material = ifcopenshell.util.element.get_material(relating_type) if material and material.is_a("IfcMaterialProfileSet"): - if profile.DumbProfileGenerator(relating_type).generate(): + if profile.DumbProfileGenerator(relating_type).generate(link_to_scene=self.link_to_scene): return {"FINISHED"} elif material and material.is_a("IfcMaterialLayerSet"): - if self.generate_layered_element(ifc_class, relating_type): + if self.generate_layered_element(ifc_class, relating_type, link_to_scene=self.link_to_scene): return {"FINISHED"} if relating_type.is_a("IfcFlowSegmentType") and not relating_type.RepresentationMaps: - if mep.MepGenerator(relating_type).generate(): + if mep.MepGenerator(relating_type).generate(link_to_scene=self.link_to_scene): return {"FINISHED"} building_obj = None @@ -125,15 +126,17 @@ class AddConstrTypeInstance(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.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) + if self.link_to_scene: + 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) - # Update required as core.type.assign_type may change obj.data - bpy.context.view_layer.update() + if self.link_to_scene: + # Update required as core.type.assign_type may change obj.data + bpy.context.view_layer.update() if ( building_obj @@ -145,9 +148,9 @@ class AddConstrTypeInstance(bpy.types.Operator): bpy.ops.bim.add_element_opening( voided_building_element=building_obj.name, filling_building_element=obj.name ) - if instance_class == "IfcDoor": + if instance_class == "IfcDoor" and self.link_to_scene: obj.location[2] = building_obj.location[2] - min([v[2] for v in obj.bound_box]) - else: + elif self.link_to_scene: if collection_obj and collection_obj.BIMObjectProperties.ifc_definition_id: obj.location[2] = collection_obj.location[2] - min([v[2] for v in obj.bound_box]) @@ -168,7 +171,7 @@ class AddConstrTypeInstance(bpy.types.Operator): return {"FINISHED"} @staticmethod - def generate_layered_element(ifc_class, relating_type): + def generate_layered_element(ifc_class, relating_type, link_to_scene=True): layer_set_direction = None parametric = ifcopenshell.util.element.get_psets(relating_type).get("EPset_Parametric") @@ -181,10 +184,10 @@ class AddConstrTypeInstance(bpy.types.Operator): layer_set_direction = "AXIS2" if layer_set_direction == "AXIS3": - if slab.DumbSlabGenerator(relating_type).generate(): + if slab.DumbSlabGenerator(relating_type).generate(link_to_scene=link_to_scene): return True elif layer_set_direction == "AXIS2": - if wall.DumbWallGenerator(relating_type).generate(): + if wall.DumbWallGenerator(relating_type).generate(link_to_scene=link_to_scene): return True else: pass # Dumb block generator? Eh? :) @@ -201,8 +204,8 @@ class DisplayConstrTypes(bpy.types.Operator): AuthoringData.load() props = context.scene.BIMModelProperties ifc_class = props.ifc_class - relating_type_info = AuthoringData.relating_type_info(ifc_class) - if relating_type_info is None or not relating_type_info.fully_loaded: + constr_class_info = AuthoringData.constr_class_info(ifc_class) + if constr_class_info is None or not constr_class_info.fully_loaded: AuthoringData.assetize_constr_class(ifc_class) bpy.ops.bim.display_constr_types_ui("INVOKE_DEFAULT") return {"FINISHED"} diff --git a/src/blenderbim/blenderbim/bim/module/model/profile.py b/src/blenderbim/blenderbim/bim/module/model/profile.py index c85b54453b..c4218af57c 100644 --- a/src/blenderbim/blenderbim/bim/module/model/profile.py +++ b/src/blenderbim/blenderbim/bim/module/model/profile.py @@ -97,7 +97,7 @@ class DumbProfileGenerator: def __init__(self, relating_type): self.relating_type = relating_type - def generate(self): + def generate(self, link_to_scene=True): self.file = IfcStore.get_file() self.unit_scale = ifcopenshell.util.unit.calculate_unit_scale(IfcStore.get_file()) material = ifcopenshell.util.element.get_material(self.relating_type) @@ -114,13 +114,13 @@ class DumbProfileGenerator: self.rotation = 0 self.location = Vector((0, 0, 0)) self.cardinal_point = int(bpy.context.scene.BIMModelProperties.cardinal_point) - return self.derive_from_cursor() + return self.derive_from_cursor(link_to_scene=link_to_scene) - def derive_from_cursor(self): + def derive_from_cursor(self, link_to_scene): self.location = bpy.context.scene.cursor.location - return self.create_profile() + return self.create_profile(link_to_scene) - def create_profile(self): + def create_profile(self, link_to_scene): ifc_classes = ifcopenshell.util.type.get_applicable_entities(self.relating_type.is_a(), self.file.schema) # Standard cases are deprecated, so let's cull them ifc_class = [c for c in ifc_classes if "StandardCase" not in c][0] @@ -128,10 +128,11 @@ class DumbProfileGenerator: mesh = bpy.data.meshes.new("Dummy") obj = bpy.data.objects.new(tool.Model.generate_occurrence_name(self.relating_type, ifc_class), mesh) obj.location = self.location - if self.collection_obj and self.collection_obj.BIMObjectProperties.ifc_definition_id: + if link_to_scene and self.collection_obj and self.collection_obj.BIMObjectProperties.ifc_definition_id: obj.location[2] = self.collection_obj.location[2] bpy.context.view_layer.update() - self.collection.objects.link(obj) + if link_to_scene: + self.collection.objects.link(obj) element = blenderbim.core.root.assign_class( tool.Ifc, @@ -186,7 +187,8 @@ class DumbProfileGenerator: ifcopenshell.api.run("pset.edit_pset", self.file, pset=pset, properties={"Engine": "BlenderBIM.DumbProfile"}) MaterialData.load(self.file) - obj.select_set(True) + if link_to_scene: + obj.select_set(True) return obj diff --git a/src/blenderbim/blenderbim/bim/module/model/prop.py b/src/blenderbim/blenderbim/bim/module/model/prop.py index 3857520c86..a995e3290a 100644 --- a/src/blenderbim/blenderbim/bim/module/model/prop.py +++ b/src/blenderbim/blenderbim/bim/module/model/prop.py @@ -18,6 +18,7 @@ import bpy from blenderbim.bim.module.model.data import AuthoringData +from blenderbim.bim.module.model.root import ConstrTypeEntityNotFound from bpy.types import PropertyGroup @@ -42,14 +43,21 @@ def get_relating_type_browser(self, context): def update_icon_id(self, context, browser=False): ifc_class = self.ifc_class_browser if browser else self.ifc_class relating_type_id = self.relating_type_id_browser if browser else self.relating_type_id - relating_type = AuthoringData.relating_type_name_by_id(ifc_class, relating_type_id) - if ( - ifc_class not in AuthoringData.data["preview_constr_types"] - or relating_type_id not in AuthoringData.data["preview_constr_types"][ifc_class] - ) and relating_type is not None: - if not AuthoringData.assetize_relating_type_from_selection(browser=browser): + # relating_type = AuthoringData.relating_type_name_by_id(ifc_class, relating_type_id) + + if ifc_class not in self.constr_classes or relating_type_id not in self.constr_classes[ifc_class].constr_types: + try: + AuthoringData.assetize_relating_type_from_selection(browser=browser) + except ConstrTypeEntityNotFound: return - self.icon_id = AuthoringData.data["preview_constr_types"][ifc_class][relating_type_id]["icon_id"] + + def set_icon(update_interval_seconds=0.0001): + if ifc_class not in self.constr_classes or relating_type_id not in self.constr_classes[ifc_class].constr_types: + return update_interval_seconds + else: + self.icon_id = self.constr_classes[ifc_class].constr_types[relating_type_id].icon_id + + bpy.app.timers.register(set_icon) def update_ifc_class(self, context): @@ -65,8 +73,9 @@ def update_ifc_class_browser(self, context): if self.updating: return ifc_class = self.ifc_class_browser - relating_type_info = AuthoringData.relating_type_info(ifc_class) - if relating_type_info is None or not relating_type_info.fully_loaded: + constr_class_info = AuthoringData.constr_class_info(ifc_class) + + if constr_class_info is None or not constr_class_info.fully_loaded: AuthoringData.assetize_constr_class(ifc_class) @@ -89,16 +98,32 @@ def update_relating_type_by_name(self, context): self.relating_type_id = relating_type_id +def get_constr_class_info(props, ifc_class): + return props.constr_classes[ifc_class] if ifc_class in props.constr_classes else None + + def update_preview_multiple(self, context): if self.preview_multiple_constr_types: ifc_class = self.ifc_class - relating_type_info = AuthoringData.relating_type_info(ifc_class) - if relating_type_info is None or not relating_type_info.fully_loaded: + constr_class_info = get_constr_class_info(self, ifc_class) + if constr_class_info is None or not constr_class_info.fully_loaded: AuthoringData.assetize_constr_class(ifc_class) else: update_relating_type(self, context) +class ConstrTypeInfo(PropertyGroup): + name: bpy.props.StringProperty(name="Construction type ID") + icon_id: bpy.props.IntProperty(name="Icon ID") + object: bpy.props.PointerProperty(name="Object", type=bpy.types.Object) + + +class ConstrClassInfo(PropertyGroup): + name: bpy.props.StringProperty(name="Construction class") + constr_types: bpy.props.CollectionProperty(type=ConstrTypeInfo) + fully_loaded: bpy.props.BoolProperty(default=False) + + class BIMModelProperties(PropertyGroup): ifc_class: bpy.props.EnumProperty(items=get_ifc_class, name="Construction Class", update=update_ifc_class) ifc_class_browser: bpy.props.EnumProperty( @@ -120,6 +145,7 @@ class BIMModelProperties(PropertyGroup): ) occurrence_name_function: bpy.props.StringProperty(name="Occurrence Name Function") getter_enum = {"ifc_class": get_ifc_class, "relating_type": get_relating_type} + constr_classes: bpy.props.CollectionProperty(type=ConstrClassInfo) extrusion_depth: bpy.props.FloatProperty(default=42.0) cardinal_point: bpy.props.EnumProperty( items=( @@ -148,13 +174,3 @@ class BIMModelProperties(PropertyGroup): default="5", ) length: bpy.props.FloatProperty(default=42.0) - - -def get_relating_type_info(self, context): - return AuthoringData.relating_types(ifc_class=self.name) - - -class ConstrTypeInfo(PropertyGroup): - name: bpy.props.StringProperty(name="Construction class") - relating_type: bpy.props.EnumProperty(name="Construction type", items=get_relating_type_info) - fully_loaded: bpy.props.BoolProperty(default=False) diff --git a/src/blenderbim/blenderbim/bim/module/model/root.py b/src/blenderbim/blenderbim/bim/module/model/root.py index a3a72e6e98..43cdb1432a 100644 --- a/src/blenderbim/blenderbim/bim/module/model/root.py +++ b/src/blenderbim/blenderbim/bim/module/model/root.py @@ -48,3 +48,8 @@ def sync_name(usecase_path, ifc_file, settings): collection.name = new_name obj.name = new_name blenderbim.bim.handler.refresh_ui_data() + + +class ConstrTypeEntityNotFound(Exception): + pass + diff --git a/src/blenderbim/blenderbim/bim/module/model/slab.py b/src/blenderbim/blenderbim/bim/module/model/slab.py index fa45235a5c..9df1752bfa 100644 --- a/src/blenderbim/blenderbim/bim/module/model/slab.py +++ b/src/blenderbim/blenderbim/bim/module/model/slab.py @@ -184,7 +184,7 @@ class DumbSlabGenerator: def __init__(self, relating_type): self.relating_type = relating_type - def generate(self): + def generate(self, link_to_scene=True): self.file = IfcStore.get_file() unit_scale = ifcopenshell.util.unit.calculate_unit_scale(IfcStore.get_file()) thicknesses = [] @@ -204,13 +204,13 @@ class DumbSlabGenerator: self.length = 3 self.rotation = 0 self.location = Vector((0, 0, 0)) - return self.derive_from_cursor() + return self.derive_from_cursor(link_to_scene=link_to_scene) - def derive_from_cursor(self): + def derive_from_cursor(self, link_to_scene): self.location = bpy.context.scene.cursor.location - return self.create_slab() + return self.create_slab(link_to_scene) - def create_slab(self): + def create_slab(self, link_to_scene): verts = [ Vector((0, 0, 0)), Vector((0, self.width, 0)), @@ -232,12 +232,13 @@ class DumbSlabGenerator: modifier.offset = 1 modifier.thickness = self.depth - obj.location = self.location - if self.collection_obj and self.collection_obj.BIMObjectProperties.ifc_definition_id: - obj.location[2] = self.collection_obj.location[2] - self.depth - else: - obj.location[2] -= self.depth - self.collection.objects.link(obj) + if link_to_scene: + obj.location = self.location + if self.collection_obj and self.collection_obj.BIMObjectProperties.ifc_definition_id: + obj.location[2] = self.collection_obj.location[2] - self.depth + else: + obj.location[2] -= self.depth + self.collection.objects.link(obj) bpy.ops.bim.assign_class( obj=obj.name, ifc_class=ifc_class, diff --git a/src/blenderbim/blenderbim/bim/module/model/ui.py b/src/blenderbim/blenderbim/bim/module/model/ui.py index 6f9de18277..2dc5afd4ba 100644 --- a/src/blenderbim/blenderbim/bim/module/model/ui.py +++ b/src/blenderbim/blenderbim/bim/module/model/ui.py @@ -69,11 +69,10 @@ class DisplayConstrTypesUI(Operator): row.label(text=name, icon="FILE_3D") row.alignment = "CENTER" row = box.row() - preview_constr_types = AuthoringData.data["preview_constr_types"] - if ifc_class in preview_constr_types: - preview_ifc_class = preview_constr_types[ifc_class] - if relating_type_id in preview_ifc_class: - icon_id = preview_ifc_class[relating_type_id]["icon_id"] + if ifc_class in props.constr_classes: + constr_class_info = props.constr_classes[ifc_class] + if relating_type_id in constr_class_info.constr_types: + icon_id = constr_class_info.constr_types[relating_type_id].icon_id row.template_icon(icon_value=icon_id, scale=6.0) row = box.row() op = row.operator("bim.add_constr_type_instance", icon="ADD") diff --git a/src/blenderbim/blenderbim/bim/module/model/wall.py b/src/blenderbim/blenderbim/bim/module/model/wall.py index c589dd992d..bea8b3a88c 100644 --- a/src/blenderbim/blenderbim/bim/module/model/wall.py +++ b/src/blenderbim/blenderbim/bim/module/model/wall.py @@ -413,7 +413,7 @@ class DumbWallGenerator: def __init__(self, relating_type): self.relating_type = relating_type - def generate(self): + def generate(self, link_to_scene=True): self.file = IfcStore.get_file() self.layers = get_material_layer_parameters(self.relating_type) if not self.layers["thickness"]: @@ -433,7 +433,7 @@ class DumbWallGenerator: if self.has_sketch(): return # For now return self.derive_from_sketch() - return self.derive_from_cursor() + return self.derive_from_cursor(link_to_scene) def has_sketch(self): return ( @@ -511,7 +511,7 @@ class DumbWallGenerator: def is_near(self, point1, point2): return (point1 - point2).length < 0.1 - def derive_from_cursor(self): + def derive_from_cursor(self, link_to_scene): self.location = bpy.context.scene.cursor.location if self.collection: for sibling_obj in self.collection.objects: @@ -537,18 +537,19 @@ class DumbWallGenerator: normal = (sibling_obj.matrix_world.to_quaternion() @ face.normal).normalized() self.rotation = math.atan2(normal[1], normal[0]) break - return self.create_wall() + return self.create_wall(link_to_scene) - def create_wall(self): + def create_wall(self, link_to_scene): ifc_class = self.get_relating_type_class(self.relating_type) mesh = bpy.data.meshes.new("Dummy") obj = bpy.data.objects.new(tool.Model.generate_occurrence_name(self.relating_type, ifc_class), mesh) - obj.location = self.location - obj.rotation_euler[2] = self.rotation - if self.collection_obj and self.collection_obj.BIMObjectProperties.ifc_definition_id: - obj.location[2] = self.collection_obj.location[2] - bpy.context.view_layer.update() - self.collection.objects.link(obj) + if link_to_scene: + obj.location = self.location + obj.rotation_euler[2] = self.rotation + if self.collection_obj and self.collection_obj.BIMObjectProperties.ifc_definition_id: + obj.location[2] = self.collection_obj.location[2] + bpy.context.view_layer.update() + self.collection.objects.link(obj) element = blenderbim.core.root.assign_class( tool.Ifc,