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