From fcc2b9ee13e0505c617b306fe5e29890855ced5e Mon Sep 17 00:00:00 2001 From: Dion Moult Date: Thu, 7 Jan 2021 10:47:50 +1100 Subject: [PATCH] WIP migrate types to partial editing. See #1222. --- .../blenderbim/bim/__init__.py | 6 +- .../blenderbim/bim/export_ifc.py | 16 --- src/ifcblenderexport/blenderbim/bim/ifc.py | 9 ++ .../blenderbim/bim/import_ifc.py | 8 -- .../bim/module/aggregate/operator.py | 5 +- .../blenderbim/bim/module/attribute/data.py | 3 +- .../blenderbim/bim/module/root/operator.py | 7 +- .../bim/module/spatial/assign_container.py | 2 +- .../blenderbim/bim/module/type/__init__.py | 19 ++++ .../blenderbim/bim/module/type/assign_type.py | 51 ++++++++++ .../blenderbim/bim/module/type/data.py | 27 ++++++ .../bim/module/type/get_related_objects.py | 32 ++++++ .../blenderbim/bim/module/type/operator.py | 97 +++++++++++++++++++ .../blenderbim/bim/module/type/ui.py | 49 ++++++++++ .../bim/module/type/unassign_type.py | 31 ++++++ .../blenderbim/bim/operator.py | 17 ---- src/ifcblenderexport/blenderbim/bim/prop.py | 12 +-- src/ifcblenderexport/blenderbim/bim/ui.py | 26 ----- 18 files changed, 330 insertions(+), 87 deletions(-) create mode 100644 src/ifcblenderexport/blenderbim/bim/module/type/__init__.py create mode 100644 src/ifcblenderexport/blenderbim/bim/module/type/assign_type.py create mode 100644 src/ifcblenderexport/blenderbim/bim/module/type/data.py create mode 100644 src/ifcblenderexport/blenderbim/bim/module/type/get_related_objects.py create mode 100644 src/ifcblenderexport/blenderbim/bim/module/type/operator.py create mode 100644 src/ifcblenderexport/blenderbim/bim/module/type/ui.py create mode 100644 src/ifcblenderexport/blenderbim/bim/module/type/unassign_type.py diff --git a/src/ifcblenderexport/blenderbim/bim/__init__.py b/src/ifcblenderexport/blenderbim/bim/__init__.py index 1496e4caa5..b9edfe5a65 100644 --- a/src/ifcblenderexport/blenderbim/bim/__init__.py +++ b/src/ifcblenderexport/blenderbim/bim/__init__.py @@ -16,6 +16,7 @@ if bpy is not None: import blenderbim.bim.module.project as module_project import blenderbim.bim.module.spatial as module_spatial import blenderbim.bim.module.style as module_style + import blenderbim.bim.module.type as module_type import blenderbim.bim.module.unit as module_unit from . import ui, prop, operator @@ -150,7 +151,6 @@ if bpy is not None: operator.ImportIfcCsv, operator.EyedropIfcCsv, operator.ReloadIfcFile, - operator.SelectSimilarType, operator.AddIfcFile, operator.RemoveIfcFile, operator.SelectDocIfcFile, @@ -285,7 +285,6 @@ if bpy is not None: ui.BIM_PT_debug, ui.BIM_PT_material, ui.BIM_PT_presentation_layer_data, - ui.BIM_PT_object, ui.BIM_PT_object_material, ui.BIM_PT_object_psets, ui.BIM_PT_object_qto, @@ -323,6 +322,7 @@ if bpy is not None: classes.extend(module_project.classes) classes.extend(module_spatial.classes) classes.extend(module_style.classes) + classes.extend(module_type.classes) classes.extend(module_unit.classes) def menu_func_export(self, context): @@ -366,6 +366,7 @@ if bpy is not None: module_project.register() module_spatial.register() module_style.register() + module_type.register() module_unit.register() bpy.app.handlers.depsgraph_update_pre.append(operator.depsgraph_update_pre_handler) bpy.app.handlers.load_post.append(prop.toggleDecorationsOnLoad) @@ -389,6 +390,7 @@ if bpy is not None: del bpy.types.TextCurve.BIMTextProperties bpy.types.SCENE_PT_unit.remove(ui.ifc_units) module_unit.unregister() + module_type.unregister() module_style.unregister() module_spatial.unregister() module_project.unregister() diff --git a/src/ifcblenderexport/blenderbim/bim/export_ifc.py b/src/ifcblenderexport/blenderbim/bim/export_ifc.py index f3199dd0e6..c4e4349888 100644 --- a/src/ifcblenderexport/blenderbim/bim/export_ifc.py +++ b/src/ifcblenderexport/blenderbim/bim/export_ifc.py @@ -59,7 +59,6 @@ class IfcParser: self.rel_contained_in_spatial_structure = {} self.rel_nests = {} self.rel_space_boundaries = {} - self.rel_defines_by_type = {} self.rel_defines_by_qto = {} self.rel_defines_by_pset = {} self.rel_associates_document_object = {} @@ -371,9 +370,6 @@ class IfcParser: product.update(metadata_override) type_product = obj.BIMObjectProperties.relating_type - if type_product and self.is_a_type(self.get_ifc_class(type_product.name)): - reference = self.get_type_product_reference(type_product.name) - self.rel_defines_by_type.setdefault(reference, []).append(self.product_index) if product["has_boundary_condition"]: product["boundary_condition_class"] = obj.BIMObjectProperties.boundary_condition.name @@ -1374,7 +1370,6 @@ class IfcExporter: self.relate_objects_to_objects() self.relate_elements_to_spatial_structures() self.relate_nested_elements_to_hosted_elements() - self.relate_objects_to_types() self.relate_objects_to_qtos() self.relate_objects_to_psets() self.relate_objects_to_opening_elements() @@ -3177,17 +3172,6 @@ class IfcExporter: [o["ifc"] for o in related_objects], ) - def relate_objects_to_types(self): - for relating_type, related_objects in self.ifc_parser.rel_defines_by_type.items(): - self.file.createIfcRelDefinesByType( - ifcopenshell.guid.new(), - self.owner_history, - None, - None, - [self.ifc_parser.products[o]["ifc"] for o in related_objects], - self.ifc_parser.type_products[relating_type]["ifc"], - ) - def relate_objects_to_qtos(self): for relating_property_key, related_objects in self.ifc_parser.rel_defines_by_qto.items(): self.file.createIfcRelDefinesByProperties( diff --git a/src/ifcblenderexport/blenderbim/bim/ifc.py b/src/ifcblenderexport/blenderbim/bim/ifc.py index d2efa09c71..43ae6873f3 100644 --- a/src/ifcblenderexport/blenderbim/bim/ifc.py +++ b/src/ifcblenderexport/blenderbim/bim/ifc.py @@ -5,6 +5,7 @@ import ifcopenshell class IfcStore: path = "" file = None + schema = None pset_template_path = "" pset_template_file = None @@ -15,3 +16,11 @@ class IfcStore: if IfcStore.path: IfcStore.file = ifcopenshell.open(IfcStore.path) return IfcStore.file + + @staticmethod + def get_schema(): + if IfcStore.file is None: + return + elif IfcStore.schema is None: + IfcStore.schema = ifcopenshell.ifcopenshell_wrapper.schema_by_name(IfcStore.file.schema) + return IfcStore.schema diff --git a/src/ifcblenderexport/blenderbim/bim/import_ifc.py b/src/ifcblenderexport/blenderbim/bim/import_ifc.py index ca5436ebf8..b21be24c48 100644 --- a/src/ifcblenderexport/blenderbim/bim/import_ifc.py +++ b/src/ifcblenderexport/blenderbim/bim/import_ifc.py @@ -976,7 +976,6 @@ class IfcImporter: self.add_element_representation_items(element, obj) self.add_element_classifications(element, obj) self.add_element_document_relations(element, obj) - self.add_defines_by_type_relation(element, obj) self.add_opening_relation(element, obj) self.add_product_definitions(element, obj) self.added_data[element.GlobalId] = obj @@ -1426,11 +1425,6 @@ class IfcImporter: new_prop.name = prop.Name new_prop.string_value = str(value) - def add_defines_by_type_relation(self, element, obj): - related_type = ifcopenshell.util.element.get_type(element) - if related_type: - obj.BIMObjectProperties.relating_type = self.type_products[related_type.GlobalId] - def add_opening_relation(self, element, obj): if not element.is_a("IfcOpeningElement"): return @@ -1732,7 +1726,6 @@ class IfcImporter: self.place_object_in_spatial_tree(element, obj) self.add_element_classifications(element, obj) self.add_element_document_relations(element, obj) - self.add_defines_by_type_relation(element, obj) self.add_product_definitions(element, obj) self.aggregates[element.GlobalId] = obj self.aggregate_collections[rel_aggregate.id()] = collection @@ -1794,7 +1787,6 @@ class IfcImporter: obj.matrix_world = self.get_element_matrix(element, mesh_name) self.add_element_classifications(element, obj) self.add_element_document_relations(element, obj) - self.add_defines_by_type_relation(element, obj) self.add_product_definitions(element, obj) self.added_data[element.GlobalId] = obj diff --git a/src/ifcblenderexport/blenderbim/bim/module/aggregate/operator.py b/src/ifcblenderexport/blenderbim/bim/module/aggregate/operator.py index 7f5a57aac0..f5cf7659d7 100644 --- a/src/ifcblenderexport/blenderbim/bim/module/aggregate/operator.py +++ b/src/ifcblenderexport/blenderbim/bim/module/aggregate/operator.py @@ -29,10 +29,7 @@ class AssignObject(bpy.types.Operator): Data.load(props.ifc_definition_id) bpy.ops.bim.disable_editing_aggregate(obj=related_object.name) - file = IfcStore.get_file() - ifc_schema = ifcopenshell.ifcopenshell_wrapper.schema_by_name(file.schema) - declaration = ifc_schema.declaration_by_name(product.is_a()) - + declaration = IfcStore.get_schema().declaration_by_name(product.is_a()) # TODO: we may not need this conditional if aggregates stop using collection instances if ifcopenshell.util.schema.is_a(declaration, "IfcSpatialElement"): related_collection = related_object.users_collection[0] diff --git a/src/ifcblenderexport/blenderbim/bim/module/attribute/data.py b/src/ifcblenderexport/blenderbim/bim/module/attribute/data.py index ab5d954d06..b02874563c 100644 --- a/src/ifcblenderexport/blenderbim/bim/module/attribute/data.py +++ b/src/ifcblenderexport/blenderbim/bim/module/attribute/data.py @@ -13,8 +13,7 @@ class Data: product = file.by_id(product_id) cls.products[product_id] = [] attributes = product.get_info() - schema = ifcopenshell.ifcopenshell_wrapper.schema_by_name(file.schema) - declaration = schema.declaration_by_name(product.is_a()) + declaration = IfcStore.get_schema().declaration_by_name(product.is_a()) for attribute in declaration.all_attributes(): data_type = str(attribute.type_of_attribute()) value = getattr(product, attribute.name()) diff --git a/src/ifcblenderexport/blenderbim/bim/module/root/operator.py b/src/ifcblenderexport/blenderbim/bim/module/root/operator.py index 67a128ed98..aebd873f1f 100644 --- a/src/ifcblenderexport/blenderbim/bim/module/root/operator.py +++ b/src/ifcblenderexport/blenderbim/bim/module/root/operator.py @@ -20,8 +20,6 @@ class EnableReassignClass(bpy.types.Operator): def execute(self, context): obj = bpy.context.active_object ifc_class = obj.name.split("/")[0] - file = IfcStore.get_file() - ifc_schema = ifcopenshell.ifcopenshell_wrapper.schema_by_name(file.schema) bpy.context.active_object.BIMObjectProperties.is_reassigning_class = True ifc_products = [ "IfcElement", @@ -34,7 +32,7 @@ class EnableReassignClass(bpy.types.Operator): "IfcAnnotation", ] for ifc_product in ifc_products: - if ifcopenshell.util.schema.is_a(ifc_schema.declaration_by_name(ifc_class), ifc_product): + if ifcopenshell.util.schema.is_a(IfcStore.get_schema().declaration_by_name(ifc_class), ifc_product): bpy.context.scene.BIMProperties.ifc_product = ifc_product bpy.context.scene.BIMProperties.ifc_class = obj.name.split("/")[0] predefined_type = obj.BIMObjectProperties.attributes.get("PredefinedType") @@ -87,8 +85,7 @@ class AssignClass(bpy.types.Operator): def execute(self, context): objects = [bpy.data.objects.get(self.obj)] if self.obj else bpy.context.selected_objects self.file = IfcStore.get_file() - ifc_schema = ifcopenshell.ifcopenshell_wrapper.schema_by_name(self.file.schema) - self.declaration = ifc_schema.declaration_by_name(self.ifc_class) + self.declaration = IfcStore.get_schema().declaration_by_name(self.ifc_class) if self.predefined_type == "USERDEFINED": self.predefined_type = self.ifc_userdefined_type elif self.predefined_type == "": diff --git a/src/ifcblenderexport/blenderbim/bim/module/spatial/assign_container.py b/src/ifcblenderexport/blenderbim/bim/module/spatial/assign_container.py index 8fe283d9ac..b8087cd3a0 100644 --- a/src/ifcblenderexport/blenderbim/bim/module/spatial/assign_container.py +++ b/src/ifcblenderexport/blenderbim/bim/module/spatial/assign_container.py @@ -15,7 +15,7 @@ class Usecase: contained_in_structure = self.settings["product"].ContainedInStructure contains_elements = self.settings["relating_structure"].ContainsElements - if contains_elements and contained_in_structure == contains_elements: + if contains_elements and contained_in_structure and contained_in_structure[0] == contains_elements[0]: return if contained_in_structure: diff --git a/src/ifcblenderexport/blenderbim/bim/module/type/__init__.py b/src/ifcblenderexport/blenderbim/bim/module/type/__init__.py new file mode 100644 index 0000000000..a4ac57b1c4 --- /dev/null +++ b/src/ifcblenderexport/blenderbim/bim/module/type/__init__.py @@ -0,0 +1,19 @@ +import bpy +from . import ui, operator + +classes = ( + operator.AssignType, + operator.UnassignType, + operator.EnableEditingType, + operator.DisableEditingType, + operator.SelectSimilarType, + ui.BIM_PT_type, +) + + +def register(): + pass + + +def unregister(): + pass diff --git a/src/ifcblenderexport/blenderbim/bim/module/type/assign_type.py b/src/ifcblenderexport/blenderbim/bim/module/type/assign_type.py new file mode 100644 index 0000000000..50e72813b7 --- /dev/null +++ b/src/ifcblenderexport/blenderbim/bim/module/type/assign_type.py @@ -0,0 +1,51 @@ +import ifcopenshell + + +class Usecase: + def __init__(self, file, settings=None): + self.file = file + self.settings = { + "related_object": None, + "relating_type": None, + } + for key, value in settings.items(): + self.settings[key] = value + + def execute(self): + if self.file.schema == "IFC2X3": + is_typed_by = None + is_defined_by = self.settings["related_object"].IsDefinedBy + for rel in is_defined_by: + if rel.is_a("IfcRelDefinesByType"): + is_typed_by = [rel] + break + types = self.settings["relating_type"].ObjectTypeOf + else: + is_typed_by = self.settings["related_object"].IsTypedBy + types = self.settings["relating_type"].Types + + if types and is_typed_by == types: + return + + if is_typed_by: + related_objects = list(is_typed_by[0].RelatedObjects) + related_objects.remove(self.settings["related_object"]) + if related_objects: + is_typed_by[0].RelatedObjects = related_objects + else: + self.file.remove(is_typed_by) + + if types: + related_objects = list(types[0].RelatedObjects) + related_objects.append(self.settings["related_object"]) + types[0].RelatedObjects = related_objects + else: + types = self.file.create_entity( + "IfcRelDefinesByType", + **{ + "GlobalId": ifcopenshell.guid.new(), + # TODO "OwnerHistory": None + "RelatedObjects": [self.settings["related_object"]], + "RelatingType": self.settings["relating_type"], + } + ) diff --git a/src/ifcblenderexport/blenderbim/bim/module/type/data.py b/src/ifcblenderexport/blenderbim/bim/module/type/data.py new file mode 100644 index 0000000000..8201945cb7 --- /dev/null +++ b/src/ifcblenderexport/blenderbim/bim/module/type/data.py @@ -0,0 +1,27 @@ +from blenderbim.bim.ifc import IfcStore + + +class Data: + products = {} + + @classmethod + def load(cls, product_id): + file = IfcStore.get_file() + if not file: + return + product = file.by_id(product_id) + if file.schema == "IFC2X3" and not hasattr(product, "IsDefinedBy"): + cls.products[product_id] = None + elif file.schema != "IFC2X3" and not hasattr(product, "IsTypedBy"): + cls.products[product_id] = None + elif hasattr(product, "IsTypedBy") and product.IsTypedBy: + type = product.IsTypedBy[0].RelatingType + cls.products[product_id] = {"type": type.is_a(), "Name": type.Name, "id": int(type.id())} + elif hasattr(product, "IsDefinedBy") and product.IsDefinedBy: + cls.products[product_id] = {"type": None, "Name": None} + for rel in product.IsDefinedBy: + if rel.is_a("IfcRelDefinesByType"): + type = rel.RelatingType + cls.products[product_id] = {"type": type.is_a(), "Name": type.Name, "id": int(type.id())} + else: + cls.products[product_id] = {"type": None, "Name": None, "id": None} diff --git a/src/ifcblenderexport/blenderbim/bim/module/type/get_related_objects.py b/src/ifcblenderexport/blenderbim/bim/module/type/get_related_objects.py new file mode 100644 index 0000000000..9226799575 --- /dev/null +++ b/src/ifcblenderexport/blenderbim/bim/module/type/get_related_objects.py @@ -0,0 +1,32 @@ +import ifcopenshell + + +class Usecase: + def __init__(self, file, settings=None): + self.file = file + self.settings = { + "related_object": None, + "relating_type": None, + } + for key, value in settings.items(): + self.settings[key] = value + + def execute(self): + if self.settings["related_object"]: + if self.file.schema == "IFC2X3": + is_defined_by = self.settings["related_object"].IsDefinedBy + for rel in is_defined_by: + if rel.is_a("IfcRelDefinesByType"): + return set([int(o.id()) for o in rel.RelatedObjects]) + else: + is_typed_by = self.settings["related_object"].IsTypedBy + if is_typed_by: + return set([int(o.id()) for o in is_typed_by[0].RelatedObjects]) + elif self.settings["relating_type"]: + if self.file.schema == "IFC2X3": + types = self.settings["relating_type"].ObjectTypeOf + else: + types = self.settings["relating_type"].Types + if types: + return set([int(o.id()) for o in types[0].RelatedObjects]) + return set() diff --git a/src/ifcblenderexport/blenderbim/bim/module/type/operator.py b/src/ifcblenderexport/blenderbim/bim/module/type/operator.py new file mode 100644 index 0000000000..aa72ef7358 --- /dev/null +++ b/src/ifcblenderexport/blenderbim/bim/module/type/operator.py @@ -0,0 +1,97 @@ +import bpy +import ifcopenshell.util.schema +import blenderbim.bim.module.type.assign_type as assign_type +import blenderbim.bim.module.type.unassign_type as unassign_type +import blenderbim.bim.module.type.get_related_objects as get_related_objects +from blenderbim.bim.ifc import IfcStore +from blenderbim.bim.module.type.data import Data + + +class AssignType(bpy.types.Operator): + bl_idname = "bim.assign_type" + bl_label = "Assign Type" + relating_type: bpy.props.StringProperty() + related_object: bpy.props.StringProperty() + + def execute(self, context): + self.file = IfcStore.get_file() + related_object = bpy.data.objects.get(self.related_object) if self.related_object else bpy.context.active_object + props = related_object.BIMObjectProperties + relating_type = bpy.data.objects.get(self.relating_type) if self.relating_type else props.relating_type + if not relating_type or not relating_type.BIMObjectProperties.ifc_definition_id: + return {"FINISHED"} + assign_type.Usecase( + self.file, + { + "related_object": self.file.by_id(props.ifc_definition_id), + "relating_type": self.file.by_id(relating_type.BIMObjectProperties.ifc_definition_id), + }, + ).execute() + Data.load(props.ifc_definition_id) + bpy.ops.bim.disable_editing_type(obj=related_object.name) + return {"FINISHED"} + + +class UnassignType(bpy.types.Operator): + bl_idname = "bim.unassign_type" + bl_label = "Unassign Type" + related_object: bpy.props.StringProperty() + + def execute(self, context): + self.file = IfcStore.get_file() + related_object = bpy.data.objects.get(self.related_object) if self.related_object else bpy.context.active_object + props = related_object.BIMObjectProperties + unassign_type.Usecase( + self.file, + { + "related_object": self.file.by_id(props.ifc_definition_id), + }, + ).execute() + Data.load(props.ifc_definition_id) + return {"FINISHED"} + + +class EnableEditingType(bpy.types.Operator): + bl_idname = "bim.enable_editing_type" + bl_label = "Enable Editing Type" + + def execute(self, context): + bpy.context.active_object.BIMObjectProperties.relating_type = None + bpy.context.active_object.BIMObjectProperties.is_editing_type = True + return {"FINISHED"} + + +class DisableEditingType(bpy.types.Operator): + bl_idname = "bim.disable_editing_type" + bl_label = "Disable Editing Type" + obj: bpy.props.StringProperty() + + def execute(self, context): + obj = bpy.data.objects.get(self.obj) if self.obj else bpy.context.active_object + obj.BIMObjectProperties.is_editing_type = False + return {"FINISHED"} + + +class SelectSimilarType(bpy.types.Operator): + bl_idname = "bim.select_similar_type" + bl_label = "Select Similar Type" + related_object: bpy.props.StringProperty() + + def execute(self, context): + self.file = IfcStore.get_file() + related_object = bpy.data.objects.get(self.related_object) if self.related_object else bpy.context.active_object + props = related_object.BIMObjectProperties + product = self.file.by_id(props.ifc_definition_id) + declaration = IfcStore.get_schema().declaration_by_name(product.is_a()) + if ifcopenshell.util.schema.is_a(declaration, "IfcElementType"): + related_objects = get_related_objects.Usecase(self.file, { + "relating_type": self.file.by_id(props.ifc_definition_id) + }).execute() + else: + related_objects = get_related_objects.Usecase(self.file, { + "related_object": self.file.by_id(props.ifc_definition_id) + }).execute() + for obj in bpy.context.visible_objects: + if obj.BIMObjectProperties.ifc_definition_id in related_objects: + obj.select_set(True) + return {"FINISHED"} diff --git a/src/ifcblenderexport/blenderbim/bim/module/type/ui.py b/src/ifcblenderexport/blenderbim/bim/module/type/ui.py new file mode 100644 index 0000000000..05bd240097 --- /dev/null +++ b/src/ifcblenderexport/blenderbim/bim/module/type/ui.py @@ -0,0 +1,49 @@ +from bpy.types import Panel +from blenderbim.bim.module.type.data import Data + + +class BIM_PT_type(Panel): + bl_label = "IFC Construction Type" + bl_idname = "BIM_PT_type" + bl_space_type = "PROPERTIES" + bl_region_type = "WINDOW" + bl_context = "object" + + @classmethod + def poll(cls, context): + props = context.active_object.BIMObjectProperties + if not props.ifc_definition_id: + return False + if props.ifc_definition_id not in Data.products: + Data.load(props.ifc_definition_id) + if not Data.products[props.ifc_definition_id]: + return False + return True + + + def draw(self, context): + props = context.active_object.BIMObjectProperties + if not props.ifc_definition_id: + return + if props.ifc_definition_id not in Data.products: + Data.load(props.ifc_definition_id) + + if props.is_editing_type: + row = self.layout.row(align=True) + row.prop(props, "relating_type", text="") + row.operator("bim.assign_type", icon="CHECKMARK", text="") + row.operator("bim.disable_editing_type", icon="X", text="") + else: + row = self.layout.row(align=True) + name = "{}/{}".format( + Data.products[props.ifc_definition_id]["type"], Data.products[props.ifc_definition_id]["Name"] + ) + if name == "None/None": + label = "This object has no type" + else: + label = name + row.label(text=label) + row.operator("bim.select_similar_type", icon="RESTRICT_SELECT_OFF", text="") + row.operator("bim.enable_editing_type", icon="GREASEPENCIL", text="") + if name != "None/None": + row.operator("bim.unassign_type", icon="X", text="") diff --git a/src/ifcblenderexport/blenderbim/bim/module/type/unassign_type.py b/src/ifcblenderexport/blenderbim/bim/module/type/unassign_type.py new file mode 100644 index 0000000000..e20ba75a2d --- /dev/null +++ b/src/ifcblenderexport/blenderbim/bim/module/type/unassign_type.py @@ -0,0 +1,31 @@ +import ifcopenshell + + +class Usecase: + def __init__(self, file, settings=None): + self.file = file + self.settings = { + "related_object": None + } + for key, value in settings.items(): + self.settings[key] = value + + def execute(self): + if self.file.schema == "IFC2X3": + is_typed_by = None + is_defined_by = self.settings["related_object"].IsDefinedBy + for rel in is_defined_by: + if rel.is_a("IfcRelDefinesByType"): + is_typed_by = rel + else: + is_typed_by = self.settings["related_object"].IsTypedBy + if is_typed_by: + is_typed_by = is_typed_by[0] + + if is_typed_by: + related_objects = list(is_typed_by.RelatedObjects) + related_objects.remove(self.settings["related_object"]) + if related_objects: + is_typed_by.RelatedObjects = related_objects + else: + self.file.remove(is_typed_by) diff --git a/src/ifcblenderexport/blenderbim/bim/operator.py b/src/ifcblenderexport/blenderbim/bim/operator.py index 136e650675..b1ea842083 100644 --- a/src/ifcblenderexport/blenderbim/bim/operator.py +++ b/src/ifcblenderexport/blenderbim/bim/operator.py @@ -2832,23 +2832,6 @@ class ReloadIfcFile(bpy.types.Operator): ifc_importer.execute() -class SelectSimilarType(bpy.types.Operator): - bl_idname = "bim.select_similar_type" - bl_label = "Select Similar Type" - - def execute(self, context): - if context.active_object.BIMObjectProperties.relating_type: - relating_type = context.active_object.BIMObjectProperties.relating_type - elif "Type/" in context.active_object.name: - relating_type = context.active_object - else: - return {"FINISHED"} - for obj in bpy.context.visible_objects: - if obj.BIMObjectProperties.relating_type == relating_type: - obj.select_set(True) - return {"FINISHED"} - - class AddIfcFile(bpy.types.Operator): bl_idname = "bim.add_ifc_file" bl_label = "Add IFC File" diff --git a/src/ifcblenderexport/blenderbim/bim/prop.py b/src/ifcblenderexport/blenderbim/bim/prop.py index a9b4f8a17e..de0ba731f3 100644 --- a/src/ifcblenderexport/blenderbim/bim/prop.py +++ b/src/ifcblenderexport/blenderbim/bim/prop.py @@ -128,8 +128,7 @@ def getIfcPredefinedTypes(self, context): global types_enum file = IfcStore.get_file() if len(types_enum) < 1 and file: - ifc_schema = ifcopenshell.ifcopenshell_wrapper.schema_by_name(file.schema) - declaration = ifc_schema.declaration_by_name(self.ifc_class) + declaration = IfcStore.get_schema().declaration_by_name(self.ifc_class) for attribute in declaration.attributes(): if attribute.name() == "PredefinedType": types_enum.extend([(e, e, "") for e in attribute.type_of_attribute().declared_type().enumeration_items()]) @@ -271,8 +270,7 @@ def getIfcClasses(self, context): global classes_enum file = IfcStore.get_file() if len(classes_enum) < 1 and file: - ifc_schema = ifcopenshell.ifcopenshell_wrapper.schema_by_name(file.schema) - declaration = ifc_schema.declaration_by_name(self.ifc_product) + declaration = IfcStore.get_schema().declaration_by_name(self.ifc_product) def get_classes(declaration): results = [] if not declaration.is_abstract(): @@ -1258,7 +1256,7 @@ class BIMProperties(PropertyGroup): ) export_should_force_faceted_brep: BoolProperty(name="Export with Faceted Breps", default=False) export_should_force_triangulation: BoolProperty(name="Export with Triangulation", default=False) - export_should_export_from_memory: BoolProperty(name="Export from Memory", default=False) + export_should_export_from_memory: BoolProperty(name="Export from Memory", default=True) import_should_ignore_site_coordinates: BoolProperty(name="Import Ignoring Site Coordinates", default=False) import_should_ignore_building_coordinates: BoolProperty(name="Import Ignoring Building Coordinates", default=False) import_should_reset_absolute_coordinates: BoolProperty(name="Import Resetting Absolute Coordinates", default=False) @@ -1270,7 +1268,7 @@ class BIMProperties(PropertyGroup): import_should_auto_set_workarounds: BoolProperty(name="Automatically Set Vendor Workarounds", default=True) import_should_use_legacy: BoolProperty(name="Import with Legacy Importer", default=False) import_should_import_native: BoolProperty(name="Import Native Representations", default=False) - import_export_should_roundtrip_native: BoolProperty(name="Roundtrip Native Representations", default=False) + import_export_should_roundtrip_native: BoolProperty(name="Roundtrip Native Representations", default=True) import_should_use_cpu_multiprocessing: BoolProperty(name="Import with CPU Multiprocessing", default=True) import_should_import_with_profiling: BoolProperty(name="Import with Profiling", default=True) import_should_import_aggregates: BoolProperty(name="Import Aggregates", default=True) @@ -1481,6 +1479,8 @@ class BIMObjectProperties(PropertyGroup): relating_object: PointerProperty(name="Aggregate", type=bpy.types.Object) is_editing_aggregate: BoolProperty(name="Is Editing Aggregate") is_editing_container: BoolProperty(name="Is Editing Container") + relating_type: PointerProperty(name="Type", type=bpy.types.Object) + is_editing_type: BoolProperty(name="Is Editing Type") relating_type: PointerProperty(name="Type Product", type=bpy.types.Object) relating_structure: PointerProperty(name="Spatial Container", type=bpy.types.Object) psets: CollectionProperty(name="Psets", type=PsetQto) diff --git a/src/ifcblenderexport/blenderbim/bim/ui.py b/src/ifcblenderexport/blenderbim/bim/ui.py index 35bb981c7f..8cf73cdeb2 100644 --- a/src/ifcblenderexport/blenderbim/bim/ui.py +++ b/src/ifcblenderexport/blenderbim/bim/ui.py @@ -5,32 +5,6 @@ from bpy.types import Panel from bpy.props import StringProperty -class BIM_PT_object(Panel): - bl_label = "IFC Object" - bl_idname = "BIM_PT_object" - bl_space_type = "PROPERTIES" - bl_region_type = "WINDOW" - bl_context = "object" - - @classmethod - def poll(cls, context): - return context.active_object is not None and hasattr(context.active_object, "BIMObjectProperties") - - def draw(self, context): - if context.active_object is None: - return - layout = self.layout - props = context.active_object.BIMObjectProperties - bim_properties = context.scene.BIMProperties - - if "Ifc" not in context.active_object.name: - return - - row = layout.row(align=True) - row.prop(props, "relating_type") - row.operator("bim.select_similar_type", icon="RESTRICT_SELECT_OFF", text="") - - class BIM_PT_object_material(Panel): bl_label = "IFC Object Material" bl_idname = "BIM_PT_object_material"