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 blenderbim.tool as tool
from ifcopenshell.api.cost.data import CostValueTrait
import ifcopenshell
@@ -26,7 +25,7 @@ def refresh():
ResourceData.is_loaded = False
class ResourceData(CostValueTrait):
class ResourceData:
data = {}
is_loaded = False
cost_values = {}
@@ -34,56 +33,49 @@ class ResourceData(CostValueTrait):
@classmethod
def load(cls):
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
@classmethod
def has_resources(cls):
return bool(tool.Ifc.get().by_type("IfcResource"))
@classmethod
def number_of_resources_loaded(cls):
def total_resources(cls):
return len(tool.Ifc.get().by_type("IfcResource"))
@classmethod
def load_resources(cls):
cls.data["resources"] = {}
def resources(cls):
results = {}
for resource in tool.Ifc.get().by_type("IfcResource"):
data = resource.get_info()
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)
base_quantity = None
if resource.BaseQuantity:
data["BaseQuantity"] = resource.BaseQuantity.get_info()
del data["BaseQuantity"]["Unit"]
if resource.BaseCosts:
data["BaseCosts"] = [e.id() for e in resource.BaseCosts]
cls.load_cost_values(resource, data)
cls.data["resources"][resource.id()] = data
cls.data["number_of_resources_loaded"] = cls.number_of_resources_loaded()
base_quantity = resource.BaseQuantity.get_info()
del base_quantity["Unit"]
results[resource.id()] = {"type": resource.is_a(), "BaseQuantity": base_quantity}
return results
def load_resource_times(cls):
cls.data["resource_times"] = {}
for resource_time in tool.Ifc.get().by_type("IfcResourceTime"):
data = resource_time.get_info()
for key, value in data.items():
if not value:
continue
if "Start" in key or "Finish" in key or key == "StatusTime":
data[key] = ifcopenshell.util.date.ifc2datetime(value)
elif "Work" in key or key == "LevelingDelay":
data[key] = ifcopenshell.util.date.ifc2datetime(value)
cls.data["resource_times"][resource_time.id()] = data
@classmethod
def cost_values(cls):
results = []
ifc_id = bpy.context.scene.BIMResourceProperties.active_resource_id
if not ifc_id:
return results
resource = tool.Ifc.get().by_id(ifc_id)
for cost_value in resource.BaseCosts or []:
label = "{0:.2f}".format(ifcopenshell.util.cost.calculate_applied_value(resource, cost_value))
label += " = {}".format(ifcopenshell.util.cost.serialise_cost_value(cost_value))
results.append({"id": cost_value.id(), "label": label})
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()
row = self.layout.row(align=True)
if ResourceData.data["has_resources"]:
row.label(
text="{} Resources Found".format(ResourceData.data["number_of_resources_loaded"]),
icon="TEXT",
)
if ResourceData.data["total_resources"]:
row.label(text=f"{ResourceData.data['total_resources']} Resources Found", icon="TEXT")
else:
row.label(text="No Resources found.", icon="COMMUNITY")
if self.props.is_editing:
row.operator("bim.disable_resource_editing_ui", text="", icon="CANCEL")
else:
row.operator("bim.load_resources", text="Load Resources", icon="GREASEPENCIL")
row.operator("import_resources.bim", text="Import Resources", icon="IMPORT")
row.operator("bim.load_resources", text="", icon="GREASEPENCIL")
row.operator("import_resources.bim", text="", icon="IMPORT")
if not self.props.is_editing:
return
@@ -170,25 +167,20 @@ class BIM_PT_resources(Panel):
if self.props.cost_types == "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)
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":
box = self.layout.box()
self.draw_editable_cost_value_ui(box, ResourceData.cost_values[self.props.active_cost_value_id])
blenderbim.bim.helper.draw_attributes(self.props.cost_value_attributes, self.layout.box())
def draw_readonly_cost_value_ui(self, layout, cost_value_id):
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":
def draw_readonly_cost_value_ui(self, layout, cost_value):
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="")
else:
cost_value_label = "{0:.2f}".format(cost_value["AppliedValue"])
cost_value_label += " = " + cost_value["Formula"]
layout.label(text=cost_value_label, icon="DISC")
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):
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.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):
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, "schedule_usage", text="", emboss=False)
if context.active_object and not props.active_resource_id:
oprops = context.active_object.BIMObjectProperties
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.resource = item.ifc_definition_id
else:
+8 -11
View File
@@ -30,7 +30,6 @@ from datetime import datetime
from dateutil import parser
import ifcopenshell.util.date as ifcdateutils
import ifcopenshell.util.cost
from ifcopenshell.api.unit.data import Data as UnitData
class Resource(blenderbim.core.tool.Resource):
@@ -190,10 +189,8 @@ class Resource(blenderbim.core.tool.Resource):
prop.data_type = "enum"
prop.is_null = prop.is_optional = False
units = {}
if not UnitData.is_loaded:
UnitData.load(tool.Ifc.get())
for unit_id, unit in UnitData.units.items():
if unit.get("UnitType", None) in [
for unit in tool.Ifc.get().by_type("IfcNamedUnit"):
if getattr(unit, "UnitType", None) in [
"AREAUNIT",
"LENGTHUNIT",
"TIMEUNIT",
@@ -201,13 +198,13 @@ class Resource(blenderbim.core.tool.Resource):
"MASSUNIT",
"USERDEFINED",
]:
if unit["type"] == "IfcContextDependentUnit":
units[unit_id] = f"{unit['UnitType']} / {unit['Name']}"
if unit.is_a("IfcContextDependentUnit"):
units[unit.id()] = f"{unit.is_a()} / {unit.Name}"
else:
name = unit["Name"]
if unit.get("Prefix", None):
name = f"(unit['Prefix']) {name}"
units[unit_id] = f"{unit['UnitType']} / {name}"
name = unit.Name
if getattr(unit, "Prefix", None):
name = f"(unit.Prefix) {name}"
units[unit.id()] = f"{unit.UnitType} / {name}"
prop.enum_items = json.dumps(units)
if data["UnitBasis"] and data["UnitBasis"].UnitComponent:
name = data["UnitBasis"].UnitComponent.Name