From c95a47ca97edb99f4c1b482a0574d37b27009b11 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bruno=20Perdig=C3=A3o?= Date: Fri, 15 Mar 2024 21:34:27 -0300 Subject: [PATCH 1/4] fix #4430. Shift+D whem selecting all the objects of a linked aggregate creates a normal copy that is not linked --- .../bim/module/geometry/operator.py | 90 +++++++++++-------- 1 file changed, 54 insertions(+), 36 deletions(-) diff --git a/src/blenderbim/blenderbim/bim/module/geometry/operator.py b/src/blenderbim/blenderbim/bim/module/geometry/operator.py index 54111eed24..79ed1e1b32 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): @@ -974,15 +970,15 @@ 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) @@ -1002,6 +998,8 @@ class DuplicateMoveLinkedAggregate(bpy.types.Operator): pset=pset, properties={"Index": index}, ) + + index += 1 else: pass @@ -1042,7 +1040,39 @@ 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"} @@ -1063,28 +1093,18 @@ 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 @@ -1176,8 +1196,6 @@ class RefreshLinkedAggregate(bpy.types.Operator): obj.name = original_names[group][index] except: return - - def get_element_assembly(element): if element.is_a("IfcElementAssembly"): From 3bf4a8ef529f83ba1755690175891a104e7e9209 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bruno=20Perdig=C3=A3o?= Date: Sat, 16 Mar 2024 12:44:26 -0300 Subject: [PATCH 2/4] small refactor --- .../bim/module/geometry/operator.py | 40 ++++++++++++++----- 1 file changed, 30 insertions(+), 10 deletions(-) diff --git a/src/blenderbim/blenderbim/bim/module/geometry/operator.py b/src/blenderbim/blenderbim/bim/module/geometry/operator.py index 79ed1e1b32..1ffad9df69 100644 --- a/src/blenderbim/blenderbim/bim/module/geometry/operator.py +++ b/src/blenderbim/blenderbim/bim/module/geometry/operator.py @@ -1238,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.") @@ -1277,10 +1294,11 @@ 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_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) @@ -1292,12 +1310,14 @@ 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 + + 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 for old, new in old_to_new.items(): if element_aggregate and new[0].is_a("IfcElementAssembly"): From 4829c4c02bb27cb18798f78c72eadfed736423f4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bruno=20Perdig=C3=A3o?= Date: Sat, 16 Mar 2024 15:27:04 -0300 Subject: [PATCH 3/4] fix: when subaggregate that is a linked aggregate is unassinged from the main aggregate, it remains a linked aggregate. --- .../blenderbim/bim/module/aggregate/operator.py | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/blenderbim/blenderbim/bim/module/aggregate/operator.py b/src/blenderbim/blenderbim/bim/module/aggregate/operator.py index bf336ad69b..9e26e78db0 100644 --- a/src/blenderbim/blenderbim/bim/module/aggregate/operator.py +++ b/src/blenderbim/blenderbim/bim/module/aggregate/operator.py @@ -91,10 +91,11 @@ 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): From e6bef16c45d6dcbab712c97598269afebe31d9d3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bruno=20Perdig=C3=A3o?= Date: Mon, 18 Mar 2024 23:39:06 -0300 Subject: [PATCH 4/4] small deletions --- .../blenderbim/bim/module/geometry/operator.py | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/src/blenderbim/blenderbim/bim/module/geometry/operator.py b/src/blenderbim/blenderbim/bim/module/geometry/operator.py index 1ffad9df69..50ad245ac0 100644 --- a/src/blenderbim/blenderbim/bim/module/geometry/operator.py +++ b/src/blenderbim/blenderbim/bim/module/geometry/operator.py @@ -1294,10 +1294,6 @@ 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) @@ -1312,12 +1308,6 @@ class RefreshLinkedAggregate(bpy.types.Operator): 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(): - # 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 for old, new in old_to_new.items(): if element_aggregate and new[0].is_a("IfcElementAssembly"):