See #1848. Refactor sequence data class.

This commit is contained in:
Dion Moult
2023-01-31 20:31:26 +11:00
parent f01900bdb1
commit cd132d4fe9
4 changed files with 88 additions and 46 deletions
@@ -23,6 +23,8 @@ import ifcopenshell
def refresh(): def refresh():
SequenceData.is_loaded = False SequenceData.is_loaded = False
WorkPlansData.is_loaded = False
TaskICOMData.is_loaded = False
class SequenceData: class SequenceData:
@@ -216,3 +218,62 @@ class SequenceData:
if rel.RelatingControl.is_a("IfcWorkCalendar"): if rel.RelatingControl.is_a("IfcWorkCalendar"):
data["HasAssignmentsWorkCalendar"].append(rel.RelatingControl.id()) data["HasAssignmentsWorkCalendar"].append(rel.RelatingControl.id())
cls.data["tasks"][task.id()] = data cls.data["tasks"][task.id()] = data
class WorkPlansData:
data = {}
is_loaded = False
@classmethod
def load(cls):
cls.data = {
"total_work_plans": cls.total_work_plans(),
"work_plans": cls.work_plans(),
"has_work_schedules": cls.has_work_schedules(),
"active_work_plan_schedules": cls.active_work_plan_schedules(),
}
cls.is_loaded = True
@classmethod
def total_work_plans(cls):
return len(tool.Ifc.get().by_type("IfcWorkPlan"))
@classmethod
def work_plans(cls):
results = []
for work_plan in tool.Ifc.get().by_type("IfcWorkPlan"):
results.append({"id": work_plan.id(), "name": work_plan.Name or "Unnamed"})
return results
@classmethod
def has_work_schedules(cls):
return len(tool.Ifc.get().by_type("IfcWorkSchedule"))
@classmethod
def active_work_plan_schedules(cls):
if not self.props.active_work_plan_id:
return []
for rel in tool.Ifc.get().by_id(self.props.active_work_plan_id).IsDecomposedBy:
for related_object in rel.RelatedObjects:
results.append({"id": work_schedule.id(), "name": work_schedule.Name or "Unnamed"})
return results
class TaskICOMData:
data = {}
is_loaded = False
@classmethod
def load(cls):
cls.data = {"can_active_resource_be_assigned": cls.can_active_resource_be_assigned()}
cls.is_loaded = True
@classmethod
def can_active_resource_be_assigned(cls):
resource_props = bpy.context.scene.BIMResourceProperties
resource_tprops = bpy.context.scene.BIMResourceTreeProperties
total_resources = len(resource_tprops.resources)
if total_resources and resource_props.active_resource_index < total_resources:
resource_id = resource_tprops.resources[resource_props.active_resource_index].ifc_definition_id
return not tool.Ifc.get().by_id(resource_id).is_a("IfcCrewResource")
return False
@@ -31,8 +31,6 @@ from datetime import datetime
from dateutil import parser, relativedelta from dateutil import parser, relativedelta
from blenderbim.bim.ifc import IfcStore from blenderbim.bim.ifc import IfcStore
from bpy_extras.io_utils import ImportHelper from bpy_extras.io_utils import ImportHelper
from ifcopenshell.api.sequence.data import Data
from ifcopenshell.api.resource.data import Data as ResourceData
class AddWorkPlan(bpy.types.Operator, tool.Ifc.Operator): class AddWorkPlan(bpy.types.Operator, tool.Ifc.Operator):
@@ -543,7 +541,6 @@ class ImportP6(bpy.types.Operator, ImportHelper):
p62ifc.file = self.file p62ifc.file = self.file
p62ifc.work_plan = self.file.by_type("IfcWorkPlan")[0] if self.file.by_type("IfcWorkPlan") else None p62ifc.work_plan = self.file.by_type("IfcWorkPlan")[0] if self.file.by_type("IfcWorkPlan") else None
p62ifc.execute() p62ifc.execute()
Data.load(IfcStore.get_file())
print("Import finished in {:.2f} seconds".format(time.time() - start)) print("Import finished in {:.2f} seconds".format(time.time() - start))
return {"FINISHED"} return {"FINISHED"}
@@ -570,7 +567,6 @@ class ImportP6XER(bpy.types.Operator, ImportHelper):
p6xer2ifc.file = self.file p6xer2ifc.file = self.file
p6xer2ifc.work_plan = self.file.by_type("IfcWorkPlan")[0] if self.file.by_type("IfcWorkPlan") else None p6xer2ifc.work_plan = self.file.by_type("IfcWorkPlan")[0] if self.file.by_type("IfcWorkPlan") else None
p6xer2ifc.execute() p6xer2ifc.execute()
Data.load(IfcStore.get_file())
print("Import finished in {:.2f} seconds".format(time.time() - start)) print("Import finished in {:.2f} seconds".format(time.time() - start))
return {"FINISHED"} return {"FINISHED"}
@@ -597,7 +593,6 @@ class ImportPP(bpy.types.Operator, ImportHelper):
pp2ifc.file = self.file pp2ifc.file = self.file
pp2ifc.work_plan = self.file.by_type("IfcWorkPlan")[0] if self.file.by_type("IfcWorkPlan") else None pp2ifc.work_plan = self.file.by_type("IfcWorkPlan")[0] if self.file.by_type("IfcWorkPlan") else None
pp2ifc.execute() pp2ifc.execute()
Data.load(IfcStore.get_file())
print("Import finished in {:.2f} seconds".format(time.time() - start)) print("Import finished in {:.2f} seconds".format(time.time() - start))
return {"FINISHED"} return {"FINISHED"}
@@ -624,7 +619,6 @@ class ImportMSP(bpy.types.Operator, ImportHelper):
msp2ifc.file = self.file msp2ifc.file = self.file
msp2ifc.work_plan = self.file.by_type("IfcWorkPlan")[0] if self.file.by_type("IfcWorkPlan") else None msp2ifc.work_plan = self.file.by_type("IfcWorkPlan")[0] if self.file.by_type("IfcWorkPlan") else None
msp2ifc.execute() msp2ifc.execute()
Data.load(IfcStore.get_file())
print("Import finished in {:.2f} seconds".format(time.time() - start)) print("Import finished in {:.2f} seconds".format(time.time() - start))
return {"FINISHED"} return {"FINISHED"}
@@ -1320,4 +1314,4 @@ class CopyTask(bpy.types.Operator):
def execute(self, context): def execute(self, context):
core.copy_task(tool.Ifc, tool.Sequence, task=tool.Ifc.get().by_id(self.task)) core.copy_task(tool.Ifc, tool.Sequence, task=tool.Ifc.get().by_id(self.task))
return {"FINISHED"} return {"FINISHED"}
@@ -21,7 +21,6 @@ import isodate
import ifcopenshell.api import ifcopenshell.api
import ifcopenshell.util.attribute import ifcopenshell.util.attribute
from blenderbim.bim.ifc import IfcStore from blenderbim.bim.ifc import IfcStore
from ifcopenshell.api.resource.data import Data as ResourceData
from blenderbim.bim.module.sequence.data import SequenceData from blenderbim.bim.module.sequence.data import SequenceData
import blenderbim.bim.module.pset.data import blenderbim.bim.module.pset.data
from blenderbim.bim.prop import StrProperty, Attribute from blenderbim.bim.prop import StrProperty, Attribute
@@ -21,8 +21,7 @@ import blenderbim.bim.helper
from bpy.types import Panel, UIList from bpy.types import Panel, UIList
from blenderbim.bim.ifc import IfcStore from blenderbim.bim.ifc import IfcStore
from blenderbim.bim.helper import draw_attributes from blenderbim.bim.helper import draw_attributes
from blenderbim.bim.module.sequence.data import SequenceData from blenderbim.bim.module.sequence.data import WorkPlansData, SequenceData, TaskICOMData
from ifcopenshell.api.resource.data import Data as ResourceData
class BIM_PT_work_plans(Panel): class BIM_PT_work_plans(Panel):
@@ -40,40 +39,37 @@ class BIM_PT_work_plans(Panel):
return file and file.schema != "IFC2X3" return file and file.schema != "IFC2X3"
def draw(self, context): def draw(self, context):
if not SequenceData.is_loaded: if not WorkPlansData.is_loaded:
SequenceData.load() WorkPlansData.load()
self.props = context.scene.BIMWorkPlanProperties self.props = context.scene.BIMWorkPlanProperties
row = self.layout.row() row = self.layout.row()
if SequenceData.data["has_work_plans"]: if WorkPlansData.data["total_work_plans"]:
row.label( row.label(text=f"{WorkPlansData.data['total_work_plans']} Work Plans Found", icon="TEXT")
text="{} Work Plans Found".format(SequenceData.data["number_of_work_plans_loaded"]),
icon="TEXT",
)
else: else:
row.label(text="No Work Plans found.", icon="TEXT") row.label(text="No Work Plans found.", icon="TEXT")
row.operator("bim.add_work_plan", icon="ADD", text="") row.operator("bim.add_work_plan", icon="ADD", text="")
for work_plan_id, work_plan in SequenceData.data["work_plans"].items(): for work_plan in WorkPlansData.data["work_plans"]:
self.draw_work_plan_ui(work_plan_id, work_plan) self.draw_work_plan_ui(work_plan)
def draw_work_plan_ui(self, work_plan_id, work_plan): def draw_work_plan_ui(self, work_plan):
row = self.layout.row(align=True) row = self.layout.row(align=True)
row.label(text=work_plan["Name"] or "Unnamed", icon="TEXT") row.label(text=work_plan["name"], icon="TEXT")
if self.props.active_work_plan_id == work_plan_id: if self.props.active_work_plan_id == work_plan["id"]:
if self.props.editing_type == "ATTRIBUTES": if self.props.editing_type == "ATTRIBUTES":
row.operator("bim.edit_work_plan", text="", icon="CHECKMARK") row.operator("bim.edit_work_plan", text="", icon="CHECKMARK")
row.operator("bim.disable_editing_work_plan", text="", icon="CANCEL") row.operator("bim.disable_editing_work_plan", text="", icon="CANCEL")
elif self.props.active_work_plan_id: elif self.props.active_work_plan_id:
row.operator("bim.remove_work_plan", text="", icon="X").work_plan = work_plan_id row.operator("bim.remove_work_plan", text="", icon="X").work_plan = work_plan["id"]
else: else:
op = row.operator("bim.enable_editing_work_plan_schedules", text="", icon="LINENUMBERS_ON") op = row.operator("bim.enable_editing_work_plan_schedules", text="", icon="LINENUMBERS_ON")
op.work_plan = work_plan_id op.work_plan = work_plan["id"]
op = row.operator("bim.enable_editing_work_plan", text="", icon="GREASEPENCIL") op = row.operator("bim.enable_editing_work_plan", text="", icon="GREASEPENCIL")
op.work_plan = work_plan_id op.work_plan = work_plan["id"]
row.operator("bim.remove_work_plan", text="", icon="X").work_plan = work_plan_id row.operator("bim.remove_work_plan", text="", icon="X").work_plan = work_plan["id"]
if self.props.active_work_plan_id == work_plan_id: if self.props.active_work_plan_id == work_plan["id"]:
if self.props.editing_type == "ATTRIBUTES": if self.props.editing_type == "ATTRIBUTES":
self.draw_editable_ui() self.draw_editable_ui()
elif self.props.editing_type == "SCHEDULES": elif self.props.editing_type == "SCHEDULES":
@@ -83,22 +79,18 @@ class BIM_PT_work_plans(Panel):
draw_attributes(self.props.work_plan_attributes, self.layout) draw_attributes(self.props.work_plan_attributes, self.layout)
def draw_work_schedule_ui(self): def draw_work_schedule_ui(self):
if not SequenceData.is_loaded: if WorkPlansData.data["has_work_schedules"]:
SequenceData.load()
if SequenceData.data["has_work_schedules"]:
row = self.layout.row(align=True) row = self.layout.row(align=True)
row.prop(self.props, "work_schedules", text="") row.prop(self.props, "work_schedules", text="")
op = row.operator("bim.assign_work_schedule", text="", icon="ADD") op = row.operator("bim.assign_work_schedule", text="", icon="ADD")
op.work_plan = self.props.active_work_plan_id op.work_plan = self.props.active_work_plan_id
op.work_schedule = int(self.props.work_schedules) op.work_schedule = int(self.props.work_schedules)
for work_schedule_id in SequenceData.data["work_plans"][self.props.active_work_plan_id]["IsDecomposedBy"]: for work_schedule in WorkPlansData.data["active_work_plan_schedules"]:
work_schedule = SequenceData.data["work_schedules"][work_schedule_id]
row = self.layout.row(align=True) row = self.layout.row(align=True)
row.label(text=work_schedule["Name"] or "Unnamed", icon="LINENUMBERS_ON") row.label(text=work_schedule["name"], icon="LINENUMBERS_ON")
op = row.operator("bim.unassign_work_schedule", text="", icon="X") op = row.operator("bim.unassign_work_schedule", text="", icon="X")
op.work_plan = self.props.active_work_plan_id op.work_plan = self.props.active_work_plan_id
op.work_schedule = int(self.props.work_schedules) op.work_schedule = work_schedule["id"]
else: else:
row = self.layout.row() row = self.layout.row()
row.label(text="No schedules found. See Work Schedule Panel", icon="INFO") row.label(text="No schedules found. See Work Schedule Panel", icon="INFO")
@@ -409,6 +401,9 @@ class BIM_PT_task_icom(Panel):
return False return False
def draw(self, context): def draw(self, context):
if not TaskICOMData.is_loaded:
TaskICOMData.load()
self.props = context.scene.BIMWorkScheduleProperties self.props = context.scene.BIMWorkScheduleProperties
self.tprops = context.scene.BIMTaskTreeProperties self.tprops = context.scene.BIMTaskTreeProperties
task = self.tprops.tasks[self.props.active_task_index] task = self.tprops.tasks[self.props.active_task_index]
@@ -449,17 +444,10 @@ class BIM_PT_task_icom(Panel):
op = row2.operator("bim.calculate_task_duration", text="", icon="TEMP") op = row2.operator("bim.calculate_task_duration", text="", icon="TEMP")
op.task = task.ifc_definition_id op.task = task.ifc_definition_id
resource_props = context.scene.BIMResourceProperties if TaskICOMData.data["can_active_resource_be_assigned"]:
resource_tprops = context.scene.BIMResourceTreeProperties op = row2.operator("bim.assign_process", icon="ADD", text="")
total_resources = len(resource_tprops.resources) op.task = task.ifc_definition_id
if total_resources and context.scene.BIMResourceProperties.active_resource_index < total_resources: op.related_object_type = "RESOURCE"
resource_id = resource_tprops.resources[resource_props.active_resource_index].ifc_definition_id
ResourceData.load(IfcStore.get_file())
resource = ResourceData.resources[resource_id]
if resource["type"] != "IfcCrewResource":
op = row2.operator("bim.assign_process", icon="ADD", text="")
op.task = task.ifc_definition_id
op.related_object_type = "RESOURCE"
if total_task_resources and self.props.active_task_resource_index < total_task_resources: if total_task_resources and self.props.active_task_resource_index < total_task_resources:
op = row2.operator("bim.unassign_process", icon="REMOVE", text="") op = row2.operator("bim.unassign_process", icon="REMOVE", text="")