From 29d4a8d5fe2386aa9ba052afb573fed0473cc370 Mon Sep 17 00:00:00 2001 From: Andrej730 Date: Wed, 9 Aug 2023 11:16:57 +0500 Subject: [PATCH] More Ports UI Created more UI for ports. Now you can see the list of ports from UI and what objects they are connected to, you can quickly select any ports/connected objects or disconnect objects. From port UI you can see what object's it located on and what object it's connected to and quickly jump across them. Demo - https://imgur.com/a/Gu4Vz7V --- .../blenderbim/bim/module/system/data.py | 40 +++++++ .../blenderbim/bim/module/system/operator.py | 8 +- .../blenderbim/bim/module/system/ui.py | 106 ++++++++++++++---- 3 files changed, 130 insertions(+), 24 deletions(-) diff --git a/src/blenderbim/blenderbim/bim/module/system/data.py b/src/blenderbim/blenderbim/bim/module/system/data.py index 5624f3cd87..6c71e88dc9 100644 --- a/src/blenderbim/blenderbim/bim/module/system/data.py +++ b/src/blenderbim/blenderbim/bim/module/system/data.py @@ -91,8 +91,15 @@ class PortData: @classmethod def load(cls): + element = tool.Ifc.get_entity(bpy.context.active_object) + cls.element = element + is_port = cls.is_port() cls.data = { "total_ports": cls.total_ports(), + "located_ports_data": cls.located_ports_data(), + "is_port": is_port, + "port_connected_object": cls.port_connected_object() if is_port else None, + "port_relating_object": cls.port_relating_object() if is_port else None, } cls.is_loaded = True @@ -100,3 +107,36 @@ class PortData: def total_ports(cls): element = tool.Ifc.get_entity(bpy.context.active_object) return len(ifcopenshell.util.system.get_ports(element)) + + @classmethod + def is_port(cls): + return cls.element and cls.element.is_a("IfcDistributionPort") + + @classmethod + def port_relating_object(cls): + return tool.Ifc.get_object(tool.System.get_port_relating_element(cls.element)) + + @classmethod + def port_connected_object(cls): + connected_port = tool.System.get_connected_port(cls.element) + if not connected_port: + return + connected_element = tool.System.get_port_relating_element(connected_port) + return tool.Ifc.get_object(connected_element) + + @classmethod + def located_ports_data(cls): + element = tool.Ifc.get_entity(bpy.context.active_object) + ports = ifcopenshell.util.system.get_ports(element) + + data = [] + for port in ports: + port_obj = tool.Ifc.get_object(port) + connected_port = tool.System.get_connected_port(port) + if connected_port: + connected_element = tool.Ifc.get_object(tool.System.get_port_relating_element(connected_port)) + else: + connected_element = None + + data.append((port, port_obj, connected_element)) + return data diff --git a/src/blenderbim/blenderbim/bim/module/system/operator.py b/src/blenderbim/blenderbim/bim/module/system/operator.py index 828977060e..00b86936e3 100644 --- a/src/blenderbim/blenderbim/bim/module/system/operator.py +++ b/src/blenderbim/blenderbim/bim/module/system/operator.py @@ -205,8 +205,14 @@ class DisconnectPort(bpy.types.Operator, Operator): bl_label = "Disconnect Ports" bl_options = {"REGISTER", "UNDO"} + element_id: bpy.props.IntProperty(default=0, options={"SKIP_SAVE"}) + def _execute(self, context): - core.disconnect_port(tool.Ifc, port=tool.Ifc.get_entity(context.active_object)) + if self.element_id != 0: + element = tool.Ifc.get().by_id(self.element_id) + else: + element = tool.Ifc.get_entity(context.active_object) + core.disconnect_port(tool.Ifc, port=element) class SetFlowDirection(bpy.types.Operator, Operator): diff --git a/src/blenderbim/blenderbim/bim/module/system/ui.py b/src/blenderbim/blenderbim/bim/module/system/ui.py index c59b41c043..643d10ea93 100644 --- a/src/blenderbim/blenderbim/bim/module/system/ui.py +++ b/src/blenderbim/blenderbim/bim/module/system/ui.py @@ -23,6 +23,14 @@ from blenderbim.bim.ifc import IfcStore from blenderbim.bim.module.system.data import SystemData, ObjectSystemData, PortData +FLOW_DIRECTION_TO_ICON = { + "SOURCE": "FORWARD", + "SINK": "BACK", + "SOURCEANDSINK": "ARROW_LEFTRIGHT", + "NOTDEFINED": "RESTRICT_INSTANCED_ON", +} + + class BIM_PT_systems(Panel): bl_label = "Systems" bl_idname = "BIM_PT_systems" @@ -156,11 +164,43 @@ class BIM_PT_ports(Panel): self.props = context.scene.BIMSystemProperties row = self.layout.row(align=True) - row.label(text=f"{PortData.data['total_ports']} Ports Found", icon="PLUGIN") + total_ports = PortData.data["total_ports"] + row.label(text=f"{total_ports} Ports Found", icon="PLUGIN") row.operator("bim.show_ports", icon="HIDE_OFF", text="") row.operator("bim.hide_ports", icon="HIDE_ON", text="") row.operator("bim.add_port", icon="ADD", text="") + if total_ports == 0: + return + + row = self.layout.row(align=True) + row.label(text="Ports located on object and connected objects:") + row = self.layout.row(align=True) + cols = [row.column(align=True) for i in range(6)] + + for i, port_data in enumerate(PortData.data["located_ports_data"]): + port, port_obj, connected_obj = port_data + flow_direction_icon = FLOW_DIRECTION_TO_ICON[port.FlowDirection or "NOTDEFINED"] + if port_obj: + cols[0].label(text="", icon=flow_direction_icon) + cols[1].operator("bim.select_entity", text="", icon="RESTRICT_SELECT_OFF").ifc_id = port.id() + cols[2].label(text=port_obj.name) + else: + cols[0].label(text="", icon=flow_direction_icon) + cols[1].label(text="", icon="HIDE_ON") + cols[2].label(text="Port is hidden") + + if connected_obj: + cols[3].operator("bim.disconnect_port", text="", icon="UNLINKED").element_id = port.id() + cols[4].operator( + "bim.select_entity", text="", icon="RESTRICT_SELECT_OFF" + ).ifc_id = connected_obj.BIMObjectProperties.ifc_definition_id + cols[5].label(text=f"{connected_obj.name}") + else: + cols[3].label(text="", icon="UNLINKED") + cols[4].label(text="", icon="BLANK1") + cols[5].label(text="Port is disconnected") + class BIM_PT_port(Panel): bl_label = "Port" @@ -184,36 +224,56 @@ class BIM_PT_port(Panel): def draw(self, context): self.props = context.scene.BIMSystemProperties - element = tool.Ifc.get_entity(context.active_object) - port_class = element.is_a() layout = self.layout row = layout.row(align=True) - row.label(text=port_class) + row.label(text="IfcDistributionPort") row.operator("bim.connect_port", icon="PLUGIN", text="") row.operator("bim.disconnect_port", icon="UNLINKED", text="") row.operator("bim.remove_port", icon="X", text="") - if port_class == "IfcDistributionPort": - current_flow_direction = str(element.FlowDirection) - row = layout.row(align=True) - row.label(text="Flow Direction:") - row.label(text=current_flow_direction) + if not PortData.is_loaded: + PortData.load() - # TODO: replace with enum property? - flow_directions = ( - ("SOURCE", "FORWARD"), - ("SINK", "BACK"), - ("SOURCEANDSINK", "ARROW_LEFTRIGHT"), - ("NOTDEFINED", "RESTRICT_INSTANCED_ON"), - ) + if not PortData.data["is_port"]: + return - row = layout.row(align=True) - row.label(text="Change Flow Direction:") - for flow_direction, icon in flow_directions: - row = layout.row() - row.operator("bim.set_flow_direction", icon=icon, text=flow_direction).direction = flow_direction - if flow_direction == current_flow_direction: - row.enabled = False + element = tool.Ifc.get_entity(context.active_object) + current_flow_direction = str(element.FlowDirection) + row = layout.row(align=True) + row.label(text="Flow Direction:") + row.label(text=current_flow_direction) + + # port located on + row = layout.row(align=True) + relating_object = PortData.data["port_relating_object"] + row.label(text="Port located on:") + row.label(text=relating_object.name) + row.operator( + "bim.select_entity", text="", icon="RESTRICT_SELECT_OFF" + ).ifc_id = relating_object.BIMObjectProperties.ifc_definition_id + + # object connected to the port + row = layout.row(align=True) + connected_object = PortData.data["port_connected_object"] + if connected_object: + row.label(text="Port connected to:") + row.label(text=connected_object.name) + row.operator( + "bim.select_entity", text="", icon="RESTRICT_SELECT_OFF" + ).ifc_id = connected_object.BIMObjectProperties.ifc_definition_id + else: + row.label(text="Port is not connected to any element") + + # TODO: replace with enum property? + row = layout.row(align=True) + row.label(text="Change Flow Direction:") + for flow_direction in FLOW_DIRECTION_TO_ICON.keys(): + row = layout.row() + row.operator( + "bim.set_flow_direction", icon=FLOW_DIRECTION_TO_ICON[flow_direction], text=flow_direction + ).direction = flow_direction + if flow_direction == current_flow_direction: + row.enabled = False class BIM_UL_systems(UIList):