mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-08-09 09:21:46 +00:00
typing
This commit is contained in:
@@ -369,13 +369,13 @@ class CostItemQuantitiesData:
|
||||
cls.is_loaded = True
|
||||
|
||||
@classmethod
|
||||
def product_quantity_names(cls):
|
||||
elements = tool.Spatial.get_selected_products()
|
||||
def product_quantity_names(cls) -> tool.Blender.BLENDER_ENUM_ITEMS:
|
||||
elements = list(tool.Spatial.get_selected_products())
|
||||
names = ifcopenshell.util.cost.get_product_quantity_names(elements)
|
||||
return [(n, n, "") for n in names]
|
||||
|
||||
@classmethod
|
||||
def process_quantity_names(cls):
|
||||
def process_quantity_names(cls) -> tool.Blender.BLENDER_ENUM_ITEMS:
|
||||
props = tool.Sequence.get_work_schedule_props()
|
||||
active_task_index = props.active_task_index
|
||||
tprops = tool.Sequence.get_task_tree_props()
|
||||
@@ -391,14 +391,11 @@ class CostItemQuantitiesData:
|
||||
return [(n, n, "") for n in names if n != "id"]
|
||||
|
||||
@classmethod
|
||||
def resource_quantity_names(cls):
|
||||
active_resource_index = bpy.context.scene.BIMResourceProperties.active_resource_index
|
||||
total_resources = len(bpy.context.scene.BIMResourceTreeProperties.resources)
|
||||
if not total_resources or active_resource_index >= total_resources:
|
||||
def resource_quantity_names(cls) -> tool.Blender.BLENDER_ENUM_ITEMS:
|
||||
active_resource = tool.Resource.get_resource_props().active_resource
|
||||
if not active_resource:
|
||||
return []
|
||||
ifc_definition_id = bpy.context.scene.BIMResourceTreeProperties.resources[
|
||||
active_resource_index
|
||||
].ifc_definition_id
|
||||
ifc_definition_id = active_resource.ifc_definition_id
|
||||
element = tool.Ifc.get().by_id(ifc_definition_id)
|
||||
names = set()
|
||||
qtos = ifcopenshell.util.element.get_psets(element, qtos_only=True)
|
||||
|
||||
@@ -393,7 +393,7 @@ class BIM_PT_cost_item_types(Panel):
|
||||
op.cost_item = cost_item.ifc_definition_id
|
||||
|
||||
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 has_quantity_names:
|
||||
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.cost_item = cost_item.ifc_definition_id
|
||||
|
||||
rtprops = context.scene.BIMResourceTreeProperties
|
||||
rprops = context.scene.BIMResourceProperties
|
||||
if rtprops.resources and rprops.active_resource_index < len(rtprops.resources):
|
||||
active_resource = tool.Resource.get_resource_props().active_resource
|
||||
if active_resource:
|
||||
if has_quantity_names:
|
||||
op = row2.operator("bim.assign_cost_item_quantity", text="", icon="PROPERTIES")
|
||||
op.related_object_type = "RESOURCE"
|
||||
|
||||
@@ -239,9 +239,9 @@ class ResourceQtosData(Data):
|
||||
|
||||
@classmethod
|
||||
def load(cls):
|
||||
rprops = bpy.context.scene.BIMResourceProperties
|
||||
rtprops = bpy.context.scene.BIMResourceTreeProperties
|
||||
ifc_definition_id = rtprops.resources[rprops.active_resource_index].ifc_definition_id
|
||||
active_resource = tool.Resource.get_resource_props().active_resource
|
||||
assert active_resource
|
||||
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.is_loaded = True
|
||||
|
||||
@@ -252,9 +252,9 @@ class ResourcePsetsData(Data):
|
||||
|
||||
@classmethod
|
||||
def load(cls):
|
||||
rprops = bpy.context.scene.BIMResourceProperties
|
||||
rtprops = bpy.context.scene.BIMResourceTreeProperties
|
||||
ifc_definition_id = rtprops.resources[rprops.active_resource_index].ifc_definition_id
|
||||
active_resource = tool.Resource.get_resource_props().active_resource
|
||||
assert active_resource
|
||||
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.is_loaded = True
|
||||
|
||||
|
||||
@@ -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:
|
||||
global psetnames
|
||||
rprops = context.scene.BIMResourceProperties
|
||||
rtprops = context.scene.BIMResourceTreeProperties
|
||||
ifc_class = tool.Ifc.get().by_id(rtprops.resources[rprops.active_resource_index].ifc_definition_id).is_a()
|
||||
active_resource = tool.Resource.get_resource_props().active_resource
|
||||
assert active_resource
|
||||
ifc_class = tool.Ifc.get().by_id(active_resource.ifc_definition_id).is_a()
|
||||
if ifc_class not in psetnames:
|
||||
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)
|
||||
@@ -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:
|
||||
global qtonames
|
||||
rprops = context.scene.BIMResourceProperties
|
||||
rtprops = context.scene.BIMResourceTreeProperties
|
||||
ifc_class = tool.Ifc.get().by_id(rtprops.resources[rprops.active_resource_index].ifc_definition_id).is_a()
|
||||
active_resource = tool.Resource.get_resource_props().active_resource
|
||||
assert active_resource
|
||||
ifc_class = tool.Ifc.get().by_id(active_resource.ifc_definition_id).is_a()
|
||||
if ifc_class not in qtonames:
|
||||
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)
|
||||
|
||||
@@ -596,11 +596,8 @@ class BIM_PT_resource_qtos(Panel):
|
||||
|
||||
@classmethod
|
||||
def poll(cls, context):
|
||||
props = context.scene.BIMResourceProperties
|
||||
total_resources = len(context.scene.BIMResourceTreeProperties.resources)
|
||||
if total_resources > 0 and props.active_resource_index < total_resources:
|
||||
return True
|
||||
return False
|
||||
active_resource = tool.Resource.get_resource_props().active_resource
|
||||
return bool(active_resource)
|
||||
|
||||
def draw(self, context):
|
||||
if not ResourceQtosData.is_loaded:
|
||||
@@ -631,11 +628,8 @@ class BIM_PT_resource_psets(Panel):
|
||||
|
||||
@classmethod
|
||||
def poll(cls, context):
|
||||
props = context.scene.BIMResourceProperties
|
||||
total_resources = len(context.scene.BIMResourceTreeProperties.resources)
|
||||
if total_resources > 0 and props.active_resource_index < total_resources:
|
||||
return True
|
||||
return False
|
||||
active_resource = tool.Resource.get_resource_props().active_resource
|
||||
return bool(active_resource)
|
||||
|
||||
def draw(self, context):
|
||||
if not ResourcePsetsData.is_loaded:
|
||||
|
||||
@@ -124,7 +124,7 @@ class ResourceData:
|
||||
@classmethod
|
||||
def cost_values(cls) -> list[dict[str, Any]]:
|
||||
results = []
|
||||
ifc_id = bpy.context.scene.BIMResourceProperties.active_resource_id
|
||||
ifc_id = tool.Resource.get_resource_props().active_resource_id
|
||||
if not ifc_id:
|
||||
return results
|
||||
resource = tool.Ifc.get().by_id(ifc_id)
|
||||
|
||||
@@ -87,10 +87,11 @@ class EditResource(bpy.types.Operator, tool.Ifc.Operator):
|
||||
bl_options = {"REGISTER", "UNDO"}
|
||||
|
||||
def _execute(self, context):
|
||||
props = tool.Resource.get_resource_props()
|
||||
core.edit_resource(
|
||||
tool.Ifc,
|
||||
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"}
|
||||
|
||||
def _execute(self, context):
|
||||
props = tool.Resource.get_resource_props()
|
||||
core.edit_resource_time(
|
||||
tool.Ifc,
|
||||
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),
|
||||
)
|
||||
|
||||
|
||||
|
||||
@@ -24,7 +24,7 @@ import bonsai.tool as tool
|
||||
import bonsai.bim.module.pset.data
|
||||
import bonsai.bim.module.resource.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.props import (
|
||||
PointerProperty,
|
||||
@@ -36,11 +36,12 @@ from bpy.props import (
|
||||
FloatVectorProperty,
|
||||
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
|
||||
for resource, quantities in resources.items():
|
||||
quantitytypes_enum[resource] = [(q, q, "") for q in quantities]
|
||||
@@ -49,8 +50,8 @@ def setup_quantity_types_enum():
|
||||
setup_quantity_types_enum()
|
||||
|
||||
|
||||
def updateResourceName(self, context):
|
||||
props = context.scene.BIMResourceProperties
|
||||
def updateResourceName(self: "Resource", context: object) -> None:
|
||||
props = tool.Resource.get_resource_props()
|
||||
if not props.is_resource_update_enabled:
|
||||
return
|
||||
ifc_file = tool.Ifc.get()
|
||||
@@ -66,18 +67,19 @@ def updateResourceName(self, context):
|
||||
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]
|
||||
|
||||
|
||||
def update_active_resource_index(self, context):
|
||||
def update_active_resource_index(self: "BIMResourceProperties", context: object) -> None:
|
||||
bonsai.bim.module.pset.data.refresh()
|
||||
if self.should_show_resource_tools:
|
||||
tool.Resource.load_productivity_data()
|
||||
|
||||
|
||||
def updateResourceUsage(self, context):
|
||||
if not context.scene.BIMResourceProperties.is_resource_update_enabled:
|
||||
def updateResourceUsage(self: "Resource", context: object) -> None:
|
||||
props = tool.Resource.get_resource_props()
|
||||
if not props.is_resource_update_enabled:
|
||||
return
|
||||
if not self.schedule_usage:
|
||||
return
|
||||
@@ -102,6 +104,15 @@ class ISODuration(PropertyGroup):
|
||||
minutes: IntProperty(name="Minutes", 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):
|
||||
name: StringProperty(name="Name", update=updateResourceName)
|
||||
@@ -111,10 +122,26 @@ class Resource(PropertyGroup):
|
||||
is_expanded: BoolProperty(name="Is Expanded")
|
||||
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):
|
||||
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):
|
||||
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")
|
||||
resource_time_attributes: CollectionProperty(name="Resource Usage Attributes", type=Attribute)
|
||||
editing_resource_type: EnumProperty(
|
||||
name="Editing Resource Type",
|
||||
items=(
|
||||
("ATTRIBUTES", "", ""),
|
||||
("USAGE", "", ""),
|
||||
("COSTS", "", ""),
|
||||
("QUANTITY", "", ""),
|
||||
),
|
||||
name="Editing Resource Type", items=[(i, i, "") for i in get_args(EditingResourceType)]
|
||||
)
|
||||
cost_types: EnumProperty(
|
||||
items=[
|
||||
@@ -154,9 +175,56 @@ class BIMResourceProperties(PropertyGroup):
|
||||
quantity_attributes: CollectionProperty(name="Quantity Attributes", type=Attribute)
|
||||
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):
|
||||
ifc_definition_id: IntProperty(name="IFC Definition ID")
|
||||
quantity_consumed: CollectionProperty(name="Duration", type=ISODuration)
|
||||
quantity_produced: FloatProperty(name="Quantity Produced")
|
||||
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
|
||||
|
||||
@@ -16,12 +16,16 @@
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with Bonsai. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
from __future__ import annotations
|
||||
import bpy
|
||||
import bonsai.tool as tool
|
||||
import bonsai.bim.helper
|
||||
from bpy.types import Panel, UIList
|
||||
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):
|
||||
@@ -38,9 +42,10 @@ class BIM_PT_resources(Panel):
|
||||
file = tool.Ifc.get()
|
||||
return file and hasattr(file, "schema") and file.schema != "IFC2X3"
|
||||
|
||||
layout: bpy.types.UILayout
|
||||
|
||||
def draw(self, context):
|
||||
self.props = context.scene.BIMResourceProperties
|
||||
self.tprops = context.scene.BIMResourceTreeProperties
|
||||
self.props = tool.Resource.get_resource_props()
|
||||
if not ResourceData.is_loaded:
|
||||
ResourceData.load()
|
||||
|
||||
@@ -64,7 +69,7 @@ class BIM_PT_resources(Panel):
|
||||
self.layout.template_list(
|
||||
"BIM_UL_resources",
|
||||
"",
|
||||
self.tprops,
|
||||
self.props.tree,
|
||||
"resources",
|
||||
self.props,
|
||||
"active_resource_index",
|
||||
@@ -79,18 +84,18 @@ class BIM_PT_resources(Panel):
|
||||
self.draw_editable_resource_costs_ui()
|
||||
elif self.props.active_resource_id and self.props.editing_resource_type == "USAGE":
|
||||
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.alignment = "RIGHT"
|
||||
row.prop(self.props, "should_show_resource_tools", text="Resource Tools", icon="RECOVER_LAST")
|
||||
if self.props.should_show_resource_tools:
|
||||
total_resources = len(self.tprops.resources)
|
||||
if not total_resources or self.props.active_resource_index >= total_resources:
|
||||
active_resource = self.props.active_resource
|
||||
if not active_resource:
|
||||
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]
|
||||
|
||||
if not resource["type"] in ["IfcConstructionEquipmentResource", "IfcLaborResource"]:
|
||||
@@ -145,7 +150,7 @@ class BIM_PT_resources(Panel):
|
||||
row2_col1 = col1.row()
|
||||
row2_col1.label(text="Schedule Usage")
|
||||
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.operator("bim.calculate_resource_usage", text="", icon="TEMP")
|
||||
op = row2col3.operator(
|
||||
@@ -189,7 +194,7 @@ class BIM_PT_resources(Panel):
|
||||
row.label(text="{}".format(produtivitiy_rate_message), icon="ARMATURE_DATA")
|
||||
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)
|
||||
op = row.operator("bim.add_resource", text="Add SubContract", icon="TEXT")
|
||||
op.ifc_class = "IfcSubContractResource"
|
||||
@@ -198,11 +203,11 @@ class BIM_PT_resources(Panel):
|
||||
op.ifc_class = "IfcCrewResource"
|
||||
op.parent_resource = 0
|
||||
|
||||
total_resources = len(self.tprops.resources)
|
||||
if not total_resources or self.props.active_resource_index >= total_resources:
|
||||
active_resource = self.props.active_resource
|
||||
if not active_resource:
|
||||
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]
|
||||
|
||||
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.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)
|
||||
|
||||
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)
|
||||
|
||||
def draw_editable_resource_quantity_ui(self):
|
||||
def draw_editable_resource_quantity_ui(self) -> None:
|
||||
resource = ResourceData.data["resources"][self.props.active_resource_id]
|
||||
|
||||
if resource["BaseQuantity"]:
|
||||
@@ -278,7 +283,7 @@ class BIM_PT_resources(Panel):
|
||||
op.resource = self.props.active_resource_id
|
||||
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.prop(self.props, "cost_types", text="")
|
||||
if self.props.cost_types == "CATEGORY":
|
||||
@@ -326,16 +331,6 @@ class BIM_PT_resources(Panel):
|
||||
op.parent = parent_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):
|
||||
@classmethod
|
||||
@@ -358,7 +353,16 @@ class BIM_UL_resources(UIList):
|
||||
col = row.column()
|
||||
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 = {
|
||||
"IfcSubContractResource": "TEXT",
|
||||
"IfcCrewResource": "COMMUNITY",
|
||||
@@ -369,7 +373,7 @@ class BIM_UL_resources(UIList):
|
||||
}
|
||||
if item:
|
||||
resource = ResourceData.data["resources"][item.ifc_definition_id]
|
||||
props = context.scene.BIMResourceProperties
|
||||
props = tool.Resource.get_resource_props()
|
||||
row = layout.row(align=True)
|
||||
for i in range(0, item.level_index):
|
||||
row.label(text="", icon="BLANK1")
|
||||
@@ -403,8 +407,12 @@ class BIM_UL_resources(UIList):
|
||||
row.operator("bim.disable_editing_resource", text="", icon="CANCEL")
|
||||
|
||||
|
||||
def draw_productivity_ui(self, context):
|
||||
def draw_duration_property(duration_props, layout):
|
||||
def draw_productivity_ui(self: bpy.types.Operator, context: object) -> None:
|
||||
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:
|
||||
if duration_prop.name == "BaseQuantityConsumed":
|
||||
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, "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)
|
||||
col1 = grid.column(align=False)
|
||||
col2 = grid.column(align=False)
|
||||
|
||||
@@ -386,12 +386,11 @@ class TaskICOMData:
|
||||
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
|
||||
def can_active_resource_be_assigned(cls) -> bool:
|
||||
props = tool.Resource.get_resource_props()
|
||||
active_resource = props.active_resource
|
||||
if active_resource:
|
||||
resource_id = active_resource.ifc_definition_id
|
||||
return not tool.Ifc.get().by_id(resource_id).is_a("IfcCrewResource")
|
||||
return False
|
||||
|
||||
|
||||
@@ -308,8 +308,9 @@ def updateAssignedResourceName(self, context):
|
||||
pass
|
||||
|
||||
|
||||
def updateAssignedResourceUsage(self, context):
|
||||
if not context.scene.BIMResourceProperties.is_resource_update_enabled:
|
||||
def updateAssignedResourceUsage(self: "TaskResource", context: object) -> None:
|
||||
props = tool.Resource.get_resource_props()
|
||||
if not props.is_resource_update_enabled:
|
||||
return
|
||||
if not self.schedule_usage:
|
||||
return
|
||||
|
||||
@@ -246,9 +246,9 @@ class Blender(bonsai.core.tool.Blender):
|
||||
cost_props = tool.Cost.get_cost_props()
|
||||
return cost_props.cost_items[cost_props.active_cost_item_index].ifc_definition_id
|
||||
elif obj_type == "Resource":
|
||||
return context.scene.BIMResourceTreeProperties.resources[
|
||||
context.scene.BIMResourceProperties.active_resource_index
|
||||
].ifc_definition_id
|
||||
active_resource = tool.Resource.get_resource_props().active_resource
|
||||
assert active_resource
|
||||
return active_resource.ifc_definition_id
|
||||
elif obj_type == "Profile":
|
||||
props = tool.Profile.get_profile_props()
|
||||
return props.profiles[props.active_profile_index].ifc_definition_id
|
||||
|
||||
@@ -37,18 +37,25 @@ from typing import Any, Union, TYPE_CHECKING, Literal
|
||||
|
||||
if TYPE_CHECKING:
|
||||
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):
|
||||
@classmethod
|
||||
def get_resource_props(cls) -> BIMResourceProperties:
|
||||
"""
|
||||
BIMResourceTreeProperties can be accessed using `.tree`.
|
||||
BIMResourceProductivity - using `.productivity`.
|
||||
"""
|
||||
return bpy.context.scene.BIMResourceProperties
|
||||
|
||||
@classmethod
|
||||
def load_resources(cls) -> None:
|
||||
def create_new_resource_li(resource, level_index):
|
||||
new = bpy.context.scene.BIMResourceTreeProperties.resources.add()
|
||||
props = cls.get_resource_props()
|
||||
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.is_expanded = resource.id() not in contracted_resources
|
||||
new.level_index = level_index
|
||||
@@ -61,8 +68,6 @@ class Resource(bonsai.core.tool.Resource):
|
||||
for nested_resource in rel.RelatedObjects
|
||||
]
|
||||
|
||||
props = bpy.context.scene.BIMResourceProperties
|
||||
tprops = bpy.context.scene.BIMResourceTreeProperties
|
||||
tprops.resources.clear()
|
||||
contracted_resources = json.loads(props.contracted_resources)
|
||||
props.is_resource_update_enabled = False
|
||||
@@ -77,8 +82,8 @@ class Resource(bonsai.core.tool.Resource):
|
||||
|
||||
@classmethod
|
||||
def load_resource_properties(cls) -> None:
|
||||
props = bpy.context.scene.BIMResourceProperties
|
||||
tprops = bpy.context.scene.BIMResourceTreeProperties
|
||||
props = cls.get_resource_props()
|
||||
tprops = props.tree
|
||||
props.is_resource_update_enabled = False
|
||||
for item in tprops.resources:
|
||||
resource = tool.Ifc.get().by_id(item.ifc_definition_id)
|
||||
@@ -90,20 +95,23 @@ class Resource(bonsai.core.tool.Resource):
|
||||
|
||||
@classmethod
|
||||
def disable_editing_resource(cls) -> None:
|
||||
bpy.context.scene.BIMResourceProperties.active_resource_id = 0
|
||||
bpy.context.scene.BIMResourceProperties.active_resource_time_id = 0
|
||||
props = cls.get_resource_props()
|
||||
props.property_unset("active_resource_id")
|
||||
props.property_unset("active_resource_time_id")
|
||||
|
||||
@classmethod
|
||||
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
|
||||
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
|
||||
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.resource_attributes.clear()
|
||||
props.editing_resource_type = "ATTRIBUTES"
|
||||
@@ -111,11 +119,12 @@ class Resource(bonsai.core.tool.Resource):
|
||||
|
||||
@classmethod
|
||||
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
|
||||
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.active_resource_time_id = resource.Usage.id()
|
||||
props.active_resource_id = resource.id()
|
||||
@@ -128,8 +137,10 @@ class Resource(bonsai.core.tool.Resource):
|
||||
|
||||
@classmethod
|
||||
def load_resource_time_attributes(cls, resource_time: ifcopenshell.entity_instance) -> None:
|
||||
def callback(name, prop, data):
|
||||
if prop.data_type == "string":
|
||||
props = cls.get_resource_props()
|
||||
|
||||
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):
|
||||
prop.string_value = "" if prop.is_null else data[name].isoformat()
|
||||
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")
|
||||
return True
|
||||
|
||||
bonsai.bim.helper.import_attributes(
|
||||
resource_time, bpy.context.scene.BIMResourceProperties.resource_time_attributes, callback
|
||||
)
|
||||
bonsai.bim.helper.import_attributes(resource_time, props.resource_time_attributes, callback)
|
||||
|
||||
@classmethod
|
||||
def get_resource_time_attributes(cls) -> dict[str, Any]:
|
||||
@@ -160,25 +169,25 @@ class Resource(bonsai.core.tool.Resource):
|
||||
return True
|
||||
return False
|
||||
|
||||
props = bpy.context.scene.BIMResourceProperties
|
||||
props = cls.get_resource_props()
|
||||
return bonsai.bim.helper.export_attributes(props.resource_time_attributes, callback)
|
||||
|
||||
@classmethod
|
||||
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.editing_resource_type = "COSTS"
|
||||
cls.update_cost_values_ui_data()
|
||||
|
||||
@classmethod
|
||||
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.cost_value_editing_type = ""
|
||||
|
||||
@classmethod
|
||||
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.active_cost_value_id = cost_value.id()
|
||||
props.cost_value_editing_type = "FORMULA"
|
||||
@@ -234,48 +243,44 @@ class Resource(bonsai.core.tool.Resource):
|
||||
prop.enum_value = str(data["UnitBasis"].UnitComponent.id())
|
||||
return True
|
||||
|
||||
props = bpy.context.scene.BIMResourceProperties
|
||||
props = cls.get_resource_props()
|
||||
bonsai.bim.helper.import_attributes(cost_value, props.cost_value_attributes, callback)
|
||||
|
||||
@classmethod
|
||||
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.active_cost_value_id = cost_value.id()
|
||||
props.cost_value_editing_type = "ATTRIBUTES"
|
||||
|
||||
@classmethod
|
||||
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
|
||||
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.is_null:
|
||||
attributes["UnitBasis"] = None
|
||||
data["UnitBasis"] = None
|
||||
return True
|
||||
attributes["UnitBasis"] = {
|
||||
data["UnitBasis"] = {
|
||||
"ValueComponent": prop.float_value or 1,
|
||||
"UnitComponent": tool.Ifc.get().by_id(
|
||||
int(
|
||||
bpy.context.scene.BIMResourceProperties.cost_value_attributes.get(
|
||||
"UnitBasisUnit"
|
||||
).enum_value
|
||||
)
|
||||
),
|
||||
"UnitComponent": tool.Ifc.get().by_id(int(props.cost_value_attributes["UnitBasisUnit"].enum_value)),
|
||||
}
|
||||
return True
|
||||
if prop.name == "UnitBasisUnit":
|
||||
return True
|
||||
return False
|
||||
|
||||
return bonsai.bim.helper.export_attributes(
|
||||
bpy.context.scene.BIMResourceProperties.cost_value_attributes, callback
|
||||
)
|
||||
return bonsai.bim.helper.export_attributes(props.cost_value_attributes, callback)
|
||||
|
||||
@classmethod
|
||||
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.editing_resource_type = "QUANTITY"
|
||||
props.active_resource_class = resource.is_a()
|
||||
@@ -283,22 +288,24 @@ class Resource(bonsai.core.tool.Resource):
|
||||
|
||||
@classmethod
|
||||
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.is_editing_quantity = True
|
||||
bonsai.bim.helper.import_attributes(resource_quantity, props.quantity_attributes)
|
||||
|
||||
@classmethod
|
||||
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
|
||||
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
|
||||
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)
|
||||
if not resource.id() in contracted_resources:
|
||||
return
|
||||
@@ -307,7 +314,7 @@ class Resource(bonsai.core.tool.Resource):
|
||||
|
||||
@classmethod
|
||||
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.append(resource.id())
|
||||
props.contracted_resources = json.dumps(contracted_resources)
|
||||
@@ -332,16 +339,13 @@ class Resource(bonsai.core.tool.Resource):
|
||||
|
||||
@classmethod
|
||||
def get_highlighted_resource(cls) -> Union[ifcopenshell.entity_instance, None]:
|
||||
resources = len(bpy.context.scene.BIMResourceTreeProperties.resources)
|
||||
if resources and resources > bpy.context.scene.BIMResourceProperties.active_resource_index:
|
||||
return tool.Ifc.get().by_id(
|
||||
bpy.context.scene.BIMResourceTreeProperties.resources[
|
||||
bpy.context.scene.BIMResourceProperties.active_resource_index
|
||||
].ifc_definition_id
|
||||
)
|
||||
props = cls.get_resource_props()
|
||||
active_resource = props.active_resource
|
||||
if active_resource:
|
||||
return tool.Ifc.get().by_id(active_resource.ifc_definition_id)
|
||||
|
||||
@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 []:
|
||||
if duration_prop.name == "BaseQuantityConsumed":
|
||||
duration_prop.years = 0
|
||||
@@ -356,22 +360,21 @@ class Resource(bonsai.core.tool.Resource):
|
||||
@classmethod
|
||||
def load_productivity_data(cls) -> 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
|
||||
break
|
||||
if not duration_props:
|
||||
duration_props = bpy.context.scene.BIMResourceProductivity.quantity_consumed.add()
|
||||
duration_props = productivity_props.quantity_consumed.add()
|
||||
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()
|
||||
if current_resource:
|
||||
productivity = cls.get_productivity(current_resource)
|
||||
if productivity:
|
||||
bpy.context.scene.BIMResourceProductivity.quantity_produced = (
|
||||
ifcopenshell.util.resource.get_quantity_produced(productivity)
|
||||
)
|
||||
bpy.context.scene.BIMResourceProductivity.quantity_produced_name = (
|
||||
ifcopenshell.util.resource.get_quantity_produced_name(productivity)
|
||||
productivity_props.quantity_produced = ifcopenshell.util.resource.get_quantity_produced(productivity)
|
||||
productivity_props.quantity_produced_name = ifcopenshell.util.resource.get_quantity_produced_name(
|
||||
productivity
|
||||
)
|
||||
time_consumed = ifcopenshell.util.resource.get_unit_consumed(productivity)
|
||||
if time_consumed:
|
||||
@@ -387,7 +390,7 @@ class Resource(bonsai.core.tool.Resource):
|
||||
|
||||
@classmethod
|
||||
def get_productivity_attributes(cls) -> dict[str, Any]:
|
||||
props = bpy.context.scene.BIMResourceProductivity
|
||||
props = tool.Resource.get_resource_props().productivity
|
||||
productivity = {}
|
||||
if props.quantity_consumed:
|
||||
import bonsai.bim.module.sequence.helper as helper
|
||||
@@ -446,24 +449,24 @@ class Resource(bonsai.core.tool.Resource):
|
||||
|
||||
@classmethod
|
||||
def go_to_resource(cls, resource: ifcopenshell.entity_instance) -> None:
|
||||
def get_ancestors_ids(resource):
|
||||
ids = []
|
||||
def get_ancestors_ids(resource: ifcopenshell.entity_instance) -> list[int]:
|
||||
ids: list[int] = []
|
||||
for rel in resource.Nests or []:
|
||||
ids.append(rel.RelatingObject.id())
|
||||
ids.extend(get_ancestors_ids(rel.RelatingObject))
|
||||
return ids
|
||||
|
||||
props = cls.get_resource_props()
|
||||
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:
|
||||
if ancestor in contracted_resources:
|
||||
contracted_resources.remove(ancestor)
|
||||
bpy.context.scene.BIMResourceProperties.contracted_resources = json.dumps(contracted_resources)
|
||||
props.contracted_resources = json.dumps(contracted_resources)
|
||||
cls.load_resources()
|
||||
|
||||
resource_props = bpy.context.scene.BIMResourceTreeProperties
|
||||
expanded_resources = [item.ifc_definition_id for item in resource_props.resources]
|
||||
bpy.context.scene.BIMResourceProperties.active_resource_index = expanded_resources.index(resource.id())
|
||||
expanded_resources = [item.ifc_definition_id for item in props.tree.resources]
|
||||
props.active_resource_index = expanded_resources.index(resource.id())
|
||||
|
||||
@classmethod
|
||||
def run_calculate_resource_usage(cls, resource: ifcopenshell.entity_instance) -> None:
|
||||
|
||||
Reference in New Issue
Block a user