From 0d43ef07368dedb6198d6fc99df449049b669360 Mon Sep 17 00:00:00 2001 From: Andrej730 Date: Fri, 20 Oct 2023 14:02:26 +0500 Subject: [PATCH] option to set active system Now it's possible to set in UI active system (currently it's done "select" button next to the system). Also changed the elements that are going to be decorated with system decorator. Previously it was decorating all the mep elements in the projects which was very performance heavy on large projects. --- .../blenderbim/bim/module/system/data.py | 31 +++++++++++++-- .../blenderbim/bim/module/system/operator.py | 2 +- .../blenderbim/bim/module/system/prop.py | 3 +- .../blenderbim/bim/module/system/ui.py | 38 ++++++++++++------- src/blenderbim/blenderbim/core/system.py | 3 +- src/blenderbim/blenderbim/core/tool.py | 1 + src/blenderbim/blenderbim/tool/system.py | 35 +++++++++-------- src/blenderbim/test/core/test_system.py | 3 +- src/blenderbim/test/tool/test_system.py | 8 ++-- 9 files changed, 85 insertions(+), 39 deletions(-) diff --git a/src/blenderbim/blenderbim/bim/module/system/data.py b/src/blenderbim/blenderbim/bim/module/system/data.py index a2be0d98ec..abeddb605b 100644 --- a/src/blenderbim/blenderbim/bim/module/system/data.py +++ b/src/blenderbim/blenderbim/bim/module/system/data.py @@ -162,7 +162,9 @@ class SystemDecorationData: @classmethod def load(cls): - cls.data = {} + cls.data = { + "decorated_elements": cls.decorated_elements(), + } cls.is_loaded = True cls.elements_ports_positions = {} @@ -189,6 +191,29 @@ class SystemDecorationData: cls.elements_ports_positions[element] = ports_data return cls.elements_ports_positions[element] + @classmethod + def decorated_elements(cls): + if not ObjectSystemData.is_loaded: + ObjectSystemData.load() + + # Priority: + # 1. currently selected systems + # 2. active system + # 3. if previous steps didn't worked - decorate connected elements + + decorated_elements = set() + if ObjectSystemData.data["systems"]: + for system in ObjectSystemData.data["systems"]: + system = tool.Ifc.get().by_id(system["id"]) + decorated_elements.update(ifcopenshell.util.system.get_system_elements(system)) + elif active_system := tool.System.get_active_system(): + decorated_elements = set(ifcopenshell.util.system.get_system_elements(active_system)) + + if not decorated_elements: + decorated_elements += ObjectSystemData.data["connected_elements"] + + return decorated_elements + class ZonesData: data = {} @@ -196,7 +221,7 @@ class ZonesData: @classmethod def load(cls): - cls.data = { "total_zones": cls.total_zones() } + cls.data = {"total_zones": cls.total_zones()} cls.is_loaded = True @classmethod @@ -210,7 +235,7 @@ class ActiveObjectZonesData: @classmethod def load(cls): - cls.data = { "zones": cls.zones() } + cls.data = {"zones": cls.zones()} cls.is_loaded = True @classmethod diff --git a/src/blenderbim/blenderbim/bim/module/system/operator.py b/src/blenderbim/blenderbim/bim/module/system/operator.py index 8f1671458f..de617ae7b3 100644 --- a/src/blenderbim/blenderbim/bim/module/system/operator.py +++ b/src/blenderbim/blenderbim/bim/module/system/operator.py @@ -68,7 +68,7 @@ class EditSystem(bpy.types.Operator, Operator): def _execute(self, context): core.edit_system( - tool.Ifc, tool.System, system=tool.Ifc.get().by_id(context.scene.BIMSystemProperties.active_system_id) + tool.Ifc, tool.System, system=tool.Ifc.get().by_id(context.scene.BIMSystemProperties.edited_system_id) ) diff --git a/src/blenderbim/blenderbim/bim/module/system/prop.py b/src/blenderbim/blenderbim/bim/module/system/prop.py index 23c170c46f..7d935e1910 100644 --- a/src/blenderbim/blenderbim/bim/module/system/prop.py +++ b/src/blenderbim/blenderbim/bim/module/system/prop.py @@ -64,7 +64,8 @@ class BIMSystemProperties(PropertyGroup): is_adding: BoolProperty(name="Is Adding", default=False) systems: CollectionProperty(name="Systems", type=System) active_system_index: IntProperty(name="Active System Index") - active_system_id: IntProperty(name="Active System Id", description="Id of the currrently edited system") + active_system_id: IntProperty(name="Active System Id") + edited_system_id: IntProperty(name="Edited System Id") system_class: EnumProperty(items=get_system_class, name="Class") should_draw_decorations: BoolProperty( name="Should Draw Decorations", description="Toggle system decorations", update=toggle_decorations diff --git a/src/blenderbim/blenderbim/bim/module/system/ui.py b/src/blenderbim/blenderbim/bim/module/system/ui.py index fea33a152a..3d3ceae9bc 100644 --- a/src/blenderbim/blenderbim/bim/module/system/ui.py +++ b/src/blenderbim/blenderbim/bim/module/system/ui.py @@ -59,21 +59,34 @@ class BIM_PT_systems(Panel): if not ObjectSystemData.is_loaded: ObjectSystemData.load() - self.props = context.scene.BIMSystemProperties + def draw_system_ui(row, system_id, system_name, system_class): + row = self.layout.row(align=True) + row.label(text=system_name, icon=SYSTEM_ICONS[system_class]) + op = row.operator("bim.select_system_products", text="", icon="RESTRICT_SELECT_OFF") + op.system = system_id + op = row.operator("bim.unassign_system", text="", icon="X") + op.system = system_id + self.props = context.scene.BIMSystemProperties row = self.layout.row(align=True) row.prop(self.props, "should_draw_decorations") - for system in ObjectSystemData.data["systems"]: + row = self.layout.row() + if active_system := tool.System.get_active_system(): + row.label(text=f"Active system:") row = self.layout.row(align=True) - row.label(text=system["name"], icon=SYSTEM_ICONS[system["ifc_class"]]) - op = row.operator("bim.select_system_products", text="", icon="RESTRICT_SELECT_OFF") - op.system = system["id"] - op = row.operator("bim.unassign_system", text="", icon="X") - op.system = system["id"] + draw_system_ui(row, active_system.id(), active_system.Name, active_system.is_a()) + else: + row.label(text="No active system is selected") - if not ObjectSystemData.data["systems"]: - self.layout.label(text="No System associated with Active Object") + if ObjectSystemData.data["systems"]: + row = self.layout.row() + row.label(text="Active object systems:") + for system in ObjectSystemData.data["systems"]: + row = self.layout.row(align=True) + draw_system_ui(row, system["id"], system["name"], system["ifc_class"]) + else: + self.layout.label(text="No System associated with active object") row = self.layout.row(align=True) row.label(text="{} Systems Found in Project".format(SystemData.data["total_systems"]), icon="OUTLINER") @@ -96,7 +109,7 @@ class BIM_PT_systems(Panel): "active_system_index", ) - if self.props.active_system_id: + if self.props.edited_system_id: self.draw_editable_ui(context) def draw_editable_ui(self, context): @@ -316,7 +329,6 @@ class BIM_PT_active_object_zones(Panel): def poll(cls, context): return tool.Ifc.get() and context.active_object and tool.Ifc.get_entity(context.active_object) - def draw(self, context): if not ActiveObjectZonesData.is_loaded: ActiveObjectZonesData.load() @@ -338,12 +350,12 @@ class BIM_UL_systems(UIList): row.label(text=item.name, icon=SYSTEM_ICONS[item.ifc_class]) system_id = item.ifc_definition_id row.operator("bim.assign_system", text="", icon="ADD").system = item.ifc_definition_id - if context.scene.BIMSystemProperties.active_system_id == system_id: + if context.scene.BIMSystemProperties.edited_system_id == system_id: op = row.operator("bim.select_system_products", text="", icon="RESTRICT_SELECT_OFF") op.system = system_id row.operator("bim.edit_system", text="", icon="CHECKMARK") row.operator("bim.disable_editing_system", text="", icon="CANCEL") - elif context.scene.BIMSystemProperties.active_system_id: + elif context.scene.BIMSystemProperties.edited_system_id: op = row.operator("bim.select_system_products", text="", icon="RESTRICT_SELECT_OFF") op.system = system_id op = row.operator("bim.remove_system", text="", icon="X") diff --git a/src/blenderbim/blenderbim/core/system.py b/src/blenderbim/blenderbim/core/system.py index 5afc2b0420..3c6ce42e5a 100644 --- a/src/blenderbim/blenderbim/core/system.py +++ b/src/blenderbim/blenderbim/core/system.py @@ -47,7 +47,7 @@ def remove_system(ifc, system_tool, system=None): def enable_editing_system(system_tool, system=None): system_tool.import_system_attributes(system) - system_tool.set_active_system(system) + system_tool.set_active_edited_system(system) def disable_editing_system(system): @@ -64,6 +64,7 @@ def unassign_system(ifc, system=None, product=None): def select_system_products(system_tool, system=None): system_tool.select_system_products(system) + system_tool.set_active_system(system) def show_ports(ifc, system, spatial, element=None): diff --git a/src/blenderbim/blenderbim/core/tool.py b/src/blenderbim/blenderbim/core/tool.py index 855d70a88e..30d6242841 100644 --- a/src/blenderbim/blenderbim/core/tool.py +++ b/src/blenderbim/blenderbim/core/tool.py @@ -916,6 +916,7 @@ class System: def run_geometry_edit_object_placement(cls, obj=None): pass def run_root_assign_class(cls, obj=None, ifc_class=None, predefined_type=None, should_add_representation=True, context=None, ifc_representation_class=None): pass def select_system_products(cls, system): pass + def set_active_edited_system(cls, system): pass def set_active_system(cls, system): pass diff --git a/src/blenderbim/blenderbim/tool/system.py b/src/blenderbim/blenderbim/tool/system.py index 47e1f58672..d52a94ec1d 100644 --- a/src/blenderbim/blenderbim/tool/system.py +++ b/src/blenderbim/blenderbim/tool/system.py @@ -80,7 +80,7 @@ class System(blenderbim.core.tool.System): @classmethod def disable_editing_system(cls): - bpy.context.scene.BIMSystemProperties.active_system_id = 0 + bpy.context.scene.BIMSystemProperties.edited_system_id = 0 @classmethod def disable_system_editing_ui(cls): @@ -191,10 +191,19 @@ class System(blenderbim.core.tool.System): def select_system_products(cls, system): tool.Spatial.select_products(ifcopenshell.util.system.get_system_elements(system)) + @classmethod + def set_active_edited_system(cls, system): + bpy.context.scene.BIMSystemProperties.edited_system_id = system.id() + @classmethod def set_active_system(cls, system): bpy.context.scene.BIMSystemProperties.active_system_id = system.id() + @classmethod + def get_active_system(cls): + system_props = bpy.context.scene.BIMSystemProperties + return tool.Ifc.get_entity_by_id(system_props.active_system_id) + @classmethod def get_decoration_data(cls): all_vertices = [] @@ -220,33 +229,29 @@ class System(blenderbim.core.tool.System): if not SystemDecorationData.is_loaded: SystemDecorationData.load() - object_system_data = ObjectSystemData.data - selected_elements = object_system_data["connected_elements"] - class FlowDirection(Enum): BACKWARD = -1 FORWARD = 1 BOTH = 2 AMBIGUOUS = 0 - # TODO: get only objects visible in viewport - objects = set(bpy.data.objects) - set(bpy.data.collections["Types"].objects) - for obj in objects: + connected_elements = ObjectSystemData.data["connected_elements"] + + for element in SystemDecorationData.data["decorated_elements"]: start_vert_i = len(all_vertices) + obj = tool.Ifc.get_object(element) + + # skip stuff without objects, like distribution ports + if not obj: + continue + if obj.hide_get(): continue - if not isinstance(obj.data, bpy.types.Mesh): - continue - - element = tool.Ifc.get_entity(obj) - if not element: - continue - if not cls.is_mep_element(element): continue - selected_element = element in selected_elements + selected_element = element in connected_elements verts_pos = [] port_data = SystemDecorationData.get_element_ports_data(element) diff --git a/src/blenderbim/test/core/test_system.py b/src/blenderbim/test/core/test_system.py index cabd2d9a68..f77cae4cd1 100644 --- a/src/blenderbim/test/core/test_system.py +++ b/src/blenderbim/test/core/test_system.py @@ -62,7 +62,7 @@ class TestRemoveSystem: class TestEnableEditingSystem: def test_run(self, system): system.import_system_attributes("system").should_be_called() - system.set_active_system("system").should_be_called() + system.set_active_edited_system("system").should_be_called() subject.enable_editing_system(system, system="system") @@ -87,6 +87,7 @@ class TestUnassignSystem: class TestSelectSystemProducts: def test_run(self, system): system.select_system_products("system").should_be_called() + system.set_active_system("system").should_be_called() subject.select_system_products(system, system="system") diff --git a/src/blenderbim/test/tool/test_system.py b/src/blenderbim/test/tool/test_system.py index f881c8dbef..d10817068e 100644 --- a/src/blenderbim/test/tool/test_system.py +++ b/src/blenderbim/test/tool/test_system.py @@ -53,9 +53,9 @@ class TestDeleteElementObjects(NewFile): class TestDisableEditingSystem(NewFile): def test_run(self): - bpy.context.scene.BIMSystemProperties.active_system_id = 10 + bpy.context.scene.BIMSystemProperties.edited_system_id = 10 subject.disable_editing_system() - assert bpy.context.scene.BIMSystemProperties.active_system_id == 0 + assert bpy.context.scene.BIMSystemProperties.edited_system_id == 0 class TestDisableSystemEditingUI(NewFile): @@ -219,5 +219,5 @@ class TestSetActiveSystem(NewFile): ifc = ifcopenshell.file() tool.Ifc().set(ifc) system = ifcopenshell.api.run("system.add_system", ifc, ifc_class="IfcSystem") - subject.set_active_system(system) - assert bpy.context.scene.BIMSystemProperties.active_system_id == system.id() + subject.set_active_edited_system(system) + assert bpy.context.scene.BIMSystemProperties.edited_system_id == system.id()