diff --git a/src/blenderbim/blenderbim/bim/module/sequence/data.py b/src/blenderbim/blenderbim/bim/module/sequence/data.py index 75d19b5e6f..7fa9c6c3be 100644 --- a/src/blenderbim/blenderbim/bim/module/sequence/data.py +++ b/src/blenderbim/blenderbim/bim/module/sequence/data.py @@ -23,6 +23,8 @@ import ifcopenshell def refresh(): SequenceData.is_loaded = False + WorkPlansData.is_loaded = False + TaskICOMData.is_loaded = False class SequenceData: @@ -216,3 +218,62 @@ class SequenceData: if rel.RelatingControl.is_a("IfcWorkCalendar"): data["HasAssignmentsWorkCalendar"].append(rel.RelatingControl.id()) 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 diff --git a/src/blenderbim/blenderbim/bim/module/sequence/operator.py b/src/blenderbim/blenderbim/bim/module/sequence/operator.py index 3b333fca6a..886aef58ee 100644 --- a/src/blenderbim/blenderbim/bim/module/sequence/operator.py +++ b/src/blenderbim/blenderbim/bim/module/sequence/operator.py @@ -31,8 +31,6 @@ from datetime import datetime from dateutil import parser, relativedelta from blenderbim.bim.ifc import IfcStore 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): @@ -543,7 +541,6 @@ class ImportP6(bpy.types.Operator, ImportHelper): p62ifc.file = self.file p62ifc.work_plan = self.file.by_type("IfcWorkPlan")[0] if self.file.by_type("IfcWorkPlan") else None p62ifc.execute() - Data.load(IfcStore.get_file()) print("Import finished in {:.2f} seconds".format(time.time() - start)) return {"FINISHED"} @@ -570,7 +567,6 @@ class ImportP6XER(bpy.types.Operator, ImportHelper): p6xer2ifc.file = self.file p6xer2ifc.work_plan = self.file.by_type("IfcWorkPlan")[0] if self.file.by_type("IfcWorkPlan") else None p6xer2ifc.execute() - Data.load(IfcStore.get_file()) print("Import finished in {:.2f} seconds".format(time.time() - start)) return {"FINISHED"} @@ -597,7 +593,6 @@ class ImportPP(bpy.types.Operator, ImportHelper): pp2ifc.file = self.file pp2ifc.work_plan = self.file.by_type("IfcWorkPlan")[0] if self.file.by_type("IfcWorkPlan") else None pp2ifc.execute() - Data.load(IfcStore.get_file()) print("Import finished in {:.2f} seconds".format(time.time() - start)) return {"FINISHED"} @@ -624,7 +619,6 @@ class ImportMSP(bpy.types.Operator, ImportHelper): msp2ifc.file = self.file msp2ifc.work_plan = self.file.by_type("IfcWorkPlan")[0] if self.file.by_type("IfcWorkPlan") else None msp2ifc.execute() - Data.load(IfcStore.get_file()) print("Import finished in {:.2f} seconds".format(time.time() - start)) return {"FINISHED"} @@ -1320,4 +1314,4 @@ class CopyTask(bpy.types.Operator): def execute(self, context): core.copy_task(tool.Ifc, tool.Sequence, task=tool.Ifc.get().by_id(self.task)) - return {"FINISHED"} \ No newline at end of file + return {"FINISHED"} diff --git a/src/blenderbim/blenderbim/bim/module/sequence/prop.py b/src/blenderbim/blenderbim/bim/module/sequence/prop.py index 6a4bb98c02..3e106d3f72 100644 --- a/src/blenderbim/blenderbim/bim/module/sequence/prop.py +++ b/src/blenderbim/blenderbim/bim/module/sequence/prop.py @@ -21,7 +21,6 @@ import isodate import ifcopenshell.api import ifcopenshell.util.attribute from blenderbim.bim.ifc import IfcStore -from ifcopenshell.api.resource.data import Data as ResourceData from blenderbim.bim.module.sequence.data import SequenceData import blenderbim.bim.module.pset.data from blenderbim.bim.prop import StrProperty, Attribute diff --git a/src/blenderbim/blenderbim/bim/module/sequence/ui.py b/src/blenderbim/blenderbim/bim/module/sequence/ui.py index cd68492df0..f84fd9ce92 100644 --- a/src/blenderbim/blenderbim/bim/module/sequence/ui.py +++ b/src/blenderbim/blenderbim/bim/module/sequence/ui.py @@ -21,8 +21,7 @@ import blenderbim.bim.helper from bpy.types import Panel, UIList from blenderbim.bim.ifc import IfcStore from blenderbim.bim.helper import draw_attributes -from blenderbim.bim.module.sequence.data import SequenceData -from ifcopenshell.api.resource.data import Data as ResourceData +from blenderbim.bim.module.sequence.data import WorkPlansData, SequenceData, TaskICOMData class BIM_PT_work_plans(Panel): @@ -40,40 +39,37 @@ class BIM_PT_work_plans(Panel): return file and file.schema != "IFC2X3" def draw(self, context): - if not SequenceData.is_loaded: - SequenceData.load() + if not WorkPlansData.is_loaded: + WorkPlansData.load() self.props = context.scene.BIMWorkPlanProperties row = self.layout.row() - if SequenceData.data["has_work_plans"]: - row.label( - text="{} Work Plans Found".format(SequenceData.data["number_of_work_plans_loaded"]), - icon="TEXT", - ) + if WorkPlansData.data["total_work_plans"]: + row.label(text=f"{WorkPlansData.data['total_work_plans']} Work Plans Found", icon="TEXT") else: row.label(text="No Work Plans found.", icon="TEXT") row.operator("bim.add_work_plan", icon="ADD", text="") - for work_plan_id, work_plan in SequenceData.data["work_plans"].items(): - self.draw_work_plan_ui(work_plan_id, work_plan) + for work_plan in WorkPlansData.data["work_plans"]: + 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.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": row.operator("bim.edit_work_plan", text="", icon="CHECKMARK") row.operator("bim.disable_editing_work_plan", text="", icon="CANCEL") 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: 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.work_plan = work_plan_id - row.operator("bim.remove_work_plan", text="", icon="X").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"] - 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": self.draw_editable_ui() 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) def draw_work_schedule_ui(self): - if not SequenceData.is_loaded: - SequenceData.load() - - if SequenceData.data["has_work_schedules"]: + if WorkPlansData.data["has_work_schedules"]: row = self.layout.row(align=True) row.prop(self.props, "work_schedules", text="") op = row.operator("bim.assign_work_schedule", text="", icon="ADD") op.work_plan = self.props.active_work_plan_id op.work_schedule = int(self.props.work_schedules) - for work_schedule_id in SequenceData.data["work_plans"][self.props.active_work_plan_id]["IsDecomposedBy"]: - work_schedule = SequenceData.data["work_schedules"][work_schedule_id] + for work_schedule in WorkPlansData.data["active_work_plan_schedules"]: 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.work_plan = self.props.active_work_plan_id - op.work_schedule = int(self.props.work_schedules) + op.work_schedule = work_schedule["id"] else: row = self.layout.row() row.label(text="No schedules found. See Work Schedule Panel", icon="INFO") @@ -409,6 +401,9 @@ class BIM_PT_task_icom(Panel): return False def draw(self, context): + if not TaskICOMData.is_loaded: + TaskICOMData.load() + self.props = context.scene.BIMWorkScheduleProperties self.tprops = context.scene.BIMTaskTreeProperties 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.task = task.ifc_definition_id - resource_props = context.scene.BIMResourceProperties - resource_tprops = context.scene.BIMResourceTreeProperties - total_resources = len(resource_tprops.resources) - if total_resources and context.scene.BIMResourceProperties.active_resource_index < total_resources: - 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 TaskICOMData.data["can_active_resource_be_assigned"]: + 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: op = row2.operator("bim.unassign_process", icon="REMOVE", text="")