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 91c7fe4628
commit 5bb04010ae
7 changed files with 253 additions and 8 deletions
@@ -150,6 +150,7 @@ classes = [
# Services and systems
ui.BIM_PT_tab_services,
ui.BIM_PT_tab_services_object,
ui.BIM_PT_tab_zones,
# Structural analysis
ui.BIM_PT_tab_structural,
# Construction scheduling
@@ -22,38 +22,52 @@ from . import ui, prop, operator, decorator
classes = (
operator.AddPort,
operator.AddSystem,
operator.AddZone,
operator.AssignSystem,
operator.ConnectPort,
operator.DisableEditingSystem,
operator.DisableEditingZone,
operator.DisableSystemEditingUI,
operator.DisconnectPort,
operator.EditSystem,
operator.EditZone,
operator.EnableEditingSystem,
operator.EnableEditingZone,
operator.HidePorts,
operator.LoadSystems,
operator.LoadZones,
operator.MEPConnectElements,
operator.RemovePort,
operator.RemoveSystem,
operator.RemoveZone,
operator.SelectSystemProducts,
operator.MEPConnectElements,
operator.SetFlowDirection,
operator.ShowPorts,
operator.UnassignSystem,
operator.UnloadZones,
prop.System,
prop.Zone,
prop.BIMSystemProperties,
prop.BIMZoneProperties,
ui.BIM_PT_systems,
ui.BIM_PT_object_systems,
ui.BIM_PT_zones,
ui.BIM_PT_active_object_zones,
ui.BIM_PT_ports,
ui.BIM_PT_port,
ui.BIM_UL_systems,
ui.BIM_UL_object_systems,
ui.BIM_UL_zones,
)
def register():
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)
def unregister():
del bpy.types.Scene.BIMSystemProperties
del bpy.types.Scene.BIMZoneProperties
bpy.app.handlers.load_post.remove(decorator.toggle_decorations_on_load)
@@ -25,6 +25,8 @@ import blenderbim.tool as tool
def refresh():
SystemData.is_loaded = False
ZonesData.is_loaded = False
ActiveObjectZonesData.is_loaded = False
ObjectSystemData.is_loaded = False
PortData.is_loaded = False
SystemDecorationData.is_loaded = False
@@ -47,8 +49,6 @@ class SystemData:
declaration = tool.Ifc.schema().declaration_by_name("IfcSystem")
declarations = ifcopenshell.util.schema.get_subtypes(declaration)
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.
return [
@@ -193,3 +193,32 @@ class SystemDecorationData:
ports_data.append(port_data)
cls.elements_ports_positions[element] = ports_data
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.core.system as core
import blenderbim.bim.handler
import blenderbim.bim.helper
from blenderbim.bim.ifc import IfcStore
from blenderbim.bim.module.system.data import PortData
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")
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")
class Zone(PropertyGroup):
name: StringProperty(name="Name")
ifc_definition_id: IntProperty(name="IFC Definition ID")
def toggle_decorations(self, context):
toggle = self.should_draw_decorations
if toggle:
@@ -64,3 +69,11 @@ class BIMSystemProperties(PropertyGroup):
should_draw_decorations: BoolProperty(
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
# 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
from blenderbim.bim.helper import prop_with_search
from bpy.types import Panel, UIList
from blenderbim.bim.ifc import IfcStore
from blenderbim.bim.module.system.data import SystemData, ObjectSystemData, PortData
from blenderbim.bim.module.system.data import SystemData, ZonesData, ActiveObjectZonesData, ObjectSystemData, PortData
FLOW_DIRECTION_TO_ICON = {
@@ -42,7 +42,7 @@ class BIM_PT_systems(Panel):
@classmethod
def poll(cls, context):
return IfcStore.get_file()
return tool.Ifc.get()
def draw(self, context):
if not SystemData.is_loaded:
@@ -95,7 +95,7 @@ class BIM_PT_object_systems(Panel):
def poll(cls, context):
if not context.active_object:
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):
if not ObjectSystemData.is_loaded:
@@ -294,6 +294,78 @@ class BIM_PT_port(Panel):
).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):
def draw_item(self, context, layout, data, item, icon, active_data, active_propname):
system_icons = {
@@ -341,3 +413,10 @@ class BIM_UL_object_systems(UIList):
row = layout.row(align=True)
row.label(text=item.name, icon=system_icons[item.ifc_class])
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
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):
bl_label = "Quality Control"
bl_space_type = "PROPERTIES"