This commit is contained in:
Andrej
2025-06-06 12:40:08 +05:00
parent a374a7e3ff
commit bf4a3f074f
10 changed files with 160 additions and 103 deletions
@@ -21,6 +21,7 @@ import ifcopenshell
import ifcopenshell.util.date
import ifcopenshell.util.classification
import bonsai.tool as tool
from typing import Any
from bonsai.bim.ifc import IfcStore
@@ -157,8 +158,8 @@ class CostClassificationsData(ReferencesData):
cls.data["object_type"] = "Cost"
@classmethod
def references(cls):
results = []
def references(cls) -> list[dict[str, Any]]:
results: list[dict[str, Any]] = []
props = tool.Cost.get_cost_props()
element = tool.Ifc.get().by_id(props.cost_items[props.active_cost_item_index].ifc_definition_id)
if element:
@@ -46,6 +46,7 @@ class AddCostSchedule(bpy.types.Operator, tool.Ifc.Operator):
def draw(self, context):
layout = self.layout
assert layout
props = tool.Cost.get_cost_props()
layout.prop(self, "name", text="Name")
layout.prop(props, "cost_schedule_predefined_types", text="Type")
@@ -149,6 +150,9 @@ class ExpandCostItem(bpy.types.Operator, tool.Ifc.Operator):
bl_description = "Expand this cost item"
cost_item: bpy.props.IntProperty()
if TYPE_CHECKING:
cost_item: int
def _execute(self, context):
core.expand_cost_item(tool.Cost, cost_item=tool.Ifc.get().by_id(self.cost_item))
@@ -171,6 +175,9 @@ class ContractCostItem(bpy.types.Operator, tool.Ifc.Operator):
bl_description = "Contract a cost item"
cost_item: bpy.props.IntProperty()
if TYPE_CHECKING:
cost_item: int
def _execute(self, context):
core.contract_cost_item(tool.Cost, cost_item=tool.Ifc.get().by_id(self.cost_item))
@@ -192,6 +199,9 @@ class RemoveCostItem(bpy.types.Operator, tool.Ifc.Operator):
bl_options = {"REGISTER", "UNDO"}
cost_item: bpy.props.IntProperty()
if TYPE_CHECKING:
cost_item: int
def _execute(self, context):
core.remove_cost_item(tool.Ifc, tool.Cost, cost_item_id=self.cost_item)
@@ -700,6 +710,9 @@ class ExpandCostItemRate(bpy.types.Operator, tool.Ifc.Operator):
bl_options = {"REGISTER", "UNDO"}
cost_item: bpy.props.IntProperty()
if TYPE_CHECKING:
cost_item: int
def _execute(self, context):
core.expand_cost_item_rate(tool.Cost, self.cost_item)
return {"FINISHED"}
@@ -711,6 +724,9 @@ class ContractCostItemRate(bpy.types.Operator, tool.Ifc.Operator):
bl_options = {"REGISTER", "UNDO"}
cost_item: bpy.props.IntProperty()
if TYPE_CHECKING:
cost_item: int
def _execute(self, context):
core.contract_cost_item_rate(tool.Cost, self.cost_item)
return {"FINISHED"}
+24 -17
View File
@@ -18,6 +18,7 @@
import bpy
import ifcopenshell.api
import ifcopenshell.api.cost
import bonsai.tool as tool
from bonsai.bim.module.classification.data import CostClassificationsData
from bonsai.bim.module.cost.data import CostSchedulesData, CostItemRatesData, CostItemQuantitiesData
@@ -36,42 +37,48 @@ from bpy.props import (
from typing import TYPE_CHECKING, Literal
def get_schedule_of_rates(self, context):
def get_schedule_of_rates(self: "BIMCostProperties", context: bpy.types.Context) -> tool.Blender.BLENDER_ENUM_ITEMS:
if not CostItemRatesData.is_loaded:
CostItemRatesData.load()
# return CostItemRatesData.data["schedule_of_rates"]
return CostItemRatesData.data["cost_schedules"]
def update_schedule_of_rates(self, context):
def update_schedule_of_rates(self: "BIMCostProperties", context: bpy.types.Context) -> None:
tool.Cost.load_schedule_of_rates_tree(schedule_of_rates=tool.Ifc.get().by_id(int(self.schedule_of_rates)))
def get_quantity_types(self, context):
def get_quantity_types(self: "BIMCostProperties", context: bpy.types.Context) -> tool.Blender.BLENDER_ENUM_ITEMS:
if not CostSchedulesData.is_loaded:
CostSchedulesData.load()
return CostSchedulesData.data["quantity_types"]
def get_product_quantity_names(self, context):
def get_product_quantity_names(
self: "BIMCostProperties", context: bpy.types.Context
) -> tool.Blender.BLENDER_ENUM_ITEMS:
if not CostItemQuantitiesData.is_loaded:
CostItemQuantitiesData.load()
return CostItemQuantitiesData.data["product_quantity_names"]
def get_process_quantity_names(self, context):
def get_process_quantity_names(
self: "BIMCostProperties", context: bpy.types.Context
) -> tool.Blender.BLENDER_ENUM_ITEMS:
if not CostItemQuantitiesData.is_loaded:
CostItemQuantitiesData.load()
return CostItemQuantitiesData.data["process_quantity_names"]
def get_resource_quantity_names(self, context):
def get_resource_quantity_names(
self: "BIMCostProperties", context: bpy.types.Context
) -> tool.Blender.BLENDER_ENUM_ITEMS:
if not CostItemQuantitiesData.is_loaded:
CostItemQuantitiesData.load()
return CostItemQuantitiesData.data["resource_quantity_names"]
def update_active_cost_item_index(self, context):
def update_active_cost_item_index(self: "BIMCostProperties", context: bpy.types.Context) -> None:
schedule = tool.Ifc.get().by_id(self.active_cost_schedule_id)
if schedule.PredefinedType == "SCHEDULEOFRATES":
tool.Cost.load_cost_item_types()
@@ -84,11 +91,11 @@ def update_cost_item_identification(self: "CostItem", context: bpy.types.Context
props = tool.Cost.get_cost_props()
if not props.is_cost_update_enabled or self.identification == "XXX":
return
self.file = tool.Ifc.get()
ifcopenshell.api.run(
"cost.edit_cost_item",
self.file,
**{"cost_item": self.file.by_id(self.ifc_definition_id), "attributes": {"Identification": self.identification}},
ifc_file = tool.Ifc.get()
ifcopenshell.api.cost.edit_cost_item(
ifc_file,
cost_item=ifc_file.by_id(self.ifc_definition_id),
attributes={"Identification": self.identification},
)
if props.active_cost_item_id == self.ifc_definition_id:
attribute = props.cost_item_attributes["Identification"]
@@ -99,11 +106,11 @@ def update_cost_item_name(self: "CostItem", context: bpy.types.Context) -> None:
props = tool.Cost.get_cost_props()
if not props.is_cost_update_enabled or self.name == "Unnamed":
return
self.file = tool.Ifc.get()
ifcopenshell.api.run(
"cost.edit_cost_item",
self.file,
**{"cost_item": self.file.by_id(self.ifc_definition_id), "attributes": {"Name": self.name}},
ifc_file = tool.Ifc.get()
ifcopenshell.api.cost.edit_cost_item(
ifc_file,
cost_item=ifc_file.by_id(self.ifc_definition_id),
attributes={"Name": self.name},
)
if props.active_cost_item_id == self.ifc_definition_id:
attribute = props.cost_item_attributes["Name"]
@@ -102,7 +102,7 @@ class RemoveProfileDef(bpy.types.Operator, tool.Ifc.Operator):
self.report({"ERROR"}, error_msg)
return {"CANCELLED"}
ifcopenshell.api.run("profile.remove_profile", ifc_file, profile=profile)
ifcopenshell.api.profile.remove_profile(ifc_file, profile=profile)
bpy.ops.bim.load_profiles()
# preserve selected index if possible
@@ -145,7 +145,7 @@ class EditProfile(bpy.types.Operator, tool.Ifc.Operator):
props = tool.Profile.get_profile_props()
attributes = bonsai.bim.helper.export_attributes(props.profile_attributes)
profile = tool.Ifc.get().by_id(props.active_profile_id)
ifcopenshell.api.run("profile.edit_profile", tool.Ifc.get(), profile=profile, attributes=attributes)
ifcopenshell.api.profile.edit_profile(tool.Ifc.get(), profile=profile, attributes=attributes)
model_profile.DumbProfileRegenerator().regenerate_from_profile_def(profile)
bpy.ops.bim.load_profiles()
generate_thumbnail_for_active_profile()
@@ -179,6 +179,7 @@ class AddProfileDef(bpy.types.Operator, tool.Ifc.Operator):
points = [(0, 0), (0.1, 0), (0.1, 0.1), (0, 0.1), (0, 0)]
profile = ifcopenshell.api.profile.add_arbitrary_profile(tool.Ifc.get(), profile=points)
else:
assert obj and isinstance(obj.data, bpy.types.Mesh)
if "inner_curves" not in indices:
points = [(obj.data.vertices[i].co.x, obj.data.vertices[i].co.y) for i in indices["profile"]]
points.append(points[0])
@@ -199,7 +200,7 @@ class AddProfileDef(bpy.types.Operator, tool.Ifc.Operator):
)
else:
profile = ifcopenshell.api.run("profile.add_parameterized_profile", tool.Ifc.get(), ifc_class=profile_class)
profile = ifcopenshell.api.profile.add_parameterized_profile(tool.Ifc.get(), ifc_class=profile_class)
tool.Profile.set_default_profile_attrs(profile)
profile.ProfileName = "New Profile"
bpy.ops.bim.load_profiles()
@@ -93,11 +93,14 @@ class ReassignClass(bpy.types.Operator, tool.Ifc.Operator):
bl_options = {"REGISTER", "UNDO"}
obj: bpy.props.StringProperty()
if TYPE_CHECKING:
obj: str
def _execute(self, context):
if self.obj:
objects = [bpy.data.objects.get(self.obj)]
objects = [bpy.data.objects[self.obj]]
else:
objects = set(context.selected_objects + [context.active_object])
objects = tool.Blender.get_selected_objects()
self.file = tool.Ifc.get()
root_props = tool.Root.get_root_props()
ifc_product = root_props.ifc_product
+91 -69
View File
@@ -26,32 +26,34 @@ if TYPE_CHECKING:
import bonsai.tool as tool
def add_cost_schedule(ifc: tool.Ifc, name: str, predefined_type: str) -> None:
def add_cost_schedule(ifc: type[tool.Ifc], name: str, predefined_type: str) -> None:
ifc.run("cost.add_cost_schedule", name=name, predefined_type=predefined_type)
def edit_cost_schedule(ifc: tool.Ifc, cost: tool.Cost, cost_schedule: ifcopenshell.entity_instance) -> None:
def edit_cost_schedule(ifc: type[tool.Ifc], cost: type[tool.Cost], cost_schedule: ifcopenshell.entity_instance) -> None:
attributes = cost.get_cost_schedule_attributes()
ifc.run("cost.edit_cost_schedule", cost_schedule=cost_schedule, attributes=attributes)
cost.disable_editing_cost_schedule()
def disable_editing_cost_schedule(cost: tool.Cost) -> None:
def disable_editing_cost_schedule(cost: type[tool.Cost]) -> None:
cost.disable_editing_cost_schedule()
def remove_cost_schedule(ifc: tool.Ifc, cost: tool.Cost, cost_schedule: ifcopenshell.entity_instance) -> None:
def remove_cost_schedule(
ifc: type[tool.Ifc], cost: type[tool.Cost], cost_schedule: ifcopenshell.entity_instance
) -> None:
cost.remove_stored_schedule_columns(cost_schedule)
cost.remove_csv_filepath(cost_schedule)
ifc.run("cost.remove_cost_schedule", cost_schedule=cost_schedule)
def enable_editing_cost_schedule_attributes(cost: tool.Cost, cost_schedule: ifcopenshell.entity_instance) -> None:
def enable_editing_cost_schedule_attributes(cost: type[tool.Cost], cost_schedule: ifcopenshell.entity_instance) -> None:
cost.load_cost_schedule_attributes(cost_schedule)
cost.enable_editing_cost_schedule_attributes(cost_schedule)
def enable_editing_cost_items(cost: tool.Cost, cost_schedule: ifcopenshell.entity_instance) -> None:
def enable_editing_cost_items(cost: type[tool.Cost], cost_schedule: ifcopenshell.entity_instance) -> None:
cost.enable_editing_cost_items(cost_schedule)
cost.load_active_schedule_columns()
cost.load_cost_schedule_tree()
@@ -60,55 +62,57 @@ def enable_editing_cost_items(cost: tool.Cost, cost_schedule: ifcopenshell.entit
cost.play_sound()
def add_summary_cost_item(ifc: tool.Ifc, cost: tool.Cost, cost_schedule: ifcopenshell.entity_instance) -> None:
def add_summary_cost_item(
ifc: type[tool.Ifc], cost: type[tool.Cost], cost_schedule: ifcopenshell.entity_instance
) -> None:
ifc.run("cost.add_cost_item", cost_schedule=cost_schedule)
cost.load_cost_schedule_tree()
# cost.play_sound()
def add_cost_item(ifc: tool.Ifc, cost: tool.Cost, cost_item: ifcopenshell.entity_instance) -> None:
def add_cost_item(ifc: type[tool.Ifc], cost: type[tool.Cost], cost_item: ifcopenshell.entity_instance) -> None:
ifc.run("cost.add_cost_item", cost_item=cost_item)
cost.load_cost_schedule_tree()
# cost.enable_editing_cost_schedule_attributes(cost_schedule)
def expand_cost_item(cost: tool.Cost, cost_item: ifcopenshell.entity_instance) -> None:
def expand_cost_item(cost: type[tool.Cost], cost_item: ifcopenshell.entity_instance) -> None:
cost.expand_cost_item(cost_item)
cost.load_cost_schedule_tree()
def expand_cost_items(cost: tool.Cost) -> None:
def expand_cost_items(cost: type[tool.Cost]) -> None:
cost.expand_cost_items()
cost.load_cost_schedule_tree()
def contract_cost_item(cost: tool.Cost, cost_item: ifcopenshell.entity_instance) -> None:
def contract_cost_item(cost: type[tool.Cost], cost_item: ifcopenshell.entity_instance) -> None:
cost.contract_cost_item(cost_item)
cost.load_cost_schedule_tree()
def contract_cost_items(cost: tool.Cost) -> None:
def contract_cost_items(cost: type[tool.Cost]) -> None:
cost.contract_cost_items()
cost.load_cost_schedule_tree()
def remove_cost_item(ifc: tool.Ifc, cost: tool.Cost, cost_item_id: int) -> None:
def remove_cost_item(ifc: type[tool.Ifc], cost: type[tool.Cost], cost_item_id: int) -> None:
cost_item = ifc.get().by_id(cost_item_id)
ifc.run("cost.remove_cost_item", cost_item=cost_item)
cost.clean_up_cost_item_tree(cost_item_id)
cost.load_cost_schedule_tree()
def enable_editing_cost_item_attributes(cost: tool.Cost, cost_item: ifcopenshell.entity_instance) -> None:
def enable_editing_cost_item_attributes(cost: type[tool.Cost], cost_item: ifcopenshell.entity_instance) -> None:
cost.enable_editing_cost_item_attributes(cost_item)
cost.load_cost_item_attributes(cost_item)
def disable_editing_cost_item(cost: tool.Cost) -> None:
def disable_editing_cost_item(cost: type[tool.Cost]) -> None:
cost.disable_editing_cost_item()
def edit_cost_item(ifc: tool.Ifc, cost: tool.Cost) -> None:
def edit_cost_item(ifc: type[tool.Ifc], cost: type[tool.Cost]) -> None:
attributes = cost.get_cost_item_attributes()
ifc.run("cost.edit_cost_item", cost_item=cost.get_active_cost_item(), attributes=attributes)
cost.disable_editing_cost_item()
@@ -116,7 +120,11 @@ def edit_cost_item(ifc: tool.Ifc, cost: tool.Cost) -> None:
def assign_cost_item_type(
ifc: tool.Ifc, cost: tool.Cost, spatial: tool.Spatial, cost_item: ifcopenshell.entity_instance, prop_name
ifc: type[tool.Ifc],
cost: type[tool.Cost],
spatial: type[tool.Spatial],
cost_item: ifcopenshell.entity_instance,
prop_name,
) -> list[ifcopenshell.entity_instance]:
"""
Returns:
@@ -132,9 +140,9 @@ def assign_cost_item_type(
def unassign_cost_item_type(
ifc: tool.Ifc,
cost: tool.Cost,
spatial: tool.Spatial,
ifc: type[tool.Ifc],
cost: type[tool.Cost],
spatial: type[tool.Spatial],
cost_item: ifcopenshell.entity_instance,
product_types: Optional[list[ifcopenshell.entity_instance]] = None,
) -> list[ifcopenshell.entity_instance]:
@@ -152,16 +160,16 @@ def unassign_cost_item_type(
return product_types
def load_cost_item_types(cost: tool.Cost) -> None:
def load_cost_item_types(cost: type[tool.Cost]) -> None:
cost_item = cost.get_active_cost_item()
cost.load_cost_item_types(cost_item)
def assign_cost_item_quantity(
ifc: tool.Ifc,
cost: tool.Cost,
ifc: type[tool.Ifc],
cost: type[tool.Cost],
cost_item: ifcopenshell.entity_instance,
related_object_type: tool.Cost.RELATED_OBJECT_TYPE,
related_object_type: type[tool.Cost].RELATED_OBJECT_TYPE,
prop_name: str,
) -> bool:
products = cost.get_products(related_object_type)
@@ -173,27 +181,30 @@ def assign_cost_item_quantity(
return False
def load_cost_item_quantities(cost: tool.Cost) -> None:
def load_cost_item_quantities(cost: type[tool.Cost]) -> None:
cost.load_cost_item_quantities()
def load_cost_item_element_quantities(cost: tool.Cost) -> None:
def load_cost_item_element_quantities(cost: type[tool.Cost]) -> None:
cost_item = cost.get_highlighted_cost_item()
cost.load_cost_item_quantity_assignments(cost_item, related_object_type="PRODUCT")
def load_cost_item_task_quantities(cost: tool.Cost) -> None:
def load_cost_item_task_quantities(cost: type[tool.Cost]) -> None:
cost_item = cost.get_highlighted_cost_item()
cost.load_cost_item_quantity_assignments(cost_item, related_object_type="PROCESS")
def load_cost_item_resource_quantities(cost: tool.Cost) -> None:
def load_cost_item_resource_quantities(cost: type[tool.Cost]) -> None:
cost_item = cost.get_highlighted_cost_item()
cost.load_cost_item_quantity_assignments(cost_item, related_object_type="RESOURCE")
def assign_cost_value(
ifc: tool.Ifc, cost: tool.Cost, cost_item: ifcopenshell.entity_instance, cost_rate: ifcopenshell.entity_instance
ifc: type[tool.Ifc],
cost: type[tool.Cost],
cost_item: ifcopenshell.entity_instance,
cost_rate: ifcopenshell.entity_instance,
) -> None:
ifc.run("cost.assign_cost_value", cost_item=cost_item, cost_rate=cost_rate)
existing_cost_rate = cost.get_assigned_rate_cost_item(cost_item)
@@ -204,13 +215,13 @@ def assign_cost_value(
ifc.run("control.assign_control", relating_control=cost_rate, related_object=cost_item)
def load_schedule_of_rates(cost: tool.Cost, schedule_of_rates: ifcopenshell.entity_instance) -> None:
def load_schedule_of_rates(cost: type[tool.Cost], schedule_of_rates: ifcopenshell.entity_instance) -> None:
cost.load_schedule_of_rates_tree(schedule_of_rates)
def unassign_cost_item_quantity(
ifc: tool.Ifc,
cost: tool.Cost,
ifc: type[tool.Ifc],
cost: type[tool.Cost],
cost_item: ifcopenshell.entity_instance,
products: list[ifcopenshell.entity_instance],
) -> None:
@@ -218,34 +229,36 @@ def unassign_cost_item_quantity(
cost.load_cost_item_quantities()
def enable_editing_cost_item_quantities(cost: tool.Cost, cost_item: ifcopenshell.entity_instance) -> None:
def enable_editing_cost_item_quantities(cost: type[tool.Cost], cost_item: ifcopenshell.entity_instance) -> None:
cost.enable_editing_cost_item_quantities(cost_item)
def enable_editing_cost_item_values(cost: tool.Cost, cost_item: ifcopenshell.entity_instance) -> None:
def enable_editing_cost_item_values(cost: type[tool.Cost], cost_item: ifcopenshell.entity_instance) -> None:
cost.enable_editing_cost_item_values(cost_item)
def add_cost_item_quantity(ifc: tool.Ifc, cost_item: ifcopenshell.entity_instance, ifc_class: str) -> None:
def add_cost_item_quantity(ifc: type[tool.Ifc], cost_item: ifcopenshell.entity_instance, ifc_class: str) -> None:
ifc.run("cost.add_cost_item_quantity", cost_item=cost_item, ifc_class=ifc_class)
def remove_cost_item_quantity(
ifc: tool.Ifc, cost_item: ifcopenshell.entity_instance, physical_quantity: ifcopenshell.entity_instance
ifc: type[tool.Ifc], cost_item: ifcopenshell.entity_instance, physical_quantity: ifcopenshell.entity_instance
) -> None:
ifc.run("cost.remove_cost_item_quantity", cost_item=cost_item, physical_quantity=physical_quantity)
def enable_editing_cost_item_quantity(cost: tool.Cost, physical_quantity: ifcopenshell.entity_instance) -> None:
def enable_editing_cost_item_quantity(cost: type[tool.Cost], physical_quantity: ifcopenshell.entity_instance) -> None:
cost.load_cost_item_quantity_attributes(physical_quantity)
cost.enable_editing_cost_item_quantity(physical_quantity)
def disable_editing_cost_item_quantity(cost: tool.Cost) -> None:
def disable_editing_cost_item_quantity(cost: type[tool.Cost]) -> None:
cost.disable_editing_cost_item_quantity()
def edit_cost_item_quantity(ifc: tool.Ifc, cost: tool.Cost, physical_quantity: ifcopenshell.entity_instance) -> None:
def edit_cost_item_quantity(
ifc: type[tool.Ifc], cost: type[tool.Cost], physical_quantity: ifcopenshell.entity_instance
) -> None:
attributes = cost.get_cost_item_quantity_attributes()
ifc.run("cost.edit_cost_item_quantity", physical_quantity=physical_quantity, attributes=attributes)
cost.disable_editing_cost_item_quantity()
@@ -253,8 +266,8 @@ def edit_cost_item_quantity(ifc: tool.Ifc, cost: tool.Cost, physical_quantity: i
def add_cost_value(
ifc: tool.Ifc,
cost: tool.Cost,
ifc: type[tool.Ifc],
cost: type[tool.Cost],
parent: ifcopenshell.entity_instance,
cost_type: Literal["FIXED", "SUM", "CATEGORY"],
cost_category: Optional[str] = None,
@@ -268,32 +281,34 @@ def add_cost_value(
def remove_cost_value(
ifc: tool.Ifc, parent: ifcopenshell.entity_instance, cost_value: ifcopenshell.entity_instance
ifc: type[tool.Ifc], parent: ifcopenshell.entity_instance, cost_value: ifcopenshell.entity_instance
) -> None:
ifc.run("cost.remove_cost_value", parent=parent, cost_value=cost_value)
def enable_editing_cost_item_value(cost: tool.Cost, cost_value: ifcopenshell.entity_instance) -> None:
def enable_editing_cost_item_value(cost: type[tool.Cost], cost_value: ifcopenshell.entity_instance) -> None:
cost.load_cost_item_value_attributes(cost_value)
cost.enable_editing_cost_item_value(cost_value)
def disable_editing_cost_item_value(cost: tool.Cost) -> None:
def disable_editing_cost_item_value(cost: type[tool.Cost]) -> None:
cost.disable_editing_cost_item_value()
def enable_editing_cost_item_value_formula(cost: tool.Cost, cost_value: ifcopenshell.entity_instance) -> None:
def enable_editing_cost_item_value_formula(cost: type[tool.Cost], cost_value: ifcopenshell.entity_instance) -> None:
cost.load_cost_item_value_formula_attributes(cost_value)
cost.enable_editing_cost_item_value_formula(cost_value)
def edit_cost_item_value_formula(ifc: tool.Ifc, cost: tool.Cost, cost_value: ifcopenshell.entity_instance) -> None:
def edit_cost_item_value_formula(
ifc: type[tool.Ifc], cost: type[tool.Cost], cost_value: ifcopenshell.entity_instance
) -> None:
formula = cost.get_cost_item_value_formula()
ifc.run("cost.edit_cost_value_formula", cost_value=cost_value, formula=formula)
cost.disable_editing_cost_item_value()
def edit_cost_value(ifc: tool.Ifc, cost: tool.Cost, cost_value: ifcopenshell.entity_instance) -> None:
def edit_cost_value(ifc: type[tool.Ifc], cost: type[tool.Cost], cost_value: ifcopenshell.entity_instance) -> None:
attributes = cost.get_cost_value_attributes()
ifc.run("cost.edit_cost_value", cost_value=cost_value, attributes=attributes)
cost.disable_editing_cost_item_value()
@@ -301,67 +316,72 @@ def edit_cost_value(ifc: tool.Ifc, cost: tool.Cost, cost_value: ifcopenshell.ent
def copy_cost_item_values(
ifc: tool.Ifc, cost: tool.Cost, source: ifcopenshell.entity_instance, destination: ifcopenshell.entity_instance
ifc: type[tool.Ifc],
cost: type[tool.Cost],
source: ifcopenshell.entity_instance,
destination: ifcopenshell.entity_instance,
) -> None:
ifc.run("cost.copy_cost_item_values", source=source, destination=destination)
def select_cost_item_products(cost: tool.Cost, spatial: tool.Spatial, cost_item: ifcopenshell.entity_instance) -> None:
def select_cost_item_products(
cost: type[tool.Cost], spatial: type[tool.Spatial], cost_item: ifcopenshell.entity_instance
) -> None:
is_deep = cost.show_nested_cost_item_elements()
products = cost.get_cost_item_products(cost_item, is_deep)
spatial.select_products(products)
def select_cost_schedule_products(
cost: tool.Cost, spatial: tool.Spatial, cost_schedule: ifcopenshell.entity_instance
cost: type[tool.Cost], spatial: type[tool.Spatial], cost_schedule: ifcopenshell.entity_instance
) -> None:
products = cost.get_cost_schedule_products(cost_schedule)
spatial.select_products(products)
def import_cost_schedule_csv(
cost: tool.Cost, file_path: str, is_schedule_of_rates: bool
cost: type[tool.Cost], file_path: str, is_schedule_of_rates: bool
) -> ifcopenshell.entity_instance:
cost_schedule = cost.import_cost_schedule_csv(file_path, is_schedule_of_rates)
return cost_schedule
def add_csv_filepath(cost: tool.Cost, file_path: str, is_schedule_of_rates: bool, cost_schedule) -> None:
def add_csv_filepath(cost: type[tool.Cost], file_path: str, is_schedule_of_rates: bool, cost_schedule) -> None:
cost.add_csv_filepath(file_path, is_schedule_of_rates, cost_schedule)
def remove_csv_filepath(cost: tool.Cost, cost_schedule) -> None:
def remove_csv_filepath(cost: type[tool.Cost], cost_schedule) -> None:
cost.remove_csv_filepath(cost_schedule)
def refresh_cost_schedule_csv(ifc: tool.Ifc, cost: tool.Cost) -> None:
def refresh_cost_schedule_csv(ifc: type[tool.Ifc], cost: type[tool.Cost]) -> None:
cost.delete_all_cost_items()
cost.refresh_cost_schedule_csv()
cost.load_cost_schedule_tree()
def add_cost_column(cost: tool.Cost, name: str) -> None:
def add_cost_column(cost: type[tool.Cost], name: str) -> None:
cost.add_cost_column(name)
def remove_cost_column(cost: tool.Cost, name: str) -> None:
def remove_cost_column(cost: type[tool.Cost], name: str) -> None:
cost.remove_cost_column(name)
def expand_cost_item_rate(cost: tool.Cost, cost_item: ifcopenshell.entity_instance) -> None:
def expand_cost_item_rate(cost: type[tool.Cost], cost_item: int) -> None:
cost.expand_cost_item_rate(cost_item)
def contract_cost_item_rate(cost: tool.Cost, cost_item: ifcopenshell.entity_instance) -> None:
def contract_cost_item_rate(cost: type[tool.Cost], cost_item: int) -> None:
cost.contract_cost_item_rate(cost_item)
def calculate_cost_item_resource_value(ifc: tool.Ifc, cost_item: ifcopenshell.entity_instance) -> None:
def calculate_cost_item_resource_value(ifc: type[tool.Ifc], cost_item: ifcopenshell.entity_instance) -> None:
ifc.run("cost.calculate_cost_item_resource_value", cost_item=cost_item)
def export_cost_schedules(
cost: tool.Cost,
cost: type[tool.Cost],
dirpath: str,
format: Literal["CSV", "ODS", "XLSX"],
cost_schedule: Union[ifcopenshell.entity_instance, None] = None,
@@ -371,8 +391,8 @@ def export_cost_schedules(
def clear_cost_item_assignments(
ifc: tool.Ifc,
cost: tool.Cost,
ifc: type[tool.Ifc],
cost: type[tool.Cost],
cost_item: ifcopenshell.entity_instance,
related_object_type: ifcopenshell.util.cost.FILTER_BY_TYPE,
) -> None:
@@ -383,7 +403,7 @@ def clear_cost_item_assignments(
cost.load_cost_schedule_tree()
def select_unassigned_products(ifc: tool.Ifc, cost: tool.Cost, spatial: tool.Spatial) -> None:
def select_unassigned_products(ifc: type[tool.Ifc], cost: type[tool.Cost], spatial: type[tool.Spatial]) -> None:
spatial.deselect_objects()
products = ifc.get().by_type("IfcElement")
cost_schedule = cost.get_active_cost_schedule()
@@ -391,12 +411,12 @@ def select_unassigned_products(ifc: tool.Ifc, cost: tool.Cost, spatial: tool.Spa
spatial.select_products(selection)
def load_product_cost_items(cost: tool.Cost, product: ifcopenshell.entity_instance) -> None:
def load_product_cost_items(cost: type[tool.Cost], product: ifcopenshell.entity_instance) -> None:
cost.load_product_cost_items(product)
def highlight_product_cost_item(
spatial: tool.Spatial, cost: tool.Cost, cost_item: ifcopenshell.entity_instance
spatial: type[tool.Spatial], cost: type[tool.Cost], cost_item: ifcopenshell.entity_instance
) -> Union[str, None]:
cost_schedule = cost.get_cost_schedule(cost_item)
is_cost_schedule_active = cost.is_cost_schedule_active(cost_schedule)
@@ -406,7 +426,7 @@ def highlight_product_cost_item(
return "Cost schedule is not active"
def change_parent_cost_item(ifc: tool.Ifc, cost: tool.Cost, new_parent) -> Union[str, None]:
def change_parent_cost_item(ifc: type[tool.Ifc], cost: type[tool.Cost], new_parent) -> Union[str, None]:
cost_item = cost.get_active_cost_item()
if cost_item and cost.is_root_cost_item(cost_item):
return "Cannot change root cost item"
@@ -416,7 +436,7 @@ def change_parent_cost_item(ifc: tool.Ifc, cost: tool.Cost, new_parent) -> Union
cost.load_cost_schedule_tree()
def copy_cost_item(ifc: tool.Ifc, cost: tool.Cost) -> None:
def copy_cost_item(ifc: type[tool.Ifc], cost: type[tool.Cost]) -> None:
cost_item = cost.get_highlighted_cost_item()
if cost_item:
cost_item = ifc.run("cost.copy_cost_item", cost_item=cost_item)
@@ -424,7 +444,7 @@ def copy_cost_item(ifc: tool.Ifc, cost: tool.Cost) -> None:
cost.load_cost_schedule_tree()
def add_currency(ifc: tool.Ifc, cost: tool.Cost) -> ifcopenshell.entity_instance:
def add_currency(ifc: type[tool.Ifc], cost: type[tool.Cost]) -> ifcopenshell.entity_instance:
unit = ifc.run("unit.add_monetary_unit")
attributes = cost.get_currency_attributes()
ifc.run("unit.edit_monetary_unit", unit=unit, attributes=attributes)
@@ -432,5 +452,7 @@ def add_currency(ifc: tool.Ifc, cost: tool.Cost) -> ifcopenshell.entity_instance
return unit
def generate_cost_schedule_browser(cost: tool.Cost, cost_schedule: ifcopenshell.entity_instance) -> bpy.types.Panel:
def generate_cost_schedule_browser(
cost: type[tool.Cost], cost_schedule: ifcopenshell.entity_instance
) -> bpy.types.Panel:
return cost.generate_cost_schedule_browser(cost_schedule)
+2 -2
View File
@@ -42,7 +42,7 @@ from mathutils import Vector
from pathlib import Path
from functools import lru_cache, cache
from bonsai.bim.ifc import IFC_CONNECTED_TYPE
from typing import Any, Optional, Union, Literal, Iterable, Callable, TypeVar, Generator, TYPE_CHECKING
from typing import Any, Optional, Union, Literal, Iterable, Callable, TypeVar, Generator, TYPE_CHECKING, Sequence
from typing_extensions import assert_never
if TYPE_CHECKING:
@@ -657,7 +657,7 @@ class Blender(bonsai.core.tool.Blender):
cls,
context: bpy.types.Context,
active_object: Optional[bpy.types.Object] = None,
selected_objects: list[bpy.types.Object] = list(),
selected_objects: Sequence[bpy.types.Object] = (),
clear_previous_selection=True,
) -> None:
if clear_previous_selection:
+11 -6
View File
@@ -38,6 +38,11 @@ if TYPE_CHECKING:
class Cost(bonsai.core.tool.Cost):
RELATED_OBJECT_TYPE = Literal["PRODUCT", "PROCESS", "RESOURCE"]
contracted_cost_items: list[int]
"""List of contracted cost item ids."""
contracted_cost_item_rates: list[int]
"""List of contracted const item rates ids."""
@classmethod
def get_cost_props(cls) -> BIMCostProperties:
@@ -662,18 +667,18 @@ class Cost(bonsai.core.tool.Cost):
return tool.Ifc.get().by_id(int(schedule_id))
@classmethod
def expand_cost_item_rate(cls, cost_item: ifcopenshell.entity_instance) -> None:
def expand_cost_item_rate(cls, cost_item_id: int) -> None:
props = cls.get_cost_props()
contracted_cost_item_rates = json.loads(props.contracted_cost_item_rates)
contracted_cost_item_rates.remove(cost_item)
contracted_cost_item_rates.remove(cost_item_id)
props.contracted_cost_item_rates = json.dumps(contracted_cost_item_rates)
cls.load_schedule_of_rates_tree(schedule_of_rates=tool.Ifc.get().by_id(int(props.schedule_of_rates)))
@classmethod
def contract_cost_item_rate(cls, cost_item: ifcopenshell.entity_instance) -> None:
def contract_cost_item_rate(cls, cost_item_id: int) -> None:
props = cls.get_cost_props()
contracted_cost_item_rates = json.loads(props.contracted_cost_item_rates)
contracted_cost_item_rates.append(cost_item)
contracted_cost_item_rates.append(cost_item_id)
props.contracted_cost_item_rates = json.dumps(contracted_cost_item_rates)
cls.load_schedule_of_rates_tree(schedule_of_rates=tool.Ifc.get().by_id(int(props.schedule_of_rates)))
@@ -807,8 +812,8 @@ class Cost(bonsai.core.tool.Cost):
@classmethod
def highlight_cost_item(cls, cost_item: ifcopenshell.entity_instance) -> None:
def expand_ancestors(cost_item):
cls.expand_cost_item(cost_item)
def expand_ancestors(cost_item: ifcopenshell.entity_instance) -> None:
cls.expand_cost_item(cost_item.id())
for rel in cost_item.Nests or []:
parent_cost = rel.RelatingObject if rel.RelatingObject.is_a("IfcCostItem") else None
if parent_cost:
+3 -1
View File
@@ -221,7 +221,9 @@ class TestReassignClass(NewFile):
bpy.ops.bim.add_occurrence(relating_type_id=relating_type_id)
bpy.ops.bim.add_occurrence(relating_type_id=relating_type_id)
slabs = [tool.Ifc.get_object(e) for e in ifc_file.by_type("IfcSlab")]
slabs = [
obj for e in ifc_file.by_type("IfcSlab") if isinstance(obj := tool.Ifc.get_object(e), bpy.types.Object)
]
assert len(slabs) == 3
tool.Blender.set_objects_selection(context, slabs[0], (slabs[1],))
@@ -715,7 +715,7 @@ class declaration:
def index_in_schema(self): ...
def name(self) -> str: ...
def name_uc(self): ...
def schema(self): ...
def schema(self) -> schema_definition: ...
def type(self): ...
class direction3: