See #1848. Some straggling refactoring for resource data.

This commit is contained in:
Dion Moult
2023-02-01 17:37:59 +11:00
parent b3c7971ea9
commit 7e16cb797f
3 changed files with 57 additions and 80 deletions
@@ -18,7 +18,6 @@
import bpy import bpy
import blenderbim.tool as tool import blenderbim.tool as tool
from ifcopenshell.api.cost.data import CostValueTrait
import ifcopenshell import ifcopenshell
@@ -26,7 +25,7 @@ def refresh():
ResourceData.is_loaded = False ResourceData.is_loaded = False
class ResourceData(CostValueTrait): class ResourceData:
data = {} data = {}
is_loaded = False is_loaded = False
cost_values = {} cost_values = {}
@@ -34,56 +33,49 @@ class ResourceData(CostValueTrait):
@classmethod @classmethod
def load(cls): def load(cls):
cls.data = { cls.data = {
"has_resources": cls.has_resources(), "total_resources": cls.total_resources(),
"resources": cls.resources(),
"active_resource_ids": cls.active_resource_ids(),
"cost_values": cls.cost_values(),
} }
cls.load_resources()
cls.is_loaded = True cls.is_loaded = True
@classmethod @classmethod
def has_resources(cls): def total_resources(cls):
return bool(tool.Ifc.get().by_type("IfcResource"))
@classmethod
def number_of_resources_loaded(cls):
return len(tool.Ifc.get().by_type("IfcResource")) return len(tool.Ifc.get().by_type("IfcResource"))
@classmethod @classmethod
def load_resources(cls): def resources(cls):
cls.data["resources"] = {} results = {}
for resource in tool.Ifc.get().by_type("IfcResource"): for resource in tool.Ifc.get().by_type("IfcResource"):
data = resource.get_info() base_quantity = None
del data["OwnerHistory"]
data["IsNestedBy"] = []
for rel in resource.IsNestedBy:
[data["IsNestedBy"].append(o.id()) for o in rel.RelatedObjects]
data["Nests"] = []
for rel in resource.Nests:
[data["Nests"].append(rel.RelatingObject.id())]
data["ResourceOf"] = []
for rel in resource.ResourceOf:
[data["ResourceOf"].append(o.id()) for o in rel.RelatedObjects]
data["HasContext"] = resource.HasContext[0].RelatingContext.id() if resource.HasContext else None
if resource.Usage:
data["Usage"] = data["Usage"].id()
data["TotalCostQuantity"] = cls.get_total_quantity(resource)
if resource.BaseQuantity: if resource.BaseQuantity:
data["BaseQuantity"] = resource.BaseQuantity.get_info() base_quantity = resource.BaseQuantity.get_info()
del data["BaseQuantity"]["Unit"] del base_quantity["Unit"]
if resource.BaseCosts: results[resource.id()] = {"type": resource.is_a(), "BaseQuantity": base_quantity}
data["BaseCosts"] = [e.id() for e in resource.BaseCosts] return results
cls.load_cost_values(resource, data)
cls.data["resources"][resource.id()] = data
cls.data["number_of_resources_loaded"] = cls.number_of_resources_loaded()
def load_resource_times(cls): @classmethod
cls.data["resource_times"] = {} def cost_values(cls):
for resource_time in tool.Ifc.get().by_type("IfcResourceTime"): results = []
data = resource_time.get_info() ifc_id = bpy.context.scene.BIMResourceProperties.active_resource_id
for key, value in data.items(): if not ifc_id:
if not value: return results
continue resource = tool.Ifc.get().by_id(ifc_id)
if "Start" in key or "Finish" in key or key == "StatusTime": for cost_value in resource.BaseCosts or []:
data[key] = ifcopenshell.util.date.ifc2datetime(value) label = "{0:.2f}".format(ifcopenshell.util.cost.calculate_applied_value(resource, cost_value))
elif "Work" in key or key == "LevelingDelay": label += " = {}".format(ifcopenshell.util.cost.serialise_cost_value(cost_value))
data[key] = ifcopenshell.util.date.ifc2datetime(value) results.append({"id": cost_value.id(), "label": label})
cls.data["resource_times"][resource_time.id()] = data return results
@classmethod
def active_resource_ids(cls):
obj = bpy.context.active_object
element = tool.Ifc.get_entity(obj)
if not element:
return []
results = []
for rel in getattr(element, "HasAssignments", []) or []:
if rel.is_a("IfcRelAssignsToResource"):
results.append(rel.RelatingResource.id())
return results
@@ -43,18 +43,15 @@ class BIM_PT_resources(Panel):
ResourceData.load() ResourceData.load()
row = self.layout.row(align=True) row = self.layout.row(align=True)
if ResourceData.data["has_resources"]: if ResourceData.data["total_resources"]:
row.label( row.label(text=f"{ResourceData.data['total_resources']} Resources Found", icon="TEXT")
text="{} Resources Found".format(ResourceData.data["number_of_resources_loaded"]),
icon="TEXT",
)
else: else:
row.label(text="No Resources found.", icon="COMMUNITY") row.label(text="No Resources found.", icon="COMMUNITY")
if self.props.is_editing: if self.props.is_editing:
row.operator("bim.disable_resource_editing_ui", text="", icon="CANCEL") row.operator("bim.disable_resource_editing_ui", text="", icon="CANCEL")
else: else:
row.operator("bim.load_resources", text="Load Resources", icon="GREASEPENCIL") row.operator("bim.load_resources", text="", icon="GREASEPENCIL")
row.operator("import_resources.bim", text="Import Resources", icon="IMPORT") row.operator("import_resources.bim", text="", icon="IMPORT")
if not self.props.is_editing: if not self.props.is_editing:
return return
@@ -170,25 +167,20 @@ class BIM_PT_resources(Panel):
if self.props.cost_types == "CATEGORY": if self.props.cost_types == "CATEGORY":
op.cost_category = self.props.cost_category op.cost_category = self.props.cost_category
for cost_value_id in ResourceData.data["resources"][self.props.active_resource_id]["BaseCosts"] or []: for cost_value in ResourceData.data["cost_values"]:
row = self.layout.row(align=True) row = self.layout.row(align=True)
self.draw_readonly_cost_value_ui(row, cost_value_id) self.draw_readonly_cost_value_ui(row, cost_value)
if self.props.cost_value_editing_type == "ATTRIBUTES": if self.props.cost_value_editing_type == "ATTRIBUTES":
box = self.layout.box() blenderbim.bim.helper.draw_attributes(self.props.cost_value_attributes, self.layout.box())
self.draw_editable_cost_value_ui(box, ResourceData.cost_values[self.props.active_cost_value_id])
def draw_readonly_cost_value_ui(self, layout, cost_value_id): def draw_readonly_cost_value_ui(self, layout, cost_value):
cost_value = ResourceData.cost_values[cost_value_id] if self.props.active_cost_value_id == cost_value["id"] and self.props.cost_value_editing_type == "FORMULA":
if self.props.active_cost_value_id == cost_value_id and self.props.cost_value_editing_type == "FORMULA":
layout.prop(self.props, "cost_value_formula", text="") layout.prop(self.props, "cost_value_formula", text="")
else: else:
cost_value_label = "{0:.2f}".format(cost_value["AppliedValue"]) layout.label(text=cost_value["label"], icon="DISC")
cost_value_label += " = " + cost_value["Formula"]
layout.label(text=cost_value_label, icon="DISC")
self.draw_cost_value_operator_ui(layout, cost_value_id, self.props.active_resource_id) self.draw_cost_value_operator_ui(layout, cost_value["id"], self.props.active_resource_id)
def draw_cost_value_operator_ui(self, layout, cost_value_id, parent_id): def draw_cost_value_operator_ui(self, layout, cost_value_id, parent_id):
if self.props.active_cost_value_id and self.props.active_cost_value_id == cost_value_id: if self.props.active_cost_value_id and self.props.active_cost_value_id == cost_value_id:
@@ -212,9 +204,6 @@ class BIM_PT_resources(Panel):
op.parent = parent_id op.parent = parent_id
op.cost_value = cost_value_id op.cost_value = cost_value_id
def draw_editable_cost_value_ui(self, layout, cost_value):
blenderbim.bim.helper.draw_attributes(self.props.cost_value_attributes, layout)
class BIM_UL_resources(UIList): class BIM_UL_resources(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):
@@ -246,9 +235,8 @@ class BIM_UL_resources(UIList):
row.prop(item, "name", emboss=False, text="", icon=icon_map[resource["type"]]) row.prop(item, "name", emboss=False, text="", icon=icon_map[resource["type"]])
row.prop(item, "schedule_usage", text="", emboss=False) row.prop(item, "schedule_usage", text="", emboss=False)
if context.active_object and not props.active_resource_id: if context.active_object and not props.active_resource_id:
oprops = context.active_object.BIMObjectProperties
row = layout.row(align=True) row = layout.row(align=True)
if oprops.ifc_definition_id in ResourceData.data["resources"][item.ifc_definition_id]["ResourceOf"]: if item.ifc_definition_id in ResourceData.data["active_resource_ids"]:
op = row.operator("bim.unassign_resource", text="", icon="KEYFRAME_HLT", emboss=False) op = row.operator("bim.unassign_resource", text="", icon="KEYFRAME_HLT", emboss=False)
op.resource = item.ifc_definition_id op.resource = item.ifc_definition_id
else: else:
+8 -11
View File
@@ -30,7 +30,6 @@ from datetime import datetime
from dateutil import parser from dateutil import parser
import ifcopenshell.util.date as ifcdateutils import ifcopenshell.util.date as ifcdateutils
import ifcopenshell.util.cost import ifcopenshell.util.cost
from ifcopenshell.api.unit.data import Data as UnitData
class Resource(blenderbim.core.tool.Resource): class Resource(blenderbim.core.tool.Resource):
@@ -190,10 +189,8 @@ class Resource(blenderbim.core.tool.Resource):
prop.data_type = "enum" prop.data_type = "enum"
prop.is_null = prop.is_optional = False prop.is_null = prop.is_optional = False
units = {} units = {}
if not UnitData.is_loaded: for unit in tool.Ifc.get().by_type("IfcNamedUnit"):
UnitData.load(tool.Ifc.get()) if getattr(unit, "UnitType", None) in [
for unit_id, unit in UnitData.units.items():
if unit.get("UnitType", None) in [
"AREAUNIT", "AREAUNIT",
"LENGTHUNIT", "LENGTHUNIT",
"TIMEUNIT", "TIMEUNIT",
@@ -201,13 +198,13 @@ class Resource(blenderbim.core.tool.Resource):
"MASSUNIT", "MASSUNIT",
"USERDEFINED", "USERDEFINED",
]: ]:
if unit["type"] == "IfcContextDependentUnit": if unit.is_a("IfcContextDependentUnit"):
units[unit_id] = f"{unit['UnitType']} / {unit['Name']}" units[unit.id()] = f"{unit.is_a()} / {unit.Name}"
else: else:
name = unit["Name"] name = unit.Name
if unit.get("Prefix", None): if getattr(unit, "Prefix", None):
name = f"(unit['Prefix']) {name}" name = f"(unit.Prefix) {name}"
units[unit_id] = f"{unit['UnitType']} / {name}" units[unit.id()] = f"{unit.UnitType} / {name}"
prop.enum_items = json.dumps(units) prop.enum_items = json.dumps(units)
if data["UnitBasis"] and data["UnitBasis"].UnitComponent: if data["UnitBasis"] and data["UnitBasis"].UnitComponent:
name = data["UnitBasis"].UnitComponent.Name name = data["UnitBasis"].UnitComponent.Name