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()