This commit is contained in:
Andrej730
2025-07-17 12:09:42 +05:00
parent 83a3813f53
commit 577d46eb70
13 changed files with 239 additions and 168 deletions
+7 -10
View File
@@ -369,13 +369,13 @@ class CostItemQuantitiesData:
cls.is_loaded = True cls.is_loaded = True
@classmethod @classmethod
def product_quantity_names(cls): def product_quantity_names(cls) -> tool.Blender.BLENDER_ENUM_ITEMS:
elements = tool.Spatial.get_selected_products() elements = list(tool.Spatial.get_selected_products())
names = ifcopenshell.util.cost.get_product_quantity_names(elements) names = ifcopenshell.util.cost.get_product_quantity_names(elements)
return [(n, n, "") for n in names] return [(n, n, "") for n in names]
@classmethod @classmethod
def process_quantity_names(cls): def process_quantity_names(cls) -> tool.Blender.BLENDER_ENUM_ITEMS:
props = tool.Sequence.get_work_schedule_props() props = tool.Sequence.get_work_schedule_props()
active_task_index = props.active_task_index active_task_index = props.active_task_index
tprops = tool.Sequence.get_task_tree_props() tprops = tool.Sequence.get_task_tree_props()
@@ -391,14 +391,11 @@ class CostItemQuantitiesData:
return [(n, n, "") for n in names if n != "id"] return [(n, n, "") for n in names if n != "id"]
@classmethod @classmethod
def resource_quantity_names(cls): def resource_quantity_names(cls) -> tool.Blender.BLENDER_ENUM_ITEMS:
active_resource_index = bpy.context.scene.BIMResourceProperties.active_resource_index active_resource = tool.Resource.get_resource_props().active_resource
total_resources = len(bpy.context.scene.BIMResourceTreeProperties.resources) if not active_resource:
if not total_resources or active_resource_index >= total_resources:
return [] return []
ifc_definition_id = bpy.context.scene.BIMResourceTreeProperties.resources[ ifc_definition_id = active_resource.ifc_definition_id
active_resource_index
].ifc_definition_id
element = tool.Ifc.get().by_id(ifc_definition_id) element = tool.Ifc.get().by_id(ifc_definition_id)
names = set() names = set()
qtos = ifcopenshell.util.element.get_psets(element, qtos_only=True) qtos = ifcopenshell.util.element.get_psets(element, qtos_only=True)
+3 -4
View File
@@ -393,7 +393,7 @@ class BIM_PT_cost_item_types(Panel):
op.cost_item = cost_item.ifc_definition_id op.cost_item = cost_item.ifc_definition_id
rtprops = context.scene.BIMResourceTreeProperties rtprops = context.scene.BIMResourceTreeProperties
rprops = context.scene.BIMResourceProperties rprops = tool.Resource.get_resource_props()
if rtprops.resources and rprops.active_resource_index < len(rtprops.resources): if rtprops.resources and rprops.active_resource_index < len(rtprops.resources):
if has_quantity_names: if has_quantity_names:
op = row2.operator("bim.assign_cost_item_quantity", text="", icon="PROPERTIES") op = row2.operator("bim.assign_cost_item_quantity", text="", icon="PROPERTIES")
@@ -552,9 +552,8 @@ class BIM_PT_cost_item_quantities(Panel):
op = row2.operator("bim.calculate_cost_item_resource_value", text="", icon="DISC") op = row2.operator("bim.calculate_cost_item_resource_value", text="", icon="DISC")
op.cost_item = cost_item.ifc_definition_id op.cost_item = cost_item.ifc_definition_id
rtprops = context.scene.BIMResourceTreeProperties active_resource = tool.Resource.get_resource_props().active_resource
rprops = context.scene.BIMResourceProperties if active_resource:
if rtprops.resources and rprops.active_resource_index < len(rtprops.resources):
if has_quantity_names: if has_quantity_names:
op = row2.operator("bim.assign_cost_item_quantity", text="", icon="PROPERTIES") op = row2.operator("bim.assign_cost_item_quantity", text="", icon="PROPERTIES")
op.related_object_type = "RESOURCE" op.related_object_type = "RESOURCE"
+6 -6
View File
@@ -239,9 +239,9 @@ class ResourceQtosData(Data):
@classmethod @classmethod
def load(cls): def load(cls):
rprops = bpy.context.scene.BIMResourceProperties active_resource = tool.Resource.get_resource_props().active_resource
rtprops = bpy.context.scene.BIMResourceTreeProperties assert active_resource
ifc_definition_id = rtprops.resources[rprops.active_resource_index].ifc_definition_id ifc_definition_id = active_resource.ifc_definition_id
cls.data = {"qtos": cls.psetqtos(tool.Ifc.get().by_id(ifc_definition_id), qtos_only=True)} cls.data = {"qtos": cls.psetqtos(tool.Ifc.get().by_id(ifc_definition_id), qtos_only=True)}
cls.is_loaded = True cls.is_loaded = True
@@ -252,9 +252,9 @@ class ResourcePsetsData(Data):
@classmethod @classmethod
def load(cls): def load(cls):
rprops = bpy.context.scene.BIMResourceProperties active_resource = tool.Resource.get_resource_props().active_resource
rtprops = bpy.context.scene.BIMResourceTreeProperties assert active_resource
ifc_definition_id = rtprops.resources[rprops.active_resource_index].ifc_definition_id ifc_definition_id = active_resource.ifc_definition_id
cls.data = {"psets": cls.psetqtos(tool.Ifc.get().by_id(ifc_definition_id), psets_only=True)} cls.data = {"psets": cls.psetqtos(tool.Ifc.get().by_id(ifc_definition_id), psets_only=True)}
cls.is_loaded = True cls.is_loaded = True
+6 -6
View File
@@ -155,9 +155,9 @@ def get_task_qto_names(self: "PsetProperties", context: object) -> tool.Blender.
def get_resource_pset_names(self: "PsetProperties", context: bpy.types.Context) -> tool.Blender.BLENDER_ENUM_ITEMS: def get_resource_pset_names(self: "PsetProperties", context: bpy.types.Context) -> tool.Blender.BLENDER_ENUM_ITEMS:
global psetnames global psetnames
rprops = context.scene.BIMResourceProperties active_resource = tool.Resource.get_resource_props().active_resource
rtprops = context.scene.BIMResourceTreeProperties assert active_resource
ifc_class = tool.Ifc.get().by_id(rtprops.resources[rprops.active_resource_index].ifc_definition_id).is_a() ifc_class = tool.Ifc.get().by_id(active_resource.ifc_definition_id).is_a()
if ifc_class not in psetnames: if ifc_class not in psetnames:
psets = bonsai.bim.schema.ifc.psetqto.get_applicable(ifc_class, pset_only=True, schema=tool.Ifc.get_schema()) psets = bonsai.bim.schema.ifc.psetqto.get_applicable(ifc_class, pset_only=True, schema=tool.Ifc.get_schema())
psetnames[ifc_class] = blender_formatted_enum_from_psets(psets) psetnames[ifc_class] = blender_formatted_enum_from_psets(psets)
@@ -166,9 +166,9 @@ def get_resource_pset_names(self: "PsetProperties", context: bpy.types.Context)
def get_resource_qto_names(self: "PsetProperties", context: bpy.types.Context) -> tool.Blender.BLENDER_ENUM_ITEMS: def get_resource_qto_names(self: "PsetProperties", context: bpy.types.Context) -> tool.Blender.BLENDER_ENUM_ITEMS:
global qtonames global qtonames
rprops = context.scene.BIMResourceProperties active_resource = tool.Resource.get_resource_props().active_resource
rtprops = context.scene.BIMResourceTreeProperties assert active_resource
ifc_class = tool.Ifc.get().by_id(rtprops.resources[rprops.active_resource_index].ifc_definition_id).is_a() ifc_class = tool.Ifc.get().by_id(active_resource.ifc_definition_id).is_a()
if ifc_class not in qtonames: if ifc_class not in qtonames:
psets = bonsai.bim.schema.ifc.psetqto.get_applicable(ifc_class, qto_only=True, schema=tool.Ifc.get_schema()) psets = bonsai.bim.schema.ifc.psetqto.get_applicable(ifc_class, qto_only=True, schema=tool.Ifc.get_schema())
qtonames[ifc_class] = blender_formatted_enum_from_psets(psets) qtonames[ifc_class] = blender_formatted_enum_from_psets(psets)
+4 -10
View File
@@ -596,11 +596,8 @@ class BIM_PT_resource_qtos(Panel):
@classmethod @classmethod
def poll(cls, context): def poll(cls, context):
props = context.scene.BIMResourceProperties active_resource = tool.Resource.get_resource_props().active_resource
total_resources = len(context.scene.BIMResourceTreeProperties.resources) return bool(active_resource)
if total_resources > 0 and props.active_resource_index < total_resources:
return True
return False
def draw(self, context): def draw(self, context):
if not ResourceQtosData.is_loaded: if not ResourceQtosData.is_loaded:
@@ -631,11 +628,8 @@ class BIM_PT_resource_psets(Panel):
@classmethod @classmethod
def poll(cls, context): def poll(cls, context):
props = context.scene.BIMResourceProperties active_resource = tool.Resource.get_resource_props().active_resource
total_resources = len(context.scene.BIMResourceTreeProperties.resources) return bool(active_resource)
if total_resources > 0 and props.active_resource_index < total_resources:
return True
return False
def draw(self, context): def draw(self, context):
if not ResourcePsetsData.is_loaded: if not ResourcePsetsData.is_loaded:
@@ -124,7 +124,7 @@ class ResourceData:
@classmethod @classmethod
def cost_values(cls) -> list[dict[str, Any]]: def cost_values(cls) -> list[dict[str, Any]]:
results = [] results = []
ifc_id = bpy.context.scene.BIMResourceProperties.active_resource_id ifc_id = tool.Resource.get_resource_props().active_resource_id
if not ifc_id: if not ifc_id:
return results return results
resource = tool.Ifc.get().by_id(ifc_id) resource = tool.Ifc.get().by_id(ifc_id)
@@ -87,10 +87,11 @@ class EditResource(bpy.types.Operator, tool.Ifc.Operator):
bl_options = {"REGISTER", "UNDO"} bl_options = {"REGISTER", "UNDO"}
def _execute(self, context): def _execute(self, context):
props = tool.Resource.get_resource_props()
core.edit_resource( core.edit_resource(
tool.Ifc, tool.Ifc,
tool.Resource, tool.Resource,
resource=tool.Ifc.get().by_id(context.scene.BIMResourceProperties.active_resource_id), resource=tool.Ifc.get().by_id(props.active_resource_id),
) )
@@ -174,10 +175,11 @@ class EditResourceTime(bpy.types.Operator, tool.Ifc.Operator):
bl_options = {"REGISTER", "UNDO"} bl_options = {"REGISTER", "UNDO"}
def _execute(self, context): def _execute(self, context):
props = tool.Resource.get_resource_props()
core.edit_resource_time( core.edit_resource_time(
tool.Ifc, tool.Ifc,
tool.Resource, tool.Resource,
resource_time=tool.Ifc.get().by_id(context.scene.BIMResourceProperties.active_resource_time_id), resource_time=tool.Ifc.get().by_id(props.active_resource_time_id),
) )
+84 -16
View File
@@ -24,7 +24,7 @@ import bonsai.tool as tool
import bonsai.bim.module.pset.data import bonsai.bim.module.pset.data
import bonsai.bim.module.resource.data import bonsai.bim.module.resource.data
import bonsai.bim.module.sequence.data import bonsai.bim.module.sequence.data
from bonsai.bim.prop import StrProperty, Attribute from bonsai.bim.prop import Attribute
from bpy.types import PropertyGroup from bpy.types import PropertyGroup
from bpy.props import ( from bpy.props import (
PointerProperty, PointerProperty,
@@ -36,11 +36,12 @@ from bpy.props import (
FloatVectorProperty, FloatVectorProperty,
CollectionProperty, CollectionProperty,
) )
from typing import TYPE_CHECKING, Literal, get_args
quantitytypes_enum = {} quantitytypes_enum: dict[str, tool.Blender.BLENDER_ENUM_ITEMS] = {}
def setup_quantity_types_enum(): def setup_quantity_types_enum() -> None:
resources = ifcopenshell.util.resource.RESOURCES_TO_QUANTITIES resources = ifcopenshell.util.resource.RESOURCES_TO_QUANTITIES
for resource, quantities in resources.items(): for resource, quantities in resources.items():
quantitytypes_enum[resource] = [(q, q, "") for q in quantities] quantitytypes_enum[resource] = [(q, q, "") for q in quantities]
@@ -49,8 +50,8 @@ def setup_quantity_types_enum():
setup_quantity_types_enum() setup_quantity_types_enum()
def updateResourceName(self, context): def updateResourceName(self: "Resource", context: object) -> None:
props = context.scene.BIMResourceProperties props = tool.Resource.get_resource_props()
if not props.is_resource_update_enabled: if not props.is_resource_update_enabled:
return return
ifc_file = tool.Ifc.get() ifc_file = tool.Ifc.get()
@@ -66,18 +67,19 @@ def updateResourceName(self, context):
tool.Sequence.refresh_task_resources() tool.Sequence.refresh_task_resources()
def get_quantity_types(self, context): def get_quantity_types(self: "BIMResourceProperties", context: object) -> tool.Blender.BLENDER_ENUM_ITEMS:
return quantitytypes_enum[self.active_resource_class] return quantitytypes_enum[self.active_resource_class]
def update_active_resource_index(self, context): def update_active_resource_index(self: "BIMResourceProperties", context: object) -> None:
bonsai.bim.module.pset.data.refresh() bonsai.bim.module.pset.data.refresh()
if self.should_show_resource_tools: if self.should_show_resource_tools:
tool.Resource.load_productivity_data() tool.Resource.load_productivity_data()
def updateResourceUsage(self, context): def updateResourceUsage(self: "Resource", context: object) -> None:
if not context.scene.BIMResourceProperties.is_resource_update_enabled: props = tool.Resource.get_resource_props()
if not props.is_resource_update_enabled:
return return
if not self.schedule_usage: if not self.schedule_usage:
return return
@@ -102,6 +104,15 @@ class ISODuration(PropertyGroup):
minutes: IntProperty(name="Minutes", default=0) minutes: IntProperty(name="Minutes", default=0)
seconds: IntProperty(name="Seconds", default=0) seconds: IntProperty(name="Seconds", default=0)
if TYPE_CHECKING:
name: str
years: int
months: int
days: int
hours: int
minutes: int
seconds: int
class Resource(PropertyGroup): class Resource(PropertyGroup):
name: StringProperty(name="Name", update=updateResourceName) name: StringProperty(name="Name", update=updateResourceName)
@@ -111,10 +122,26 @@ class Resource(PropertyGroup):
is_expanded: BoolProperty(name="Is Expanded") is_expanded: BoolProperty(name="Is Expanded")
level_index: IntProperty(name="Level Index") level_index: IntProperty(name="Level Index")
if TYPE_CHECKING:
name: str
ifc_definition_id: int
schedule_usage: float
has_children: bool
is_expanded: bool
level_index: int
# Separate from BIMResourceProperties - see BIMTaskTreeProperties note.
class BIMResourceTreeProperties(PropertyGroup): class BIMResourceTreeProperties(PropertyGroup):
resources: CollectionProperty(name="Resources", type=Resource) resources: CollectionProperty(name="Resources", type=Resource)
if TYPE_CHECKING:
resources: bpy.types.bpy_prop_collection_idprop[Resource]
EditingResourceType = Literal["ATTRIBUTES", "USAGE", "COSTS", "QUANTITY"]
CostType = Literal["FIXED", "SUM", "CATEGORY"]
class BIMResourceProperties(PropertyGroup): class BIMResourceProperties(PropertyGroup):
resource_attributes: CollectionProperty(name="Resource Attributes", type=Attribute) resource_attributes: CollectionProperty(name="Resource Attributes", type=Attribute)
@@ -128,13 +155,7 @@ class BIMResourceProperties(PropertyGroup):
active_resource_time_id: IntProperty(name="Active Resource Usage Id") active_resource_time_id: IntProperty(name="Active Resource Usage Id")
resource_time_attributes: CollectionProperty(name="Resource Usage Attributes", type=Attribute) resource_time_attributes: CollectionProperty(name="Resource Usage Attributes", type=Attribute)
editing_resource_type: EnumProperty( editing_resource_type: EnumProperty(
name="Editing Resource Type", name="Editing Resource Type", items=[(i, i, "") for i in get_args(EditingResourceType)]
items=(
("ATTRIBUTES", "", ""),
("USAGE", "", ""),
("COSTS", "", ""),
("QUANTITY", "", ""),
),
) )
cost_types: EnumProperty( cost_types: EnumProperty(
items=[ items=[
@@ -154,9 +175,56 @@ class BIMResourceProperties(PropertyGroup):
quantity_attributes: CollectionProperty(name="Quantity Attributes", type=Attribute) quantity_attributes: CollectionProperty(name="Quantity Attributes", type=Attribute)
should_show_resource_tools: BoolProperty(name="Edit Productivity", update=update_active_resource_index) should_show_resource_tools: BoolProperty(name="Edit Productivity", update=update_active_resource_index)
if TYPE_CHECKING:
resource_attributes: bpy.types.bpy_prop_collection_idprop[Attribute]
is_editing: bool
active_resource_index: int
active_resource_id: int
active_resource_class: str
contracted_resources: str
is_resource_update_enabled: bool
is_loaded: bool
active_resource_time_id: int
resource_time_attributes: bpy.types.bpy_prop_collection_idprop[Attribute]
editing_resource_type: EditingResourceType
cost_types: CostType
cost_category: str
active_cost_value_id: int
cost_value_editing_type: str
cost_value_attributes: bpy.types.bpy_prop_collection_idprop[Attribute]
cost_value_formula: str
quantity_types: str
is_editing_quantity: bool
quantity_attributes: bpy.types.bpy_prop_collection_idprop[Attribute]
should_show_resource_tools: bool
@property
def tree(self) -> "BIMResourceTreeProperties":
assert bpy.context.scene
tprops = bpy.context.scene.BIMResourceTreeProperties # pyright: ignore[reportAttributeAccessIssue]
assert isinstance(tprops, BIMResourceTreeProperties)
return tprops
@property
def productivity(self) -> "BIMResourceProductivity":
assert bpy.context.scene
productivity = bpy.context.scene.BIMResourceProductivity
assert isinstance(productivity, BIMResourceProductivity)
return productivity
@property
def active_resource(self) -> Resource | None:
return tool.Blender.get_active_uilist_element(self.tree.resources, self.active_resource_index)
class BIMResourceProductivity(PropertyGroup): class BIMResourceProductivity(PropertyGroup):
ifc_definition_id: IntProperty(name="IFC Definition ID") ifc_definition_id: IntProperty(name="IFC Definition ID")
quantity_consumed: CollectionProperty(name="Duration", type=ISODuration) quantity_consumed: CollectionProperty(name="Duration", type=ISODuration)
quantity_produced: FloatProperty(name="Quantity Produced") quantity_produced: FloatProperty(name="Quantity Produced")
quantity_produced_name: StringProperty(name="Quantity Produced Name") quantity_produced_name: StringProperty(name="Quantity Produced Name")
if TYPE_CHECKING:
ifc_definition_id: int
quantity_consumed: bpy.types.bpy_prop_collection_idprop[ISODuration]
quantity_produced: float
quantity_produced_name: str
+41 -33
View File
@@ -16,12 +16,16 @@
# You should have received a copy of the GNU General Public License # You should have received a copy of the GNU General Public License
# along with Bonsai. If not, see <http://www.gnu.org/licenses/>. # along with Bonsai. If not, see <http://www.gnu.org/licenses/>.
from __future__ import annotations
import bpy import bpy
import bonsai.tool as tool import bonsai.tool as tool
import bonsai.bim.helper import bonsai.bim.helper
from bpy.types import Panel, UIList from bpy.types import Panel, UIList
from bonsai.bim.module.resource.data import ResourceData from bonsai.bim.module.resource.data import ResourceData
from typing import Any from typing import Any, TYPE_CHECKING
if TYPE_CHECKING:
from bonsai.bim.module.resource.prop import ISODuration, Resource, BIMResourceTreeProperties
class BIM_PT_resources(Panel): class BIM_PT_resources(Panel):
@@ -38,9 +42,10 @@ class BIM_PT_resources(Panel):
file = tool.Ifc.get() file = tool.Ifc.get()
return file and hasattr(file, "schema") and file.schema != "IFC2X3" return file and hasattr(file, "schema") and file.schema != "IFC2X3"
layout: bpy.types.UILayout
def draw(self, context): def draw(self, context):
self.props = context.scene.BIMResourceProperties self.props = tool.Resource.get_resource_props()
self.tprops = context.scene.BIMResourceTreeProperties
if not ResourceData.is_loaded: if not ResourceData.is_loaded:
ResourceData.load() ResourceData.load()
@@ -64,7 +69,7 @@ class BIM_PT_resources(Panel):
self.layout.template_list( self.layout.template_list(
"BIM_UL_resources", "BIM_UL_resources",
"", "",
self.tprops, self.props.tree,
"resources", "resources",
self.props, self.props,
"active_resource_index", "active_resource_index",
@@ -79,18 +84,18 @@ class BIM_PT_resources(Panel):
self.draw_editable_resource_costs_ui() self.draw_editable_resource_costs_ui()
elif self.props.active_resource_id and self.props.editing_resource_type == "USAGE": elif self.props.active_resource_id and self.props.editing_resource_type == "USAGE":
self.draw_editable_resource_time_attributes_ui() self.draw_editable_resource_time_attributes_ui()
self.draw_productivity_ui(context) self.draw_productivity_ui()
def draw_productivity_ui(self, context): def draw_productivity_ui(self) -> None:
row = self.layout.row(align=True) row = self.layout.row(align=True)
row.alignment = "RIGHT" row.alignment = "RIGHT"
row.prop(self.props, "should_show_resource_tools", text="Resource Tools", icon="RECOVER_LAST") row.prop(self.props, "should_show_resource_tools", text="Resource Tools", icon="RECOVER_LAST")
if self.props.should_show_resource_tools: if self.props.should_show_resource_tools:
total_resources = len(self.tprops.resources) active_resource = self.props.active_resource
if not total_resources or self.props.active_resource_index >= total_resources: if not active_resource:
return return
ifc_definition_id = self.tprops.resources[self.props.active_resource_index].ifc_definition_id ifc_definition_id = active_resource.ifc_definition_id
resource = ResourceData.data["resources"][ifc_definition_id] resource = ResourceData.data["resources"][ifc_definition_id]
if not resource["type"] in ["IfcConstructionEquipmentResource", "IfcLaborResource"]: if not resource["type"] in ["IfcConstructionEquipmentResource", "IfcLaborResource"]:
@@ -145,7 +150,7 @@ class BIM_PT_resources(Panel):
row2_col1 = col1.row() row2_col1 = col1.row()
row2_col1.label(text="Schedule Usage") row2_col1.label(text="Schedule Usage")
row2col2 = col2.row() row2col2 = col2.row()
row2col2.prop(self.tprops.resources[self.props.active_resource_index], "schedule_usage", text="") row2col2.prop(active_resource, "schedule_usage", text="")
row2col3 = col3.row() row2col3 = col3.row()
row2col3.operator("bim.calculate_resource_usage", text="", icon="TEMP") row2col3.operator("bim.calculate_resource_usage", text="", icon="TEMP")
op = row2col3.operator( op = row2col3.operator(
@@ -189,7 +194,7 @@ class BIM_PT_resources(Panel):
row.label(text="{}".format(produtivitiy_rate_message), icon="ARMATURE_DATA") row.label(text="{}".format(produtivitiy_rate_message), icon="ARMATURE_DATA")
row.operator("bim.add_productivity_data", text="", icon="ADD") row.operator("bim.add_productivity_data", text="", icon="ADD")
def draw_resource_operators(self): def draw_resource_operators(self) -> None:
row = self.layout.row(align=True) row = self.layout.row(align=True)
op = row.operator("bim.add_resource", text="Add SubContract", icon="TEXT") op = row.operator("bim.add_resource", text="Add SubContract", icon="TEXT")
op.ifc_class = "IfcSubContractResource" op.ifc_class = "IfcSubContractResource"
@@ -198,11 +203,11 @@ class BIM_PT_resources(Panel):
op.ifc_class = "IfcCrewResource" op.ifc_class = "IfcCrewResource"
op.parent_resource = 0 op.parent_resource = 0
total_resources = len(self.tprops.resources) active_resource = self.props.active_resource
if not total_resources or self.props.active_resource_index >= total_resources: if not active_resource:
return return
ifc_definition_id = self.tprops.resources[self.props.active_resource_index].ifc_definition_id ifc_definition_id = active_resource.ifc_definition_id
resource = ResourceData.data["resources"][ifc_definition_id] resource = ResourceData.data["resources"][ifc_definition_id]
if resource["type"] != "IfcSubContractResource": if resource["type"] != "IfcSubContractResource":
@@ -239,13 +244,13 @@ class BIM_PT_resources(Panel):
row.operator("bim.edit_resource_time", text="", icon="CHECKMARK") row.operator("bim.edit_resource_time", text="", icon="CHECKMARK")
row.operator("bim.disable_editing_resource", text="", icon="CANCEL") row.operator("bim.disable_editing_resource", text="", icon="CANCEL")
def draw_editable_resource_attributes_ui(self): def draw_editable_resource_attributes_ui(self) -> None:
bonsai.bim.helper.draw_attributes(self.props.resource_attributes, self.layout) bonsai.bim.helper.draw_attributes(self.props.resource_attributes, self.layout)
def draw_editable_resource_time_attributes_ui(self): def draw_editable_resource_time_attributes_ui(self) -> None:
bonsai.bim.helper.draw_attributes(self.props.resource_time_attributes, self.layout) bonsai.bim.helper.draw_attributes(self.props.resource_time_attributes, self.layout)
def draw_editable_resource_quantity_ui(self): def draw_editable_resource_quantity_ui(self) -> None:
resource = ResourceData.data["resources"][self.props.active_resource_id] resource = ResourceData.data["resources"][self.props.active_resource_id]
if resource["BaseQuantity"]: if resource["BaseQuantity"]:
@@ -278,7 +283,7 @@ class BIM_PT_resources(Panel):
op.resource = self.props.active_resource_id op.resource = self.props.active_resource_id
op.ifc_class = self.props.quantity_types op.ifc_class = self.props.quantity_types
def draw_editable_resource_costs_ui(self): def draw_editable_resource_costs_ui(self) -> None:
row = self.layout.row(align=True) row = self.layout.row(align=True)
row.prop(self.props, "cost_types", text="") row.prop(self.props, "cost_types", text="")
if self.props.cost_types == "CATEGORY": if self.props.cost_types == "CATEGORY":
@@ -326,16 +331,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_duration_property(self, duration_props, layout):
for duration_prop in duration_props:
if duration_prop.name == "BaseQuantityConsumed":
layout.prop(duration_prop, "years", text="Y")
layout.prop(duration_prop, "months", text="M")
layout.prop(duration_prop, "days", text="D")
layout.prop(duration_prop, "hours", text="H")
layout.prop(duration_prop, "minutes", text="Min")
layout.prop(duration_prop, "seconds", text="S")
class BIM_UL_resources(UIList): class BIM_UL_resources(UIList):
@classmethod @classmethod
@@ -358,7 +353,16 @@ class BIM_UL_resources(UIList):
col = row.column() col = row.column()
col.label(text="") col.label(text="")
def draw_item(self, context, layout, data, item, icon, active_data, active_propname): def draw_item(
self,
context: bpy.types.Context,
layout: bpy.types.UILayout,
data: BIMResourceTreeProperties,
item: Resource,
icon,
active_data,
active_propname,
) -> None:
icon_map = { icon_map = {
"IfcSubContractResource": "TEXT", "IfcSubContractResource": "TEXT",
"IfcCrewResource": "COMMUNITY", "IfcCrewResource": "COMMUNITY",
@@ -369,7 +373,7 @@ class BIM_UL_resources(UIList):
} }
if item: if item:
resource = ResourceData.data["resources"][item.ifc_definition_id] resource = ResourceData.data["resources"][item.ifc_definition_id]
props = context.scene.BIMResourceProperties props = tool.Resource.get_resource_props()
row = layout.row(align=True) row = layout.row(align=True)
for i in range(0, item.level_index): for i in range(0, item.level_index):
row.label(text="", icon="BLANK1") row.label(text="", icon="BLANK1")
@@ -403,8 +407,12 @@ class BIM_UL_resources(UIList):
row.operator("bim.disable_editing_resource", text="", icon="CANCEL") row.operator("bim.disable_editing_resource", text="", icon="CANCEL")
def draw_productivity_ui(self, context): def draw_productivity_ui(self: bpy.types.Operator, context: object) -> None:
def draw_duration_property(duration_props, layout): assert self.layout
def draw_duration_property(
duration_props: bpy.types.bpy_prop_collection_idprop[ISODuration], layout: bpy.types.UILayout
) -> None:
for duration_prop in duration_props: for duration_prop in duration_props:
if duration_prop.name == "BaseQuantityConsumed": if duration_prop.name == "BaseQuantityConsumed":
layout.prop(duration_prop, "years", text="Y") layout.prop(duration_prop, "years", text="Y")
@@ -414,7 +422,7 @@ def draw_productivity_ui(self, context):
layout.prop(duration_prop, "minutes", text="Min") layout.prop(duration_prop, "minutes", text="Min")
layout.prop(duration_prop, "seconds", text="S") layout.prop(duration_prop, "seconds", text="S")
productivity_props = context.scene.BIMResourceProductivity productivity_props = tool.Resource.get_resource_props().productivity
grid = self.layout.grid_flow(columns=2, even_columns=False, even_rows=False, align=False) grid = self.layout.grid_flow(columns=2, even_columns=False, even_rows=False, align=False)
col1 = grid.column(align=False) col1 = grid.column(align=False)
col2 = grid.column(align=False) col2 = grid.column(align=False)
@@ -386,12 +386,11 @@ class TaskICOMData:
cls.is_loaded = True cls.is_loaded = True
@classmethod @classmethod
def can_active_resource_be_assigned(cls): def can_active_resource_be_assigned(cls) -> bool:
resource_props = bpy.context.scene.BIMResourceProperties props = tool.Resource.get_resource_props()
resource_tprops = bpy.context.scene.BIMResourceTreeProperties active_resource = props.active_resource
total_resources = len(resource_tprops.resources) if active_resource:
if total_resources and resource_props.active_resource_index < total_resources: resource_id = active_resource.ifc_definition_id
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 not tool.Ifc.get().by_id(resource_id).is_a("IfcCrewResource")
return False return False
@@ -308,8 +308,9 @@ def updateAssignedResourceName(self, context):
pass pass
def updateAssignedResourceUsage(self, context): def updateAssignedResourceUsage(self: "TaskResource", context: object) -> None:
if not context.scene.BIMResourceProperties.is_resource_update_enabled: props = tool.Resource.get_resource_props()
if not props.is_resource_update_enabled:
return return
if not self.schedule_usage: if not self.schedule_usage:
return return
+3 -3
View File
@@ -246,9 +246,9 @@ class Blender(bonsai.core.tool.Blender):
cost_props = tool.Cost.get_cost_props() cost_props = tool.Cost.get_cost_props()
return cost_props.cost_items[cost_props.active_cost_item_index].ifc_definition_id return cost_props.cost_items[cost_props.active_cost_item_index].ifc_definition_id
elif obj_type == "Resource": elif obj_type == "Resource":
return context.scene.BIMResourceTreeProperties.resources[ active_resource = tool.Resource.get_resource_props().active_resource
context.scene.BIMResourceProperties.active_resource_index assert active_resource
].ifc_definition_id return active_resource.ifc_definition_id
elif obj_type == "Profile": elif obj_type == "Profile":
props = tool.Profile.get_profile_props() props = tool.Profile.get_profile_props()
return props.profiles[props.active_profile_index].ifc_definition_id return props.profiles[props.active_profile_index].ifc_definition_id
+72 -69
View File
@@ -37,18 +37,25 @@ from typing import Any, Union, TYPE_CHECKING, Literal
if TYPE_CHECKING: if TYPE_CHECKING:
from bonsai.bim.prop import Attribute from bonsai.bim.prop import Attribute
from bonsai.bim.module.resource.prop import BIMResourceProperties from bonsai.bim.module.resource.prop import BIMResourceProperties, BIMResourceProductivity
class Resource(bonsai.core.tool.Resource): class Resource(bonsai.core.tool.Resource):
@classmethod @classmethod
def get_resource_props(cls) -> BIMResourceProperties: def get_resource_props(cls) -> BIMResourceProperties:
"""
BIMResourceTreeProperties can be accessed using `.tree`.
BIMResourceProductivity - using `.productivity`.
"""
return bpy.context.scene.BIMResourceProperties return bpy.context.scene.BIMResourceProperties
@classmethod @classmethod
def load_resources(cls) -> None: def load_resources(cls) -> None:
def create_new_resource_li(resource, level_index): props = cls.get_resource_props()
new = bpy.context.scene.BIMResourceTreeProperties.resources.add() tprops = props.tree
def create_new_resource_li(resource: ifcopenshell.entity_instance, level_index: int) -> None:
new = tprops.resources.add()
new.ifc_definition_id = resource.id() new.ifc_definition_id = resource.id()
new.is_expanded = resource.id() not in contracted_resources new.is_expanded = resource.id() not in contracted_resources
new.level_index = level_index new.level_index = level_index
@@ -61,8 +68,6 @@ class Resource(bonsai.core.tool.Resource):
for nested_resource in rel.RelatedObjects for nested_resource in rel.RelatedObjects
] ]
props = bpy.context.scene.BIMResourceProperties
tprops = bpy.context.scene.BIMResourceTreeProperties
tprops.resources.clear() tprops.resources.clear()
contracted_resources = json.loads(props.contracted_resources) contracted_resources = json.loads(props.contracted_resources)
props.is_resource_update_enabled = False props.is_resource_update_enabled = False
@@ -77,8 +82,8 @@ class Resource(bonsai.core.tool.Resource):
@classmethod @classmethod
def load_resource_properties(cls) -> None: def load_resource_properties(cls) -> None:
props = bpy.context.scene.BIMResourceProperties props = cls.get_resource_props()
tprops = bpy.context.scene.BIMResourceTreeProperties tprops = props.tree
props.is_resource_update_enabled = False props.is_resource_update_enabled = False
for item in tprops.resources: for item in tprops.resources:
resource = tool.Ifc.get().by_id(item.ifc_definition_id) resource = tool.Ifc.get().by_id(item.ifc_definition_id)
@@ -90,20 +95,23 @@ class Resource(bonsai.core.tool.Resource):
@classmethod @classmethod
def disable_editing_resource(cls) -> None: def disable_editing_resource(cls) -> None:
bpy.context.scene.BIMResourceProperties.active_resource_id = 0 props = cls.get_resource_props()
bpy.context.scene.BIMResourceProperties.active_resource_time_id = 0 props.property_unset("active_resource_id")
props.property_unset("active_resource_time_id")
@classmethod @classmethod
def disable_resource_editing_ui(cls) -> None: def disable_resource_editing_ui(cls) -> None:
bpy.context.scene.BIMResourceProperties.is_editing = False props = cls.get_resource_props()
props.property_unset("is_editing")
@classmethod @classmethod
def load_resource_attributes(cls, resource: ifcopenshell.entity_instance) -> None: def load_resource_attributes(cls, resource: ifcopenshell.entity_instance) -> None:
bonsai.bim.helper.import_attributes(resource, bpy.context.scene.BIMResourceProperties.resource_attributes) props = cls.get_resource_props()
bonsai.bim.helper.import_attributes(resource, props.resource_attributes)
@classmethod @classmethod
def enable_editing_resource(cls, resource: ifcopenshell.entity_instance) -> None: def enable_editing_resource(cls, resource: ifcopenshell.entity_instance) -> None:
props = bpy.context.scene.BIMResourceProperties props = cls.get_resource_props()
props.active_resource_id = resource.id() props.active_resource_id = resource.id()
props.resource_attributes.clear() props.resource_attributes.clear()
props.editing_resource_type = "ATTRIBUTES" props.editing_resource_type = "ATTRIBUTES"
@@ -111,11 +119,12 @@ class Resource(bonsai.core.tool.Resource):
@classmethod @classmethod
def get_resource_attributes(cls) -> dict[str, Any]: def get_resource_attributes(cls) -> dict[str, Any]:
return bonsai.bim.helper.export_attributes(bpy.context.scene.BIMResourceProperties.resource_attributes) props = cls.get_resource_props()
return bonsai.bim.helper.export_attributes(props.resource_attributes)
@classmethod @classmethod
def enable_editing_resource_time(cls, resource: ifcopenshell.entity_instance) -> None: def enable_editing_resource_time(cls, resource: ifcopenshell.entity_instance) -> None:
props = bpy.context.scene.BIMResourceProperties props = cls.get_resource_props()
props.resource_time_attributes.clear() props.resource_time_attributes.clear()
props.active_resource_time_id = resource.Usage.id() props.active_resource_time_id = resource.Usage.id()
props.active_resource_id = resource.id() props.active_resource_id = resource.id()
@@ -128,8 +137,10 @@ class Resource(bonsai.core.tool.Resource):
@classmethod @classmethod
def load_resource_time_attributes(cls, resource_time: ifcopenshell.entity_instance) -> None: def load_resource_time_attributes(cls, resource_time: ifcopenshell.entity_instance) -> None:
def callback(name, prop, data): props = cls.get_resource_props()
if prop.data_type == "string":
def callback(name: str, prop: Union[Attribute, None], data: dict[str, Any]) -> None | Literal[True]:
if prop and prop.data_type == "string":
if isinstance(data[name], datetime): if isinstance(data[name], datetime):
prop.string_value = "" if prop.is_null else data[name].isoformat() prop.string_value = "" if prop.is_null else data[name].isoformat()
return True return True
@@ -137,9 +148,7 @@ class Resource(bonsai.core.tool.Resource):
prop.string_value = "" if prop.is_null else ifcdateutils.datetime2ifc(data[name], "IfcDuration") prop.string_value = "" if prop.is_null else ifcdateutils.datetime2ifc(data[name], "IfcDuration")
return True return True
bonsai.bim.helper.import_attributes( bonsai.bim.helper.import_attributes(resource_time, props.resource_time_attributes, callback)
resource_time, bpy.context.scene.BIMResourceProperties.resource_time_attributes, callback
)
@classmethod @classmethod
def get_resource_time_attributes(cls) -> dict[str, Any]: def get_resource_time_attributes(cls) -> dict[str, Any]:
@@ -160,25 +169,25 @@ class Resource(bonsai.core.tool.Resource):
return True return True
return False return False
props = bpy.context.scene.BIMResourceProperties props = cls.get_resource_props()
return bonsai.bim.helper.export_attributes(props.resource_time_attributes, callback) return bonsai.bim.helper.export_attributes(props.resource_time_attributes, callback)
@classmethod @classmethod
def enable_editing_resource_costs(cls, resource: ifcopenshell.entity_instance) -> None: def enable_editing_resource_costs(cls, resource: ifcopenshell.entity_instance) -> None:
props = bpy.context.scene.BIMResourceProperties props = cls.get_resource_props()
props.active_resource_id = resource.id() props.active_resource_id = resource.id()
props.editing_resource_type = "COSTS" props.editing_resource_type = "COSTS"
cls.update_cost_values_ui_data() cls.update_cost_values_ui_data()
@classmethod @classmethod
def disable_editing_resource_cost_value(cls) -> None: def disable_editing_resource_cost_value(cls) -> None:
props = bpy.context.scene.BIMResourceProperties props = cls.get_resource_props()
props.active_cost_value_id = 0 props.active_cost_value_id = 0
props.cost_value_editing_type = "" props.cost_value_editing_type = ""
@classmethod @classmethod
def enable_editing_resource_cost_value_formula(cls, cost_value: ifcopenshell.entity_instance) -> None: def enable_editing_resource_cost_value_formula(cls, cost_value: ifcopenshell.entity_instance) -> None:
props = bpy.context.scene.BIMResourceProperties props = cls.get_resource_props()
props.cost_value_attributes.clear() props.cost_value_attributes.clear()
props.active_cost_value_id = cost_value.id() props.active_cost_value_id = cost_value.id()
props.cost_value_editing_type = "FORMULA" props.cost_value_editing_type = "FORMULA"
@@ -234,48 +243,44 @@ class Resource(bonsai.core.tool.Resource):
prop.enum_value = str(data["UnitBasis"].UnitComponent.id()) prop.enum_value = str(data["UnitBasis"].UnitComponent.id())
return True return True
props = bpy.context.scene.BIMResourceProperties props = cls.get_resource_props()
bonsai.bim.helper.import_attributes(cost_value, props.cost_value_attributes, callback) bonsai.bim.helper.import_attributes(cost_value, props.cost_value_attributes, callback)
@classmethod @classmethod
def enable_editing_cost_value_attributes(cls, cost_value: ifcopenshell.entity_instance) -> None: def enable_editing_cost_value_attributes(cls, cost_value: ifcopenshell.entity_instance) -> None:
props = bpy.context.scene.BIMResourceProperties props = cls.get_resource_props()
props.cost_value_attributes.clear() props.cost_value_attributes.clear()
props.active_cost_value_id = cost_value.id() props.active_cost_value_id = cost_value.id()
props.cost_value_editing_type = "ATTRIBUTES" props.cost_value_editing_type = "ATTRIBUTES"
@classmethod @classmethod
def get_resource_cost_value_formula(cls): def get_resource_cost_value_formula(cls):
return bpy.context.scene.BIMResourceProperties.cost_value_formula props = cls.get_resource_props()
return props.cost_value_formula
@classmethod @classmethod
def get_resource_cost_value_attributes(cls) -> dict[str, Any]: def get_resource_cost_value_attributes(cls) -> dict[str, Any]:
def callback(attributes, prop): props = cls.get_resource_props()
def callback(data: dict[str, Any], prop: Attribute) -> bool:
if prop.name == "UnitBasisValue": if prop.name == "UnitBasisValue":
if prop.is_null: if prop.is_null:
attributes["UnitBasis"] = None data["UnitBasis"] = None
return True return True
attributes["UnitBasis"] = { data["UnitBasis"] = {
"ValueComponent": prop.float_value or 1, "ValueComponent": prop.float_value or 1,
"UnitComponent": tool.Ifc.get().by_id( "UnitComponent": tool.Ifc.get().by_id(int(props.cost_value_attributes["UnitBasisUnit"].enum_value)),
int(
bpy.context.scene.BIMResourceProperties.cost_value_attributes.get(
"UnitBasisUnit"
).enum_value
)
),
} }
return True return True
if prop.name == "UnitBasisUnit": if prop.name == "UnitBasisUnit":
return True return True
return False
return bonsai.bim.helper.export_attributes( return bonsai.bim.helper.export_attributes(props.cost_value_attributes, callback)
bpy.context.scene.BIMResourceProperties.cost_value_attributes, callback
)
@classmethod @classmethod
def enable_editing_resource_base_quantity(cls, resource: ifcopenshell.entity_instance) -> None: def enable_editing_resource_base_quantity(cls, resource: ifcopenshell.entity_instance) -> None:
props = bpy.context.scene.BIMResourceProperties props = cls.get_resource_props()
props.active_resource_id = resource.id() props.active_resource_id = resource.id()
props.editing_resource_type = "QUANTITY" props.editing_resource_type = "QUANTITY"
props.active_resource_class = resource.is_a() props.active_resource_class = resource.is_a()
@@ -283,22 +288,24 @@ class Resource(bonsai.core.tool.Resource):
@classmethod @classmethod
def enable_editing_resource_quantity(cls, resource_quantity: ifcopenshell.entity_instance) -> None: def enable_editing_resource_quantity(cls, resource_quantity: ifcopenshell.entity_instance) -> None:
props = bpy.context.scene.BIMResourceProperties props = cls.get_resource_props()
props.quantity_attributes.clear() props.quantity_attributes.clear()
props.is_editing_quantity = True props.is_editing_quantity = True
bonsai.bim.helper.import_attributes(resource_quantity, props.quantity_attributes) bonsai.bim.helper.import_attributes(resource_quantity, props.quantity_attributes)
@classmethod @classmethod
def disable_editing_resource_quantity(cls) -> None: def disable_editing_resource_quantity(cls) -> None:
bpy.context.scene.BIMResourceProperties.is_editing_quantity = False props = cls.get_resource_props()
props.property_unset("is_editing_quantity")
@classmethod @classmethod
def get_resource_quantity_attributes(cls) -> dict[str, Any]: def get_resource_quantity_attributes(cls) -> dict[str, Any]:
return bonsai.bim.helper.export_attributes(bpy.context.scene.BIMResourceProperties.quantity_attributes) props = cls.get_resource_props()
return bonsai.bim.helper.export_attributes(props.quantity_attributes)
@classmethod @classmethod
def expand_resource(cls, resource: ifcopenshell.entity_instance) -> None: def expand_resource(cls, resource: ifcopenshell.entity_instance) -> None:
props = bpy.context.scene.BIMResourceProperties props = cls.get_resource_props()
contracted_resources = json.loads(props.contracted_resources) contracted_resources = json.loads(props.contracted_resources)
if not resource.id() in contracted_resources: if not resource.id() in contracted_resources:
return return
@@ -307,7 +314,7 @@ class Resource(bonsai.core.tool.Resource):
@classmethod @classmethod
def contract_resource(cls, resource: ifcopenshell.entity_instance) -> None: def contract_resource(cls, resource: ifcopenshell.entity_instance) -> None:
props = bpy.context.scene.BIMResourceProperties props = cls.get_resource_props()
contracted_resources = json.loads(props.contracted_resources) contracted_resources = json.loads(props.contracted_resources)
contracted_resources.append(resource.id()) contracted_resources.append(resource.id())
props.contracted_resources = json.dumps(contracted_resources) props.contracted_resources = json.dumps(contracted_resources)
@@ -332,16 +339,13 @@ class Resource(bonsai.core.tool.Resource):
@classmethod @classmethod
def get_highlighted_resource(cls) -> Union[ifcopenshell.entity_instance, None]: def get_highlighted_resource(cls) -> Union[ifcopenshell.entity_instance, None]:
resources = len(bpy.context.scene.BIMResourceTreeProperties.resources) props = cls.get_resource_props()
if resources and resources > bpy.context.scene.BIMResourceProperties.active_resource_index: active_resource = props.active_resource
return tool.Ifc.get().by_id( if active_resource:
bpy.context.scene.BIMResourceTreeProperties.resources[ return tool.Ifc.get().by_id(active_resource.ifc_definition_id)
bpy.context.scene.BIMResourceProperties.active_resource_index
].ifc_definition_id
)
@classmethod @classmethod
def clear_productivity_data(cls, props: bpy.types.PropertyGroup) -> None: def clear_productivity_data(cls, props: BIMResourceProductivity) -> None:
for duration_prop in props.quantity_consumed or []: for duration_prop in props.quantity_consumed or []:
if duration_prop.name == "BaseQuantityConsumed": if duration_prop.name == "BaseQuantityConsumed":
duration_prop.years = 0 duration_prop.years = 0
@@ -356,22 +360,21 @@ class Resource(bonsai.core.tool.Resource):
@classmethod @classmethod
def load_productivity_data(cls) -> None: def load_productivity_data(cls) -> None:
duration_props = None duration_props = None
for collection_prop in bpy.context.scene.BIMResourceProductivity.quantity_consumed: productivity_props = tool.Resource.get_resource_props().productivity
for collection_prop in productivity_props.quantity_consumed:
duration_props = collection_prop if collection_prop.name == "BaseQuantityConsumed" else None duration_props = collection_prop if collection_prop.name == "BaseQuantityConsumed" else None
break break
if not duration_props: if not duration_props:
duration_props = bpy.context.scene.BIMResourceProductivity.quantity_consumed.add() duration_props = productivity_props.quantity_consumed.add()
duration_props.name = "BaseQuantityConsumed" duration_props.name = "BaseQuantityConsumed"
cls.clear_productivity_data(bpy.context.scene.BIMResourceProductivity) cls.clear_productivity_data(productivity_props)
current_resource = tool.Resource.get_highlighted_resource() current_resource = tool.Resource.get_highlighted_resource()
if current_resource: if current_resource:
productivity = cls.get_productivity(current_resource) productivity = cls.get_productivity(current_resource)
if productivity: if productivity:
bpy.context.scene.BIMResourceProductivity.quantity_produced = ( productivity_props.quantity_produced = ifcopenshell.util.resource.get_quantity_produced(productivity)
ifcopenshell.util.resource.get_quantity_produced(productivity) productivity_props.quantity_produced_name = ifcopenshell.util.resource.get_quantity_produced_name(
) productivity
bpy.context.scene.BIMResourceProductivity.quantity_produced_name = (
ifcopenshell.util.resource.get_quantity_produced_name(productivity)
) )
time_consumed = ifcopenshell.util.resource.get_unit_consumed(productivity) time_consumed = ifcopenshell.util.resource.get_unit_consumed(productivity)
if time_consumed: if time_consumed:
@@ -387,7 +390,7 @@ class Resource(bonsai.core.tool.Resource):
@classmethod @classmethod
def get_productivity_attributes(cls) -> dict[str, Any]: def get_productivity_attributes(cls) -> dict[str, Any]:
props = bpy.context.scene.BIMResourceProductivity props = tool.Resource.get_resource_props().productivity
productivity = {} productivity = {}
if props.quantity_consumed: if props.quantity_consumed:
import bonsai.bim.module.sequence.helper as helper import bonsai.bim.module.sequence.helper as helper
@@ -446,24 +449,24 @@ class Resource(bonsai.core.tool.Resource):
@classmethod @classmethod
def go_to_resource(cls, resource: ifcopenshell.entity_instance) -> None: def go_to_resource(cls, resource: ifcopenshell.entity_instance) -> None:
def get_ancestors_ids(resource): def get_ancestors_ids(resource: ifcopenshell.entity_instance) -> list[int]:
ids = [] ids: list[int] = []
for rel in resource.Nests or []: for rel in resource.Nests or []:
ids.append(rel.RelatingObject.id()) ids.append(rel.RelatingObject.id())
ids.extend(get_ancestors_ids(rel.RelatingObject)) ids.extend(get_ancestors_ids(rel.RelatingObject))
return ids return ids
props = cls.get_resource_props()
ancestors = get_ancestors_ids(resource) ancestors = get_ancestors_ids(resource)
contracted_resources = json.loads(bpy.context.scene.BIMResourceProperties.contracted_resources) contracted_resources = json.loads(props.contracted_resources)
for ancestor in ancestors: for ancestor in ancestors:
if ancestor in contracted_resources: if ancestor in contracted_resources:
contracted_resources.remove(ancestor) contracted_resources.remove(ancestor)
bpy.context.scene.BIMResourceProperties.contracted_resources = json.dumps(contracted_resources) props.contracted_resources = json.dumps(contracted_resources)
cls.load_resources() cls.load_resources()
resource_props = bpy.context.scene.BIMResourceTreeProperties expanded_resources = [item.ifc_definition_id for item in props.tree.resources]
expanded_resources = [item.ifc_definition_id for item in resource_props.resources] props.active_resource_index = expanded_resources.index(resource.id())
bpy.context.scene.BIMResourceProperties.active_resource_index = expanded_resources.index(resource.id())
@classmethod @classmethod
def run_calculate_resource_usage(cls, resource: ifcopenshell.entity_instance) -> None: def run_calculate_resource_usage(cls, resource: ifcopenshell.entity_instance) -> None: