Fix #3095. Very basic implementation of a new zones panel.

This commit is contained in:
Dion Moult
2023-10-20 17:51:30 +11:00
parent 4f64dcdbd4
commit f3b541f00a
7 changed files with 253 additions and 8 deletions
@@ -150,6 +150,7 @@ classes = [
# Services and systems # Services and systems
ui.BIM_PT_tab_services, ui.BIM_PT_tab_services,
ui.BIM_PT_tab_services_object, ui.BIM_PT_tab_services_object,
ui.BIM_PT_tab_zones,
# Structural analysis # Structural analysis
ui.BIM_PT_tab_structural, ui.BIM_PT_tab_structural,
# Construction scheduling # Construction scheduling
@@ -22,38 +22,52 @@ from . import ui, prop, operator, decorator
classes = ( classes = (
operator.AddPort, operator.AddPort,
operator.AddSystem, operator.AddSystem,
operator.AddZone,
operator.AssignSystem, operator.AssignSystem,
operator.ConnectPort, operator.ConnectPort,
operator.DisableEditingSystem, operator.DisableEditingSystem,
operator.DisableEditingZone,
operator.DisableSystemEditingUI, operator.DisableSystemEditingUI,
operator.DisconnectPort, operator.DisconnectPort,
operator.EditSystem, operator.EditSystem,
operator.EditZone,
operator.EnableEditingSystem, operator.EnableEditingSystem,
operator.EnableEditingZone,
operator.HidePorts, operator.HidePorts,
operator.LoadSystems, operator.LoadSystems,
operator.LoadZones,
operator.MEPConnectElements,
operator.RemovePort, operator.RemovePort,
operator.RemoveSystem, operator.RemoveSystem,
operator.RemoveZone,
operator.SelectSystemProducts, operator.SelectSystemProducts,
operator.MEPConnectElements,
operator.SetFlowDirection, operator.SetFlowDirection,
operator.ShowPorts, operator.ShowPorts,
operator.UnassignSystem, operator.UnassignSystem,
operator.UnloadZones,
prop.System, prop.System,
prop.Zone,
prop.BIMSystemProperties, prop.BIMSystemProperties,
prop.BIMZoneProperties,
ui.BIM_PT_systems, ui.BIM_PT_systems,
ui.BIM_PT_object_systems, ui.BIM_PT_object_systems,
ui.BIM_PT_zones,
ui.BIM_PT_active_object_zones,
ui.BIM_PT_ports, ui.BIM_PT_ports,
ui.BIM_PT_port, ui.BIM_PT_port,
ui.BIM_UL_systems, ui.BIM_UL_systems,
ui.BIM_UL_object_systems, ui.BIM_UL_object_systems,
ui.BIM_UL_zones,
) )
def register(): def register():
bpy.types.Scene.BIMSystemProperties = bpy.props.PointerProperty(type=prop.BIMSystemProperties) bpy.types.Scene.BIMSystemProperties = bpy.props.PointerProperty(type=prop.BIMSystemProperties)
bpy.types.Scene.BIMZoneProperties = bpy.props.PointerProperty(type=prop.BIMZoneProperties)
bpy.app.handlers.load_post.append(decorator.toggle_decorations_on_load) bpy.app.handlers.load_post.append(decorator.toggle_decorations_on_load)
def unregister(): def unregister():
del bpy.types.Scene.BIMSystemProperties del bpy.types.Scene.BIMSystemProperties
del bpy.types.Scene.BIMZoneProperties
bpy.app.handlers.load_post.remove(decorator.toggle_decorations_on_load) bpy.app.handlers.load_post.remove(decorator.toggle_decorations_on_load)
@@ -25,6 +25,8 @@ import blenderbim.tool as tool
def refresh(): def refresh():
SystemData.is_loaded = False SystemData.is_loaded = False
ZonesData.is_loaded = False
ActiveObjectZonesData.is_loaded = False
ObjectSystemData.is_loaded = False ObjectSystemData.is_loaded = False
PortData.is_loaded = False PortData.is_loaded = False
SystemDecorationData.is_loaded = False SystemDecorationData.is_loaded = False
@@ -47,8 +49,6 @@ class SystemData:
declaration = tool.Ifc.schema().declaration_by_name("IfcSystem") declaration = tool.Ifc.schema().declaration_by_name("IfcSystem")
declarations = ifcopenshell.util.schema.get_subtypes(declaration) declarations = ifcopenshell.util.schema.get_subtypes(declaration)
version = tool.Ifc.get_schema() version = tool.Ifc.get_schema()
if version == "IFC2X3":
declarations += [tool.Ifc.schema().declaration_by_name("IfcZone")]
# We're only interested in systems for services. Not sure why IFC groups these together. # We're only interested in systems for services. Not sure why IFC groups these together.
return [ return [
@@ -193,3 +193,32 @@ class SystemDecorationData:
ports_data.append(port_data) ports_data.append(port_data)
cls.elements_ports_positions[element] = ports_data cls.elements_ports_positions[element] = ports_data
return cls.elements_ports_positions[element] return cls.elements_ports_positions[element]
class ZonesData:
data = {}
is_loaded = False
@classmethod
def load(cls):
cls.data = { "total_zones": cls.total_zones() }
cls.is_loaded = True
@classmethod
def total_zones(cls):
return len(tool.Ifc.get().by_type("IfcZone"))
class ActiveObjectZonesData:
data = {}
is_loaded = False
@classmethod
def load(cls):
cls.data = { "zones": cls.zones() }
cls.is_loaded = True
@classmethod
def zones(cls):
systems = ifcopenshell.util.system.get_element_systems(tool.Ifc.get_entity(bpy.context.active_object))
return [s.Name or "Unnamed" for s in systems if s.is_a("IfcZone")]
@@ -21,6 +21,7 @@ import ifcopenshell.api
import blenderbim.tool as tool import blenderbim.tool as tool
import blenderbim.core.system as core import blenderbim.core.system as core
import blenderbim.bim.handler import blenderbim.bim.handler
import blenderbim.bim.helper
from blenderbim.bim.ifc import IfcStore from blenderbim.bim.ifc import IfcStore
from blenderbim.bim.module.system.data import PortData from blenderbim.bim.module.system.data import PortData
from mathutils import Matrix from mathutils import Matrix
@@ -326,3 +327,97 @@ class SetFlowDirection(bpy.types.Operator, Operator):
self.report({"ERROR"}, "Selected elements are not connected to set the flow direction") self.report({"ERROR"}, "Selected elements are not connected to set the flow direction")
return {"CANCELLED"} return {"CANCELLED"}
class LoadZones(bpy.types.Operator, Operator):
bl_idname = "bim.load_zones"
bl_label = "Load Zones"
bl_options = {"REGISTER", "UNDO"}
def _execute(self, context):
props = bpy.context.scene.BIMZoneProperties
props.zones.clear()
for zone in tool.Ifc.get().by_type("IfcZone"):
new = props.zones.add()
new.ifc_definition_id = zone.id()
new.name = zone.Name or "Unnamed"
props.is_loaded = True
props.is_editing = 0
class UnloadZones(bpy.types.Operator, Operator):
bl_idname = "bim.unload_zones"
bl_label = "Unload Zones"
bl_options = {"REGISTER", "UNDO"}
def _execute(self, context):
props = bpy.context.scene.BIMZoneProperties
props.is_loaded = False
class AddZone(bpy.types.Operator, Operator):
bl_idname = "bim.add_zone"
bl_label = "Add Zone"
bl_options = {"REGISTER", "UNDO"}
name: bpy.props.StringProperty()
def invoke(self, context, event):
return context.window_manager.invoke_props_dialog(self)
def draw(self, context):
row = self.layout
row.prop(self, "name", text="Name")
def _execute(self, context):
element = ifcopenshell.api.run("system.add_system", tool.Ifc.get(), ifc_class="IfcZone")
if self.name:
element.Name = self.name
bpy.ops.bim.load_zones()
class EnableEditingZone(bpy.types.Operator, Operator):
bl_idname = "bim.enable_editing_zone"
bl_label = "Enable Editing Zone"
bl_options = {"REGISTER", "UNDO"}
zone: bpy.props.IntProperty()
def _execute(self, context):
props = bpy.context.scene.BIMZoneProperties
props.attributes.clear()
blenderbim.bim.helper.import_attributes2(tool.Ifc.get().by_id(self.zone), props.attributes)
props.is_editing = self.zone
class DisableEditingZone(bpy.types.Operator, Operator):
bl_idname = "bim.disable_editing_zone"
bl_label = "Disable Editing Zone"
bl_options = {"REGISTER", "UNDO"}
def _execute(self, context):
props = bpy.context.scene.BIMZoneProperties
props.is_editing = 0
class EditZone(bpy.types.Operator, Operator):
bl_idname = "bim.edit_zone"
bl_label = "Edit Zone"
bl_options = {"REGISTER", "UNDO"}
def _execute(self, context):
props = bpy.context.scene.BIMZoneProperties
zone = tool.Ifc.get().by_id(props.is_editing)
attributes = blenderbim.bim.helper.export_attributes(props.attributes)
ifcopenshell.api.run("system.edit_system", tool.Ifc.get(), system=zone, attributes=attributes)
props.is_editing = 0
bpy.ops.bim.load_zones()
class RemoveZone(bpy.types.Operator, Operator):
bl_idname = "bim.remove_zone"
bl_label = "Remove Zone"
bl_options = {"REGISTER", "UNDO"}
zone: bpy.props.IntProperty()
def _execute(self, context):
ifcopenshell.api.run("system.remove_system", tool.Ifc.get(), system=tool.Ifc.get().by_id(self.zone))
bpy.ops.bim.load_zones()
@@ -45,6 +45,11 @@ class System(PropertyGroup):
ifc_definition_id: IntProperty(name="IFC Definition ID") ifc_definition_id: IntProperty(name="IFC Definition ID")
class Zone(PropertyGroup):
name: StringProperty(name="Name")
ifc_definition_id: IntProperty(name="IFC Definition ID")
def toggle_decorations(self, context): def toggle_decorations(self, context):
toggle = self.should_draw_decorations toggle = self.should_draw_decorations
if toggle: if toggle:
@@ -64,3 +69,11 @@ class BIMSystemProperties(PropertyGroup):
should_draw_decorations: BoolProperty( should_draw_decorations: BoolProperty(
name="Should Draw Decorations", description="Toggle system decorations", update=toggle_decorations name="Should Draw Decorations", description="Toggle system decorations", update=toggle_decorations
) )
class BIMZoneProperties(PropertyGroup):
attributes: CollectionProperty(name="Attributes", type=Attribute)
is_loaded: BoolProperty(name="Is Loaded", default=False)
is_editing: IntProperty(name="Is Editing", default=0)
zones: CollectionProperty(name="Zones", type=Zone)
active_zone_index: IntProperty(name="Active Zone Index")
@@ -16,11 +16,11 @@
# You should have received a copy of the GNU General Public License # You should have received a copy of the GNU General Public License
# along with BlenderBIM Add-on. If not, see <http://www.gnu.org/licenses/>. # along with BlenderBIM Add-on. If not, see <http://www.gnu.org/licenses/>.
from blenderbim.bim.helper import prop_with_search import blenderbim.bim.helper
import blenderbim.tool as tool import blenderbim.tool as tool
from blenderbim.bim.helper import prop_with_search
from bpy.types import Panel, UIList from bpy.types import Panel, UIList
from blenderbim.bim.ifc import IfcStore from blenderbim.bim.module.system.data import SystemData, ZonesData, ActiveObjectZonesData, ObjectSystemData, PortData
from blenderbim.bim.module.system.data import SystemData, ObjectSystemData, PortData
FLOW_DIRECTION_TO_ICON = { FLOW_DIRECTION_TO_ICON = {
@@ -42,7 +42,7 @@ class BIM_PT_systems(Panel):
@classmethod @classmethod
def poll(cls, context): def poll(cls, context):
return IfcStore.get_file() return tool.Ifc.get()
def draw(self, context): def draw(self, context):
if not SystemData.is_loaded: if not SystemData.is_loaded:
@@ -95,7 +95,7 @@ class BIM_PT_object_systems(Panel):
def poll(cls, context): def poll(cls, context):
if not context.active_object: if not context.active_object:
return False return False
return IfcStore.get_file() and context.active_object.BIMObjectProperties.ifc_definition_id return tool.Ifc.get() and context.active_object.BIMObjectProperties.ifc_definition_id
def draw(self, context): def draw(self, context):
if not ObjectSystemData.is_loaded: if not ObjectSystemData.is_loaded:
@@ -294,6 +294,78 @@ class BIM_PT_port(Panel):
).direction = flow_direction ).direction = flow_direction
class BIM_PT_zones(Panel):
bl_label = "Zones"
bl_idname = "BIM_PT_zones"
bl_options = {"HIDE_HEADER"}
bl_space_type = "PROPERTIES"
bl_region_type = "WINDOW"
bl_context = "scene"
bl_parent_id = "BIM_PT_tab_zones"
@classmethod
def poll(cls, context):
return tool.Ifc.get()
def draw(self, context):
if not ZonesData.is_loaded:
ZonesData.load()
self.props = context.scene.BIMZoneProperties
row = self.layout.row(align=True)
row.label(text="{} Zones Found".format(ZonesData.data["total_zones"]), icon="SEQ_STRIP_META")
if not self.props.is_loaded:
row.operator("bim.load_zones", text="", icon="GREASEPENCIL")
return
row.operator("bim.add_zone", text="", icon="ADD")
row.operator("bim.unload_zones", text="", icon="CANCEL")
if self.props.zones and self.props.active_zone_index < len(self.props.zones):
row = self.layout.row(align=True)
ifc_definition_id = self.props.zones[self.props.active_zone_index].ifc_definition_id
row.operator("bim.enable_editing_zone", text="Edit Zone", icon="GREASEPENCIL").zone = ifc_definition_id
row.operator("bim.select_system_products", text="", icon="RESTRICT_SELECT_OFF").system = ifc_definition_id
row.operator("bim.assign_system", text="", icon="KEYFRAME_HLT").system = ifc_definition_id
row.operator("bim.unassign_system", text="", icon="KEYFRAME").system = ifc_definition_id
row.operator("bim.remove_zone", text="", icon="X").zone = ifc_definition_id
self.layout.template_list("BIM_UL_zones", "", self.props, "zones", self.props, "active_zone_index")
if self.props.is_editing:
blenderbim.bim.helper.draw_attributes(self.props.attributes, self.layout)
row = self.layout.row(align=True)
row.operator("bim.edit_zone", icon="CHECKMARK")
row.operator("bim.disable_editing_zone", icon="CANCEL", text="")
class BIM_PT_active_object_zones(Panel):
bl_label = "Active Object Zones"
bl_idname = "BIM_PT_active_object_zones"
bl_space_type = "PROPERTIES"
bl_region_type = "WINDOW"
bl_context = "scene"
bl_parent_id = "BIM_PT_tab_zones"
@classmethod
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()
self.props = context.scene.BIMZoneProperties
for zone in ActiveObjectZonesData.data["zones"]:
row = self.layout.row()
row.label(text=zone, icon="SEQ_STRIP_META")
if not ActiveObjectZonesData.data["zones"]:
row = self.layout.row()
row.label(text="Active Object Has No Zones")
class BIM_UL_systems(UIList): class BIM_UL_systems(UIList):
def draw_item(self, context, layout, data, item, icon, active_data, active_propname): def draw_item(self, context, layout, data, item, icon, active_data, active_propname):
system_icons = { system_icons = {
@@ -341,3 +413,10 @@ class BIM_UL_object_systems(UIList):
row = layout.row(align=True) row = layout.row(align=True)
row.label(text=item.name, icon=system_icons[item.ifc_class]) row.label(text=item.name, icon=system_icons[item.ifc_class])
row.operator("bim.assign_system", text="", icon="ADD").system = item.ifc_definition_id row.operator("bim.assign_system", text="", icon="ADD").system = item.ifc_definition_id
class BIM_UL_zones(UIList):
def draw_item(self, context, layout, data, item, icon, active_data, active_propname):
if item:
row = layout.row(align=True)
row.label(text=item.name)
+14
View File
@@ -495,6 +495,20 @@ class BIM_PT_tab_services(Panel):
pass pass
class BIM_PT_tab_zones(Panel):
bl_label = "Zones"
bl_space_type = "PROPERTIES"
bl_region_type = "WINDOW"
bl_context = "scene"
@classmethod
def poll(cls, context):
return tool.Blender.is_tab(context, "SERVICES") and tool.Ifc.get()
def draw(self, context):
pass
class BIM_PT_tab_quality_control(Panel): class BIM_PT_tab_quality_control(Panel):
bl_label = "Quality Control" bl_label = "Quality Control"
bl_space_type = "PROPERTIES" bl_space_type = "PROPERTIES"