diff --git a/src/blenderbim/blenderbim/bim/module/aggregate/operator.py b/src/blenderbim/blenderbim/bim/module/aggregate/operator.py index 2c3fbef38e..db4c1232cd 100644 --- a/src/blenderbim/blenderbim/bim/module/aggregate/operator.py +++ b/src/blenderbim/blenderbim/bim/module/aggregate/operator.py @@ -96,12 +96,13 @@ class BIM_OT_aggregate_unassign_object(bpy.types.Operator, Operator): ) # Removes Pset related to Linked Aggregates - pset = ifcopenshell.util.element.get_pset(element, "BBIM_Linked_Aggregate") - if pset: - pset = tool.Ifc.get().by_id(pset["id"]) - ifcopenshell.api.run("pset.remove_pset", tool.Ifc.get(), pset=pset) - + if not element.is_a('IfcElementAssembly'): + pset = ifcopenshell.util.element.get_pset(element, 'BBIM_Linked_Aggregate') + if pset: + pset = tool.Ifc.get().by_id(pset["id"]) + ifcopenshell.api.run("pset.remove_pset", tool.Ifc.get(), pset=pset) + class BIM_OT_enable_editing_aggregate(bpy.types.Operator, Operator): """Enable editing aggregation relationship""" diff --git a/src/blenderbim/blenderbim/bim/module/geometry/operator.py b/src/blenderbim/blenderbim/bim/module/geometry/operator.py index 4071d2a882..f953c1d743 100644 --- a/src/blenderbim/blenderbim/bim/module/geometry/operator.py +++ b/src/blenderbim/blenderbim/bim/module/geometry/operator.py @@ -843,7 +843,7 @@ class OverrideDuplicateMove(bpy.types.Operator): # Recreate decompositions tool.Root.recreate_decompositions(decomposition_relationships, old_to_new) - OverrideDuplicateMove.handle_linked_aggregates(old_to_new) + OverrideDuplicateMove.remove_linked_aggregate_data(old_to_new) blenderbim.bim.handler.refresh_ui_data() return old_to_new @@ -896,25 +896,21 @@ class OverrideDuplicateMove(bpy.types.Operator): if entity in old_to_new.keys(): core.remove_connection(tool.Geometry, connection=connection) - @staticmethod - def handle_linked_aggregates(old_to_new): + def remove_linked_aggregate_data(old_to_new): for old, new in old_to_new.items(): pset = ifcopenshell.util.element.get_pset(new[0], "BBIM_Linked_Aggregate") if pset: - old_aggregate = ifcopenshell.util.element.get_aggregate(old) - new_aggregate = ifcopenshell.util.element.get_aggregate(new[0]) - if old_aggregate == new_aggregate: - parts = ifcopenshell.util.element.get_parts(new_aggregate) - if parts: - index = DuplicateMoveLinkedAggregate.get_max_index(parts) - index += 1 - pset = tool.Ifc.get().by_id(pset["id"]) - ifcopenshell.api.run( - "pset.edit_pset", - tool.Ifc.get(), - pset=pset, - properties={"Index": index}, - ) + pset = tool.Ifc.get().by_id(pset["id"]) + ifcopenshell.api.run("pset.remove_pset", tool.Ifc.get(), pset=pset) + + if new[0].is_a("IfcElementAssembly"): + linked_aggregate_group = [ + r.RelatingGroup + for r in getattr(new[0], "HasAssignments", []) or [] + if r.is_a("IfcRelAssignsToGroup") + if "BBIM_Linked_Aggregate" in r.RelatingGroup.Name + ] + tool.Ifc.run("group.unassign_group", group=linked_aggregate_group[0], product=new[0]) class OverrideDuplicateMoveLinkedMacro(bpy.types.Macro): @@ -975,16 +971,16 @@ class DuplicateMoveLinkedAggregate(bpy.types.Operator): obj.select_set(True) parts = ifcopenshell.util.element.get_parts(element) if parts: - index = DuplicateMoveLinkedAggregate.get_max_index(parts) + index = get_max_index(parts) add_linked_aggregate_pset(element, index) index += 1 for part in parts: if part.is_a("IfcElementAssembly"): select_objects_and_add_data(part) else: - add_linked_aggregate_pset(part, index) - index += 1 - + index = add_linked_aggregate_pset(part, index) + # index += 1 + obj = tool.Ifc.get_object(part) obj.select_set(True) @@ -1000,6 +996,8 @@ class DuplicateMoveLinkedAggregate(bpy.types.Operator): pset=pset, properties={"Index": index}, ) + + index += 1 else: pass @@ -1042,6 +1040,40 @@ class DuplicateMoveLinkedAggregate(bpy.types.Operator): if re.findall(pattern2, new_obj.name): split_name = new_obj.name.split(".") new_obj.name = split_name[0] + "_" + number + + def get_max_index(parts): + psets = [ifcopenshell.util.element.get_pset(p, "BBIM_Linked_Aggregate") for p in parts] + index = [i['Index'] for i in psets if i] + if len(index) > 0: + index = max(index) + return index + else: + return 0 + + def copy_linked_aggregate_data(old_to_new): + for old, new in old_to_new.items(): + pset = ifcopenshell.util.element.get_pset(old, "BBIM_Linked_Aggregate") + if pset: + new_pset = ifcopenshell.api.run( + "pset.add_pset", tool.Ifc.get(), product=new[0], name=self.pset_name + ) + + ifcopenshell.api.run( + "pset.edit_pset", + tool.Ifc.get(), + pset=new_pset, + properties={"Index": pset["Index"]}, + ) + + if new[0].is_a("IfcElementAssembly"): + linked_aggregate_group = [ + r.RelatingGroup + for r in getattr(old, "HasAssignments", []) or [] + if r.is_a("IfcRelAssignsToGroup") + if "BBIM_Linked_Aggregate" in r.RelatingGroup.Name + ] + tool.Ifc.run("group.assign_group", group=linked_aggregate_group[0], products=new) + if len(context.selected_objects) != 1: return {"FINISHED"} @@ -1062,28 +1094,17 @@ class DuplicateMoveLinkedAggregate(bpy.types.Operator): select_objects_and_add_data(selected_element) old_to_new = OverrideDuplicateMove.execute_ifc_duplicate_operator(self, context, linked=True) + + tool.Root.recreate_aggregate(old_to_new) + + copy_linked_aggregate_data(old_to_new) custom_incremental_naming_for_element_assembly(old_to_new) - # Recreate aggregate relationship - for old in old_to_new.keys(): - if old.is_a("IfcElementAssembly"): - tool.Root.recreate_aggregate(old_to_new) - blenderbim.bim.handler.refresh_ui_data() return old_to_new - @staticmethod - def get_max_index(parts): - psets = [ifcopenshell.util.element.get_pset(p, "BBIM_Linked_Aggregate") for p in parts] - index = [i["Index"] for i in psets if i] - if len(index) > 0: - index = max(index) - return index - else: - return 0 - class RefreshLinkedAggregate(bpy.types.Operator): bl_idname = "bim.refresh_linked_aggregate" @@ -1217,6 +1238,23 @@ class RefreshLinkedAggregate(bpy.types.Operator): return list(set(linked_aggregate_groups)), selected_parents + def get_original_matrix(element, base_instance): + selected_obj = tool.Ifc.get_object(base_instance) + selected_matrix = selected_obj.matrix_world + object_duplicate = tool.Ifc.get_object(element) + duplicate_matrix = object_duplicate.matrix_world.decompose() + + return selected_matrix, duplicate_matrix + + def set_new_matrix(selected_matrix, duplicate_matrix, old_to_new): + for old, new in old_to_new.items(): + new_obj = tool.Ifc.get_object(new[0]) + new_base_matrix = Matrix.LocRotScale(*duplicate_matrix) + matrix_diff = Matrix.inverted(selected_matrix) @ new_obj.matrix_world + new_obj_matrix = new_base_matrix @ matrix_diff + new_obj.matrix_world = new_obj_matrix + + active_element = tool.Ifc.get_entity(context.active_object) if not active_element: self.report({"INFO"}, "Object has no Ifc metadata.") @@ -1256,10 +1294,7 @@ class RefreshLinkedAggregate(bpy.types.Operator): element_aggregate = ifcopenshell.util.element.get_aggregate(element) - selected_obj = tool.Ifc.get_object(base_instance) - selected_matrix = selected_obj.matrix_world - object_duplicate = tool.Ifc.get_object(element) - duplicate_matrix = object_duplicate.matrix_world.decompose() + selected_matrix, duplicate_matrix = get_original_matrix(element, base_instance) original_names = get_original_names(element) @@ -1270,15 +1305,9 @@ class RefreshLinkedAggregate(bpy.types.Operator): tool.Ifc.get_object(base_instance).select_set(True) - old_to_new = DuplicateMoveLinkedAggregate.execute_ifc_duplicate_linked_aggregate_operator( - self, context - ) - for old, new in old_to_new.items(): - new_obj = tool.Ifc.get_object(new[0]) - new_base_matrix = Matrix.LocRotScale(*duplicate_matrix) - matrix_diff = Matrix.inverted(selected_matrix) @ new_obj.matrix_world - new_obj_matrix = new_base_matrix @ matrix_diff - new_obj.matrix_world = new_obj_matrix + old_to_new = DuplicateMoveLinkedAggregate.execute_ifc_duplicate_linked_aggregate_operator(self, context) + + set_new_matrix(selected_matrix, duplicate_matrix, old_to_new) for old, new in old_to_new.items(): if element_aggregate and new[0].is_a("IfcElementAssembly"):