complete costing module refactoring

This commit is contained in:
Sigma Dimensions
2023-02-11 12:34:54 +01:00
parent 0d0691a012
commit d3b176e5eb
8 changed files with 733 additions and 472 deletions
@@ -30,6 +30,7 @@ classes = (
operator.EnableEditingCostSchedule, operator.EnableEditingCostSchedule,
operator.EnableEditingCostItems, operator.EnableEditingCostItems,
operator.EnableEditingCostItem, operator.EnableEditingCostItem,
operator.ExpandCostItems,
operator.EnableEditingCostItemQuantities, operator.EnableEditingCostItemQuantities,
operator.EnableEditingCostItemQuantity, operator.EnableEditingCostItemQuantity,
operator.EnableEditingCostItemValues, operator.EnableEditingCostItemValues,
@@ -281,7 +281,9 @@ class CostItemQuantitiesData:
total_resources = len(bpy.context.scene.BIMResourceTreeProperties.resources) total_resources = len(bpy.context.scene.BIMResourceTreeProperties.resources)
if not total_resources or active_resource_index >= total_resources: if not total_resources or active_resource_index >= total_resources:
return [] return []
ifc_definition_id = bpy.context.scene.BIMResourceTreeProperties.resources[active_resource_index].ifc_definition_id ifc_definition_id = bpy.context.scene.BIMResourceTreeProperties.resources[
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)
@@ -62,15 +62,16 @@ class RemoveCostSchedule(bpy.types.Operator, tool.Ifc.Operator):
core.remove_cost_schedule(tool.Ifc, cost_schedule=tool.Ifc.get().by_id(self.cost_schedule)) core.remove_cost_schedule(tool.Ifc, cost_schedule=tool.Ifc.get().by_id(self.cost_schedule))
class EnableEditingCostSchedule(bpy.types.Operator, tool.Ifc.Operator): class EnableEditingCostSchedule(bpy.types.Operator):
bl_idname = "bim.enable_editing_cost_schedule_attributes" bl_idname = "bim.enable_editing_cost_schedule_attributes"
bl_label = "Enable Editing Cost Schedule" bl_label = "Enable Editing Cost Schedule"
bl_options = {"REGISTER", "UNDO"} bl_options = {"REGISTER", "UNDO"}
bl_description = "Enable editing cost schedule" bl_description = "Enable editing cost schedule"
cost_schedule: bpy.props.IntProperty() cost_schedule: bpy.props.IntProperty()
def _execute(self, context): def execute(self, context):
core.enable_editing_cost_schedule_attributes(tool.Cost, cost_schedule=tool.Ifc.get().by_id(self.cost_schedule)) core.enable_editing_cost_schedule_attributes(tool.Cost, cost_schedule=tool.Ifc.get().by_id(self.cost_schedule))
return {"FINISHED"}
class EnableEditingCostItems(bpy.types.Operator, tool.Ifc.Operator): class EnableEditingCostItems(bpy.types.Operator, tool.Ifc.Operator):
@@ -194,18 +195,13 @@ class AssignCostItemType(bpy.types.Operator, tool.Ifc.Operator):
prop_name: bpy.props.StringProperty() prop_name: bpy.props.StringProperty()
def _execute(self, context): def _execute(self, context):
self.file = IfcStore.get_file() core.assign_cost_item_type(
cost_item = self.file.by_id(self.cost_item) tool.Ifc,
for obj in context.selected_objects: tool.Cost,
if not obj.BIMObjectProperties.ifc_definition_id: tool.Spatial,
continue cost_item=tool.Ifc.get().by_id(self.cost_item),
product = self.file.by_id(obj.BIMObjectProperties.ifc_definition_id) prop_name=self.prop_name, # TODO: REVIEW PROP_NAME USABILITY
if product.is_a("IfcTypeProduct"): )
ifcopenshell.api.run(
"control.assign_control", self.file, relating_control=cost_item, related_object=product
)
bpy.ops.bim.load_cost_item_types()
return {"FINISHED"}
class UnassignCostItemType(bpy.types.Operator, tool.Ifc.Operator): class UnassignCostItemType(bpy.types.Operator, tool.Ifc.Operator):
@@ -216,22 +212,12 @@ class UnassignCostItemType(bpy.types.Operator, tool.Ifc.Operator):
related_object: bpy.props.IntProperty() related_object: bpy.props.IntProperty()
def _execute(self, context): def _execute(self, context):
self.file = IfcStore.get_file() core.unassign_cost_item_type(
cost_item = self.file.by_id(self.cost_item) tool.Ifc,
if self.related_object: tool.Cost,
products = [self.file.by_id(self.related_object)] self.cost_item,
else: products=[tool.Ifc.get().by_id(self.related_object)] if self.related_object else [],
for obj in context.selected_objects: )
if not obj.BIMObjectProperties.ifc_definition_id:
continue
product = self.file.by_id(obj.BIMObjectProperties.ifc_definition_id)
if product.is_a("IfcTypeProduct"):
products.append(product)
for product in products:
ifcopenshell.api.run(
"control.unassign_control", self.file, relating_control=cost_item, related_object=product
)
bpy.ops.bim.load_cost_item_types()
return {"FINISHED"} return {"FINISHED"}
@@ -244,157 +230,106 @@ class AssignCostItemQuantity(bpy.types.Operator, tool.Ifc.Operator):
prop_name: bpy.props.StringProperty() prop_name: bpy.props.StringProperty()
def _execute(self, context): def _execute(self, context):
if self.related_object_type == "PRODUCT": core.assign_cost_item_quantity(
products = [ tool.Ifc,
tool.Ifc.get().by_id(o.BIMObjectProperties.ifc_definition_id) tool.Cost,
for o in context.selected_objects
if o.BIMObjectProperties.ifc_definition_id
]
elif self.related_object_type == "PROCESS":
products = [
tool.Ifc.get().by_id(
context.scene.BIMTaskTreeProperties.tasks[
context.scene.BIMWorkScheduleProperties.active_task_index
].ifc_definition_id
)
]
elif self.related_object_type == "RESOURCE":
products = [
tool.Ifc.get().by_id(
context.scene.BIMResourceTreeProperties.resources[
context.scene.BIMResourceProperties.active_resource_index
].ifc_definition_id
)
]
ifcopenshell.api.run(
"cost.assign_cost_item_quantity",
tool.Ifc.get(),
cost_item=tool.Ifc.get().by_id(self.cost_item), cost_item=tool.Ifc.get().by_id(self.cost_item),
products=products, related_object_type=self.related_object_type,
prop_name=self.prop_name, prop_name=self.prop_name, # TODO: REVIEW PROP_NAME USABILITY
) )
bpy.ops.bim.load_cost_item_quantities()
return {"FINISHED"}
class UnassignCostItemQuantity(bpy.types.Operator, tool.Ifc.Operator): class UnassignCostItemQuantity(bpy.types.Operator, tool.Ifc.Operator):
bl_idname = "bim.unassign_cost_item_quantity" bl_idname = "bim.unassign_cost_item_quantity"
bl_label = "Unassign Cost Item Quantity" bl_label = "Unassign Cost Item Quantity"
bl_options = {"REGISTER", "UNDO"} bl_options = {"REGISTER", "UNDO"}
bl_description = "Unassign cost item quantity"
cost_item: bpy.props.IntProperty() cost_item: bpy.props.IntProperty()
related_object: bpy.props.IntProperty() related_object: bpy.props.IntProperty()
def _execute(self, context): def _execute(self, context):
self.file = IfcStore.get_file() core.unassign_cost_item_quantity(
if self.related_object: tool.Ifc,
products = [self.file.by_id(self.related_object)] tool.Cost,
else: cost_item=tool.Ifc.get().by_id(self.cost_item),
products = [ products=[tool.Ifc.get().by_id(self.related_object)]
self.file.by_id(o.BIMObjectProperties.ifc_definition_id) if self.related_object
for o in context.selected_objects else tool.Spatial.get_selected_products(),
if o.BIMObjectProperties.ifc_definition_id
]
ifcopenshell.api.run(
"cost.unassign_cost_item_quantity",
self.file,
cost_item=self.file.by_id(self.cost_item),
products=products,
) )
bpy.ops.bim.load_cost_item_quantities()
return {"FINISHED"}
class EnableEditingCostItemQuantities(bpy.types.Operator, tool.Ifc.Operator): class EnableEditingCostItemQuantities(bpy.types.Operator, tool.Ifc.Operator):
bl_idname = "bim.enable_editing_cost_item_quantities" bl_idname = "bim.enable_editing_cost_item_quantities"
bl_label = "Enable Editing Cost Item Quantities" bl_label = "Enable Editing Cost Item Quantities"
bl_options = {"REGISTER", "UNDO"} bl_options = {"REGISTER", "UNDO"}
bl_description = "Enable editing cost item quantities"
cost_item: bpy.props.IntProperty() cost_item: bpy.props.IntProperty()
def _execute(self, context): def _execute(self, context):
props = context.scene.BIMCostProperties core.enable_editing_cost_item_quantities(tool.Cost, cost_item=tool.Ifc.get().by_id(self.cost_item))
props.active_cost_item_id = self.cost_item
props.cost_item_editing_type = "QUANTITIES"
return {"FINISHED"}
class EnableEditingCostItemValues(bpy.types.Operator, tool.Ifc.Operator): class EnableEditingCostItemValues(bpy.types.Operator, tool.Ifc.Operator):
bl_idname = "bim.enable_editing_cost_item_values" bl_idname = "bim.enable_editing_cost_item_values"
bl_label = "Enable Editing Cost Item Values" bl_label = "Enable Editing Cost Item Values"
bl_options = {"REGISTER", "UNDO"} bl_options = {"REGISTER", "UNDO"}
bl_description = "Enable editing cost item values"
cost_item: bpy.props.IntProperty() cost_item: bpy.props.IntProperty()
def _execute(self, context): def _execute(self, context):
props = context.scene.BIMCostProperties core.enable_editing_cost_item_values(tool.Cost, cost_item=tool.Ifc.get().by_id(self.cost_item))
props.active_cost_item_id = self.cost_item
props.cost_item_editing_type = "VALUES"
bpy.ops.bim.disable_editing_cost_item_value()
return {"FINISHED"}
class AddCostItemQuantity(bpy.types.Operator, tool.Ifc.Operator): class AddCostItemQuantity(bpy.types.Operator, tool.Ifc.Operator):
bl_idname = "bim.add_cost_item_quantity" bl_idname = "bim.add_cost_item_quantity"
bl_label = "Add Cost Item Quantity" bl_label = "Add Cost Item Quantity"
bl_options = {"REGISTER", "UNDO"} bl_options = {"REGISTER", "UNDO"}
bl_description = "Add cost item quantity"
cost_item: bpy.props.IntProperty() cost_item: bpy.props.IntProperty()
ifc_class: bpy.props.StringProperty() ifc_class: bpy.props.StringProperty()
def _execute(self, context): def _execute(self, context):
self.file = IfcStore.get_file() core.add_cost_item_quantity(tool.Ifc, cost_item=tool.Ifc.get().by_id(self.cost_item), ifc_class=self.ifc_class)
self.props = context.scene.BIMCostProperties
self.add_manual_quantity()
return {"FINISHED"}
def add_manual_quantity(self):
ifcopenshell.api.run(
"cost.add_cost_item_quantity",
self.file,
cost_item=self.file.by_id(self.cost_item),
ifc_class=self.ifc_class,
)
class RemoveCostItemQuantity(bpy.types.Operator, tool.Ifc.Operator): class RemoveCostItemQuantity(bpy.types.Operator, tool.Ifc.Operator):
bl_idname = "bim.remove_cost_item_quantity" bl_idname = "bim.remove_cost_item_quantity"
bl_label = "Remove Cost Item Quantity" bl_label = "Remove Cost Item Quantity"
bl_options = {"REGISTER", "UNDO"} bl_options = {"REGISTER", "UNDO"}
bl_description = "Remove cost item quantity"
cost_item: bpy.props.IntProperty() cost_item: bpy.props.IntProperty()
physical_quantity: bpy.props.IntProperty() physical_quantity: bpy.props.IntProperty()
def _execute(self, context): def _execute(self, context):
self.file = IfcStore.get_file() core.remove_cost_item_quantity(
ifcopenshell.api.run( tool.Ifc,
"cost.remove_cost_item_quantity", cost_item=tool.Ifc.get().by_id(self.cost_item),
self.file, physical_quantity=tool.Ifc.get().by_id(self.physical_quantity),
cost_item=self.file.by_id(self.cost_item),
physical_quantity=self.file.by_id(self.physical_quantity),
) )
return {"FINISHED"}
class EnableEditingCostItemQuantity(bpy.types.Operator, tool.Ifc.Operator): class EnableEditingCostItemQuantity(bpy.types.Operator):
bl_idname = "bim.enable_editing_cost_item_quantity" bl_idname = "bim.enable_editing_cost_item_quantity"
bl_label = "Enable Editing Cost Item Quantity" bl_label = "Enable Editing Cost Item Quantity"
bl_options = {"REGISTER", "UNDO"} bl_options = {"REGISTER", "UNDO"}
bl_description = "Enable editing cost item quantity"
physical_quantity: bpy.props.IntProperty() physical_quantity: bpy.props.IntProperty()
def _execute(self, context): def execute(self, context):
self.props = context.scene.BIMCostProperties core.enable_editing_cost_item_quantity(
self.props.quantity_attributes.clear() tool.Cost, physical_quantity=tool.Ifc.get().by_id(self.physical_quantity)
self.props.active_cost_item_quantity_id = self.physical_quantity
blenderbim.bim.helper.import_attributes2(
tool.Ifc.get().by_id(self.physical_quantity), self.props.quantity_attributes
) )
return {"FINISHED"} return {"FINISHED"}
class DisableEditingCostItemQuantity(bpy.types.Operator, tool.Ifc.Operator): class DisableEditingCostItemQuantity(bpy.types.Operator):
bl_idname = "bim.disable_editing_cost_item_quantity" bl_idname = "bim.disable_editing_cost_item_quantity"
bl_label = "Disable Editing Cost Item Quantity" bl_label = "Disable Editing Cost Item Quantity"
bl_options = {"REGISTER", "UNDO"} bl_options = {"REGISTER", "UNDO"}
bl_description = "Disable editing cost item quantity"
def _execute(self, context): def _execute(self, context):
props = context.scene.BIMCostProperties core.disable_editing_cost_item_quantity(tool.Cost)
props.active_cost_item_quantity_id = 0
return {"FINISHED"} return {"FINISHED"}
@@ -405,16 +340,9 @@ class EditCostItemQuantity(bpy.types.Operator, tool.Ifc.Operator):
physical_quantity: bpy.props.IntProperty() physical_quantity: bpy.props.IntProperty()
def _execute(self, context): def _execute(self, context):
props = context.scene.BIMCostProperties core.edit_cost_item_quantity(
attributes = blenderbim.bim.helper.export_attributes(props.quantity_attributes) tool.Ifc, tool.Cost, physical_quantity=tool.Ifc.get().by_id(self.physical_quantity)
self.file = IfcStore.get_file()
ifcopenshell.api.run(
"cost.edit_cost_item_quantity",
self.file,
**{"physical_quantity": self.file.by_id(self.physical_quantity), "attributes": attributes},
) )
bpy.ops.bim.disable_editing_cost_item_quantity()
return {"FINISHED"}
class AddCostValue(bpy.types.Operator, tool.Ifc.Operator): class AddCostValue(bpy.types.Operator, tool.Ifc.Operator):
@@ -426,19 +354,13 @@ class AddCostValue(bpy.types.Operator, tool.Ifc.Operator):
cost_category: bpy.props.StringProperty() cost_category: bpy.props.StringProperty()
def _execute(self, context): def _execute(self, context):
self.file = IfcStore.get_file() core.add_cost_value(
parent = self.file.by_id(self.parent) tool.Ifc,
if self.cost_type == "FIXED": tool.Cost,
category = None parent=tool.Ifc.get().by_id(self.parent),
attributes = {"AppliedValue": 0.0} cost_type=self.cost_type,
elif self.cost_type == "SUM": cost_category=self.cost_category,
category = "*" )
attributes = {"Category": category}
elif self.cost_type == "CATEGORY":
category = self.cost_category
attributes = {"Category": category}
value = ifcopenshell.api.run("cost.add_cost_value", self.file, parent=parent)
ifcopenshell.api.run("cost.edit_cost_value", self.file, cost_value=value, attributes=attributes)
return {"FINISHED"} return {"FINISHED"}
@@ -450,114 +372,41 @@ class RemoveCostItemValue(bpy.types.Operator, tool.Ifc.Operator):
cost_value: bpy.props.IntProperty() cost_value: bpy.props.IntProperty()
def _execute(self, context): def _execute(self, context):
self.file = IfcStore.get_file() core.remove_cost_value(
parent = self.file.by_id(self.parent) tool.Ifc, parent=tool.Ifc.get().by_id(self.parent), cost_value=tool.Ifc.get().by_id(self.cost_value)
ifcopenshell.api.run(
"cost.remove_cost_value",
self.file,
parent=parent,
cost_value=self.file.by_id(self.cost_value),
) )
return {"FINISHED"} return {"FINISHED"}
class EnableEditingCostItemValue(bpy.types.Operator, tool.Ifc.Operator): class EnableEditingCostItemValue(bpy.types.Operator):
bl_idname = "bim.enable_editing_cost_item_value" bl_idname = "bim.enable_editing_cost_item_value"
bl_label = "Enable Editing Cost Item Value" bl_label = "Enable Editing Cost Item Value"
bl_options = {"REGISTER", "UNDO"} bl_options = {"REGISTER", "UNDO"}
cost_value: bpy.props.IntProperty() cost_value: bpy.props.IntProperty()
def _execute(self, context): def execute(self, context):
self.props = context.scene.BIMCostProperties core.enable_editing_cost_item_value(tool.Cost, cost_value=tool.Ifc.get().by_id(self.cost_value))
self.props.cost_value_attributes.clear()
self.props.active_cost_value_id = self.cost_value
self.props.cost_value_editing_type = "ATTRIBUTES"
schedule = tool.Ifc.get().by_id(context.scene.BIMCostProperties.active_cost_schedule_id)
is_rates = schedule.PredefinedType == "SCHEDULEOFRATES"
cost_value = tool.Ifc.get().by_id(self.cost_value)
callback = lambda name, prop, data: self.import_attributes(name, prop, data, cost_value, is_rates)
blenderbim.bim.helper.import_attributes2(cost_value, self.props.cost_value_attributes, callback=callback)
return {"FINISHED"} return {"FINISHED"}
def import_attributes(self, name, prop, data, cost_value, is_rates):
if name == "AppliedValue":
# TODO: for now, only support simple IfcValues (which are effectively IfcMonetaryMeasure)
prop = self.props.cost_value_attributes.add()
prop.data_type = "float"
prop.name = "AppliedValue"
prop.is_optional = True
prop.float_value = (
0.0
if prop.is_null
else ifcopenshell.util.cost.calculate_applied_value(
tool.Ifc.get().by_id(self.props.active_cost_item_id), cost_value
)
)
return True
if name == "UnitBasis" and is_rates:
prop = self.props.cost_value_attributes.add()
prop.name = "UnitBasisValue"
prop.data_type = "float"
prop.is_null = data["UnitBasis"] is None
prop.is_optional = True
if data["UnitBasis"]:
prop.float_value = data["UnitBasis"]["ValueComponent"] or 0
else:
prop.float_value = 0
prop = self.props.cost_value_attributes.add() class DisableEditingCostItemValue(bpy.types.Operator):
prop.name = "UnitBasisUnit"
prop.data_type = "enum"
prop.is_null = prop.is_optional = False
units = {}
for unit in tool.Ifc.get().by_type("IfcNamedUnit"):
if unit.get("UnitType", None) in [
"AREAUNIT",
"LENGTHUNIT",
"TIMEUNIT",
"VOLUMEUNIT",
"MASSUNIT",
"USERDEFINED",
]:
if unit.is_a("IfcContextDependentUnit"):
units[unit.id()] = f"{unit.UnitType} / {unit.Name}"
else:
name = unit.Name
if unit.get("Prefix", None):
name = f"{unit.Prefix} {name}"
units[unit.id()] = f"{unit.UnitType} / {name}"
prop.enum_items = json.dumps(units)
if data["UnitBasis"] and data["UnitBasis"]["UnitComponent"]:
prop.enum_value = str(data["UnitBasis"]["UnitComponent"])
return True
class DisableEditingCostItemValue(bpy.types.Operator, tool.Ifc.Operator):
bl_idname = "bim.disable_editing_cost_item_value" bl_idname = "bim.disable_editing_cost_item_value"
bl_label = "Disable Editing Cost Item Value" bl_label = "Disable Editing Cost Item Value"
bl_options = {"REGISTER", "UNDO"} bl_options = {"REGISTER", "UNDO"}
def _execute(self, context): def execute(self, context):
props = context.scene.BIMCostProperties core.disable_editing_cost_item_value(tool.Cost)
props.active_cost_value_id = 0
props.cost_value_editing_type = ""
return {"FINISHED"} return {"FINISHED"}
class EnableEditingCostItemValueFormula(bpy.types.Operator, tool.Ifc.Operator): class EnableEditingCostItemValueFormula(bpy.types.Operator):
bl_idname = "bim.enable_editing_cost_item_value_formula" bl_idname = "bim.enable_editing_cost_item_value_formula"
bl_label = "Enable Editing Cost Item Value Formula" bl_label = "Enable Editing Cost Item Value Formula"
bl_options = {"REGISTER", "UNDO"} bl_options = {"REGISTER", "UNDO"}
cost_value: bpy.props.IntProperty() cost_value: bpy.props.IntProperty()
def _execute(self, context): def execute(self, context):
self.props = context.scene.BIMCostProperties core.enable_editing_cost_item_value_formula(tool.Cost, cost_value=tool.Ifc.get().by_id(self.cost_value))
self.props.cost_value_attributes.clear()
self.props.active_cost_value_id = self.cost_value
self.props.cost_value_editing_type = "FORMULA"
self.props.cost_value_formula = ifcopenshell.util.cost.serialise_cost_value(
tool.Ifc.get().by_id(self.cost_value)
)
return {"FINISHED"} return {"FINISHED"}
@@ -568,14 +417,7 @@ class EditCostItemValueFormula(bpy.types.Operator, tool.Ifc.Operator):
cost_value: bpy.props.IntProperty() cost_value: bpy.props.IntProperty()
def _execute(self, context): def _execute(self, context):
props = context.scene.BIMCostProperties core.edit_cost_item_value_formula(tool.Ifc, tool.Cost, cost_value=tool.Ifc.get().by_id(self.cost_value))
self.file = IfcStore.get_file()
ifcopenshell.api.run(
"cost.edit_cost_value_formula",
self.file,
**{"cost_value": self.file.by_id(self.cost_value), "formula": props.cost_value_formula},
)
bpy.ops.bim.disable_editing_cost_item_value()
return {"FINISHED"} return {"FINISHED"}
@@ -586,34 +428,9 @@ class EditCostItemValue(bpy.types.Operator, tool.Ifc.Operator):
cost_value: bpy.props.IntProperty() cost_value: bpy.props.IntProperty()
def _execute(self, context): def _execute(self, context):
props = context.scene.BIMCostProperties core.edit_cost_value(tool.Ifc, tool.Cost, cost_value=tool.Ifc.get().by_id(self.cost_value))
attributes = blenderbim.bim.helper.export_attributes(
props.cost_value_attributes, lambda attributes, prop: self.export_attributes(attributes, prop, context)
)
self.file = IfcStore.get_file()
ifcopenshell.api.run(
"cost.edit_cost_value",
self.file,
**{"cost_value": self.file.by_id(self.cost_value), "attributes": attributes},
)
bpy.ops.bim.disable_editing_cost_item_value()
return {"FINISHED"} return {"FINISHED"}
def export_attributes(self, attributes, prop, context):
if prop.name == "UnitBasisValue":
if prop.is_null:
attributes["UnitBasis"] = None
return True
attributes["UnitBasis"] = {
"ValueComponent": prop.float_value or 1,
"UnitComponent": IfcStore.get_file().by_id(
int(context.scene.BIMCostProperties.cost_value_attributes.get("UnitBasisUnit").enum_value)
),
}
return True
if prop.name == "UnitBasisUnit":
return True
class CopyCostItemValues(bpy.types.Operator, tool.Ifc.Operator): class CopyCostItemValues(bpy.types.Operator, tool.Ifc.Operator):
bl_idname = "bim.copy_cost_item_values" bl_idname = "bim.copy_cost_item_values"
@@ -623,11 +440,11 @@ class CopyCostItemValues(bpy.types.Operator, tool.Ifc.Operator):
destination: bpy.props.IntProperty() destination: bpy.props.IntProperty()
def _execute(self, context): def _execute(self, context):
self.file = IfcStore.get_file() core.copy_cost_item_values(
ifcopenshell.api.run( tool.Ifc,
"cost.copy_cost_item_values", tool.Cost,
self.file, source=tool.Ifc.get().by_id(self.source),
**{"source": self.file.by_id(self.source), "destination": self.file.by_id(self.destination)}, destination=tool.Ifc.get().by_id(self.destination),
) )
return {"FINISHED"} return {"FINISHED"}
@@ -639,40 +456,24 @@ class SelectCostItemProducts(bpy.types.Operator, tool.Ifc.Operator):
cost_item: bpy.props.IntProperty() cost_item: bpy.props.IntProperty()
def _execute(self, context): def _execute(self, context):
related_objects = [] core.select_cost_item_products(
[related_objects.extend(r.RelatedObjects) for r in tool.Ifc.get().by_id(self.cost_item).Controls or []] tool.Cost, tool.Spatial, cost_item=tool.Ifc.get().by_id(self.cost_item), include_nested=False
related_objects = set([r.id() for r in related_objects]) )
for obj in context.visible_objects:
obj.select_set(False)
if obj.BIMObjectProperties.ifc_definition_id in related_objects:
obj.select_set(True)
return {"FINISHED"} return {"FINISHED"}
class SelectCostScheduleProducts(bpy.types.Operator, tool.Ifc.Operator): class SelectCostScheduleProducts(bpy.types.Operator):
bl_idname = "bim.select_cost_schedule_products" bl_idname = "bim.select_cost_schedule_products"
bl_label = "Select Cost Schedule Products" bl_label = "Select Cost Schedule Products"
bl_options = {"REGISTER", "UNDO"} bl_options = {"REGISTER", "UNDO"}
cost_schedule: bpy.props.IntProperty() cost_schedule: bpy.props.IntProperty()
def _execute(self, context): def execute(self, context):
self.file = IfcStore.get_file() core.select_cost_schedule_products(
self.related_products = [] tool.Cost, tool.Spatial, cost_schedule=tool.Ifc.get().by_id(self.cost_schedule)
for cost_item in tool.Ifc.get().by_id(self.cost_schedule).Controls or []: )
self.get_related_products(cost_item)
self.related_products = set(self.related_products)
for obj in context.visible_objects:
obj.select_set(False)
if obj.BIMObjectProperties.ifc_definition_id in self.related_products:
obj.select_set(True)
return {"FINISHED"} return {"FINISHED"}
def get_related_products(self, cost_item):
[self.related_products.extend(r.RelatedObjects) for r in cost_item.Controls or []]
for rel in cost_item.IsNestedBy or []:
for sub_cost_item in rel.RelatedObjects:
self.get_related_products(sub_cost_item)
class ImportCostScheduleCsv(bpy.types.Operator, ImportHelper, tool.Ifc.Operator): class ImportCostScheduleCsv(bpy.types.Operator, ImportHelper, tool.Ifc.Operator):
bl_idname = "import_cost_schedule_csv.bim" bl_idname = "import_cost_schedule_csv.bim"
@@ -683,158 +484,75 @@ class ImportCostScheduleCsv(bpy.types.Operator, ImportHelper, tool.Ifc.Operator)
is_schedule_of_rates: bpy.props.BoolProperty(name="Is Schedule Of Rates", default=False) is_schedule_of_rates: bpy.props.BoolProperty(name="Is Schedule Of Rates", default=False)
def _execute(self, context): def _execute(self, context):
from ifc5d.csv2ifc import Csv2Ifc core.import_cost_schedule_csv(tool.Cost, self.filepath, self.is_schedule_of_rates)
self.file = IfcStore.get_file()
start = time.time()
csv2ifc = Csv2Ifc()
csv2ifc.csv = self.filepath
csv2ifc.file = self.file
csv2ifc.is_schedule_of_rates = self.is_schedule_of_rates
csv2ifc.execute()
print("Import finished in {:.2f} seconds".format(time.time() - start))
return {"FINISHED"} return {"FINISHED"}
class AddCostColumn(bpy.types.Operator, tool.Ifc.Operator): class AddCostColumn(bpy.types.Operator):
bl_idname = "bim.add_cost_column" bl_idname = "bim.add_cost_column"
bl_label = "Add Cost Column" bl_label = "Add Cost Column"
bl_options = {"REGISTER", "UNDO"} bl_options = {"REGISTER", "UNDO"}
name: bpy.props.StringProperty() name: bpy.props.StringProperty()
def _execute(self, context): def _execute(self, context):
self.props = context.scene.BIMCostProperties core.add_cost_column(tool.Cost, self.name)
new = self.props.columns.add()
new.name = self.name
return {"FINISHED"} return {"FINISHED"}
class RemoveCostColumn(bpy.types.Operator, tool.Ifc.Operator): class RemoveCostColumn(bpy.types.Operator):
bl_idname = "bim.remove_cost_column" bl_idname = "bim.remove_cost_column"
bl_label = "Remove Cost Column" bl_label = "Remove Cost Column"
bl_options = {"REGISTER", "UNDO"} bl_options = {"REGISTER", "UNDO"}
name: bpy.props.StringProperty() name: bpy.props.StringProperty()
def _execute(self, context): def _execute(self, context):
self.props = context.scene.BIMCostProperties core.remove_cost_column(tool.Cost, self.name)
self.props.columns.remove(self.props.columns.find(self.name))
return {"FINISHED"} return {"FINISHED"}
class LoadCostItemQuantities(bpy.types.Operator, tool.Ifc.Operator): class LoadCostItemQuantities(bpy.types.Operator):
bl_idname = "bim.load_cost_item_quantities" bl_idname = "bim.load_cost_item_quantities"
bl_label = "Load Cost Item Quantities" bl_label = "Load Cost Item Quantities"
bl_options = {"REGISTER", "UNDO"} bl_options = {"REGISTER", "UNDO"}
def _execute(self, context): def execute(self, context):
self.props = context.scene.BIMCostProperties core.load_cost_item_quantities(tool.Cost)
self.file = IfcStore.get_file()
self.props.cost_item_products.clear()
self.props.cost_item_processes.clear()
self.props.cost_item_resources.clear()
if self.props.active_cost_item_index < len(self.props.cost_items):
ifc_definition_id = self.props.cost_items[self.props.active_cost_item_index].ifc_definition_id
cost_item = tool.Ifc.get().by_id(ifc_definition_id)
# for control_id, quantity_ids in cost_item.Controls.items() or {}:
for rel in cost_item.Controls or []:
# control_id, quantity_ids
for related_object in rel.RelatedObjects:
if related_object.is_a("IfcProduct"):
new = self.props.cost_item_products.add()
elif related_object.is_a("IfcProcess"):
new = self.props.cost_item_processes.add()
elif related_object.is_a("IfcResource"):
new = self.props.cost_item_resources.add()
new.ifc_definition_id = related_object.id()
new.name = related_object.Name or "Unnamed"
total_quantity = 0
qtos = ifcopenshell.util.element.get_psets(related_object, qtos_only=True)
for qset_name, quantities in qtos.items():
qto = tool.Ifc.get().by_id(quantities["id"])
for quantity in qto.Quantities:
if quantity in cost_item.CostQuantities:
total_quantity += quantity[3]
new.total_quantity = total_quantity
return {"FINISHED"} return {"FINISHED"}
class LoadCostItemTypes(bpy.types.Operator, tool.Ifc.Operator): class LoadCostItemTypes(bpy.types.Operator):
bl_idname = "bim.load_cost_item_types" bl_idname = "bim.load_cost_item_types"
bl_label = "Load Cost Item Types" bl_label = "Load Cost Item Types"
bl_options = {"REGISTER", "UNDO"} bl_options = {"REGISTER", "UNDO"}
def _execute(self, context): def execute(self, context):
self.props = context.scene.BIMCostProperties core.load_cost_item_types(tool.Cost)
self.file = IfcStore.get_file()
self.props.cost_item_type_products.clear()
# TODO implement process and resource types
# self.props.cost_item_processes.clear()
# self.props.cost_item_resources.clear()
ifc_definition_id = self.props.cost_items[self.props.active_cost_item_index].ifc_definition_id
cost_item = tool.Ifc.get().by_id(ifc_definition_id)
for rel in cost_item.Controls or []:
for related_object in rel.RelatedObjects:
if related_object.is_a("IfcTypeProduct"):
new = self.props.cost_item_type_products.add()
# TODO implement process and resource types
# elif related_object.is_a("IfcProcess"):
# new = self.props.cost_item_processes.add()
# elif related_object.is_a("IfcResource"):
# new = self.props.cost_item_resources.add()
new.ifc_definition_id = related_object.id()
new.name = related_object.Name or "Unnamed"
return {"FINISHED"} return {"FINISHED"}
class AssignCostValue(bpy.types.Operator, tool.Ifc.Operator): class AssignCostValue(bpy.types.Operator, tool.Ifc.Operator):
bl_idname = "bim.assign_cost_value" bl_idname = "bim.assign_cost_value"
bl_label = "Assign Cost Value" bl_label = "Assign Cost Rate Value"
bl_options = {"REGISTER", "UNDO"} bl_options = {"REGISTER", "UNDO"}
cost_item: bpy.props.IntProperty() cost_item: bpy.props.IntProperty()
cost_rate: bpy.props.IntProperty() cost_rate: bpy.props.IntProperty()
def _execute(self, context): def _execute(self, context):
self.file = IfcStore.get_file() core.assign_cost_value(
ifcopenshell.api.run( tool.Ifc, cost_item=tool.Ifc.get().by_id(self.cost_item), cost_rate=tool.Ifc.get().by_id(self.cost_rate)
"cost.assign_cost_value",
self.file,
cost_item=self.file.by_id(self.cost_item),
cost_rate=self.file.by_id(self.cost_rate),
) )
return {"FINISHED"}
class LoadScheduleOfRates(bpy.types.Operator, tool.Ifc.Operator): class LoadScheduleOfRates(bpy.types.Operator):
bl_idname = "bim.load_schedule_of_rates" bl_idname = "bim.load_schedule_of_rates_tree"
bl_label = "Load Schedule of Rates" bl_label = "Load Schedule of Rates"
bl_options = {"REGISTER", "UNDO"} bl_options = {"REGISTER", "UNDO"}
cost_schedule: bpy.props.IntProperty() cost_schedule: bpy.props.IntProperty()
def _execute(self, context): def execute(self, context):
self.props = context.scene.BIMCostProperties core.load_schedule_of_rates_tree(tool.Cost, schedule_of_rates=tool.Ifc.get().by_id(self.cost_schedule))
self.props.is_cost_update_enabled = False
self.props.cost_item_rates.clear()
self.contracted_cost_item_rates = json.loads(self.props.contracted_cost_item_rates)
for rel in tool.Ifc.get().by_id(self.cost_schedule).Controls or []:
for cost_item in rel.RelatedObjects:
self.create_new_cost_item_li(cost_item, 0)
self.props.is_cost_update_enabled = True
return {"FINISHED"} return {"FINISHED"}
def create_new_cost_item_li(self, cost_item, level_index):
new = self.props.cost_item_rates.add()
new.ifc_definition_id = cost_item.id()
new.name = cost_item.Name or "Unnamed"
new.identification = cost_item.Identification or "XXX"
new.is_expanded = cost_item.id() not in self.contracted_cost_item_rates
new.level_index = level_index
if cost_item.IsNestedBy:
new.has_children = True
if new.is_expanded:
for rel in cost_item.IsNestedBy:
for sub_cost_item in rel.RelatedObjects:
self.create_new_cost_item_li(sub_cost_item, level_index + 1)
class ExpandCostItemRate(bpy.types.Operator, tool.Ifc.Operator): class ExpandCostItemRate(bpy.types.Operator, tool.Ifc.Operator):
bl_idname = "bim.expand_cost_item_rate" bl_idname = "bim.expand_cost_item_rate"
@@ -843,12 +561,7 @@ class ExpandCostItemRate(bpy.types.Operator, tool.Ifc.Operator):
cost_item: bpy.props.IntProperty() cost_item: bpy.props.IntProperty()
def _execute(self, context): def _execute(self, context):
props = context.scene.BIMCostProperties core.expand_cost_item_rate(tool.Cost, self.cost_item)
self.file = IfcStore.get_file()
contracted_cost_item_rates = json.loads(props.contracted_cost_item_rates)
contracted_cost_item_rates.remove(self.cost_item)
props.contracted_cost_item_rates = json.dumps(contracted_cost_item_rates)
bpy.ops.bim.load_schedule_of_rates(cost_schedule=int(props.schedule_of_rates))
return {"FINISHED"} return {"FINISHED"}
@@ -859,12 +572,7 @@ class ContractCostItemRate(bpy.types.Operator, tool.Ifc.Operator):
cost_item: bpy.props.IntProperty() cost_item: bpy.props.IntProperty()
def _execute(self, context): def _execute(self, context):
props = context.scene.BIMCostProperties core.contract_cost_item_rate(tool.Cost, self.cost_item)
self.file = IfcStore.get_file()
contracted_cost_item_rates = json.loads(props.contracted_cost_item_rates)
contracted_cost_item_rates.append(self.cost_item)
props.contracted_cost_item_rates = json.dumps(contracted_cost_item_rates)
bpy.ops.bim.load_schedule_of_rates(cost_schedule=int(props.schedule_of_rates))
return {"FINISHED"} return {"FINISHED"}
@@ -875,8 +583,6 @@ class CalculateCostItemResourceValue(bpy.types.Operator, tool.Ifc.Operator):
cost_item: bpy.props.IntProperty() cost_item: bpy.props.IntProperty()
def _execute(self, context): def _execute(self, context):
self.file = IfcStore.get_file() core.calculate_cost_item_resource_value(tool.Ifc, cost_item=tool.Ifc.get().by_id(self.cost_item))
ifcopenshell.api.run(
"cost.calculate_cost_item_resource_value", self.file, cost_item=self.file.by_id(self.cost_item)
)
return {"FINISHED"} return {"FINISHED"}
@@ -43,7 +43,7 @@ def get_schedule_of_rates(self, context):
def update_schedule_of_rates(self, context): def update_schedule_of_rates(self, context):
bpy.ops.bim.load_schedule_of_rates(cost_schedule=int(self.schedule_of_rates)) 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, context):
@@ -73,9 +73,9 @@ def get_resource_quantity_names(self, context):
def update_active_cost_item_index(self, context): def update_active_cost_item_index(self, context):
schedule = tool.Ifc.get().by_id(self.active_cost_schedule_id) schedule = tool.Ifc.get().by_id(self.active_cost_schedule_id)
if schedule.PredefinedType == "SCHEDULEOFRATES": if schedule.PredefinedType == "SCHEDULEOFRATES":
bpy.ops.bim.load_cost_item_types() tool.Cost.load_cost_item_types()
else: else:
bpy.ops.bim.load_cost_item_quantities() tool.Cost.load_cost_item_quantities(cost_item=tool.Cost.get_highlighted_cost_item())
CostClassificationsData.load() CostClassificationsData.load()
@@ -470,13 +470,14 @@ class BIM_PT_cost_item_rates(Panel):
def draw(self, context): def draw(self, context):
self.props = context.scene.BIMCostProperties self.props = context.scene.BIMCostProperties
cost_item = self.props.cost_items[self.props.active_cost_item_index]
row = self.layout.row(align=True) row = self.layout.row(align=True)
row.prop(self.props, "schedule_of_rates", text="") row.prop(self.props, "schedule_of_rates", text="")
if self.props.active_cost_item_rate_index < len(self.props.cost_item_rates): if self.props.active_cost_item_rate_index < len(self.props.cost_item_rates):
cost_item = self.props.cost_items[self.props.active_cost_item_index]
cost_item_rate = self.props.cost_item_rates[self.props.active_cost_item_rate_index]
op = row.operator("bim.assign_cost_value", text="", icon="COPYDOWN") op = row.operator("bim.assign_cost_value", text="", icon="COPYDOWN")
op.cost_item = self.props.cost_items[self.props.active_cost_item_index].ifc_definition_id op.cost_item = cost_item.ifc_definition_id
op.cost_rate = self.props.cost_item_rates[self.props.active_cost_item_rate_index].ifc_definition_id op.cost_rate = cost_item_rate.ifc_definition_id
self.layout.template_list( self.layout.template_list(
"BIM_UL_cost_item_rates", "BIM_UL_cost_item_rates",
"", "",
+158 -11
View File
@@ -1,65 +1,212 @@
def add_cost_schedule(ifc): def add_cost_schedule(ifc):
ifc.run("cost.add_cost_schedule") ifc.run("cost.add_cost_schedule")
def edit_cost_schedule(ifc, cost, cost_schedule): def edit_cost_schedule(ifc, cost, cost_schedule):
attributes = cost.get_cost_schedule_attributes() attributes = cost.get_cost_schedule_attributes()
ifc.run("cost.edit_cost_schedule", cost_schedule=cost_schedule, attributes=attributes) ifc.run("cost.edit_cost_schedule", cost_schedule=cost_schedule, attributes=attributes)
cost.disable_editing_cost_schedule() cost.disable_editing_cost_schedule()
def disable_editing_cost_schedule(cost): def disable_editing_cost_schedule(cost):
cost.disable_editing_cost_schedule() cost.disable_editing_cost_schedule()
def remove_cost_schedule(ifc, cost_schedule): def remove_cost_schedule(ifc, cost_schedule):
ifc.run("cost.remove_cost_schedule", cost_schedule=cost_schedule) ifc.run("cost.remove_cost_schedule", cost_schedule=cost_schedule)
def enable_editing_cost_schedule_attributes(cost, cost_schedule): def enable_editing_cost_schedule_attributes(cost, cost_schedule):
cost.load_cost_schedule_attributes(cost_schedule)
cost.enable_editing_cost_schedule_attributes(cost_schedule) cost.enable_editing_cost_schedule_attributes(cost_schedule)
cost.load_cost_items() cost.play_sound()
cost.play_chaching_sound()
def enable_editing_cost_items(cost, cost_schedule): def enable_editing_cost_items(cost, cost_schedule):
cost.enable_editing_cost_items(cost_schedule) cost.enable_editing_cost_items(cost_schedule)
cost.load_cost_items() cost.load_cost_schedule_tree()
cost.play_sound()
def add_summary_cost_item(ifc, cost, cost_schedule): def add_summary_cost_item(ifc, cost, cost_schedule):
ifc.run("cost.add_cost_item", cost_schedule=cost_schedule) ifc.run("cost.add_cost_item", cost_schedule=cost_schedule)
cost.load_cost_items() cost.load_cost_schedule_tree()
# cost.play_sound()
def add_cost_item(ifc, cost, cost_item): def add_cost_item(ifc, cost, cost_item):
ifc.run("cost.add_cost_item", cost_item=cost_item) ifc.run("cost.add_cost_item", cost_item=cost_item)
cost.load_cost_items() cost.load_cost_schedule_tree()
# cost.enable_editing_cost_schedule_attributes(cost_schedule) # cost.enable_editing_cost_schedule_attributes(cost_schedule)
def expand_cost_item(cost, cost_item): def expand_cost_item(cost, cost_item):
cost.expand_cost_item(cost_item) cost.expand_cost_item(cost_item)
cost.load_cost_items() cost.load_cost_schedule_tree()
def expand_cost_items(cost): def expand_cost_items(cost):
cost.expand_cost_items() cost.expand_cost_items()
cost.load_cost_items() cost.load_cost_schedule_tree()
def contract_cost_item(cost, cost_item): def contract_cost_item(cost, cost_item):
cost.contract_cost_item(cost_item) cost.contract_cost_item(cost_item)
cost.load_cost_items() cost.load_cost_schedule_tree()
def contract_cost_items(cost): def contract_cost_items(cost):
cost.contract_cost_items() cost.contract_cost_items()
cost.load_cost_items() cost.load_cost_schedule_tree()
def remove_cost_item(ifc, cost, cost_item): def remove_cost_item(ifc, cost, cost_item):
ifc.run("cost.remove_cost_item", cost_item=cost_item) ifc.run("cost.remove_cost_item", cost_item=cost_item)
cost.clean_up_cost_item_tree(cost_item) cost.clean_up_cost_item_tree(cost_item)
cost.load_cost_items() cost.load_cost_schedule_tree()
def enable_editing_cost_item_attributes(cost, cost_item): def enable_editing_cost_item_attributes(cost, cost_item):
cost.enable_editing_cost_item_attributes(cost_item) cost.enable_editing_cost_item_attributes(cost_item)
cost.load_cost_item_attributes(cost_item) cost.load_cost_item_attributes(cost_item)
def disable_editing_cost_item(cost): def disable_editing_cost_item(cost):
cost.disable_editing_cost_item() cost.disable_editing_cost_item()
def edit_cost_item(ifc, cost): def edit_cost_item(ifc, cost):
attributes = cost.get_cost_item_attributes() attributes = cost.get_cost_item_attributes()
ifc.run("cost.edit_cost_item", cost_item=cost.get_active_cost_item(), attributes=attributes) ifc.run("cost.edit_cost_item", cost_item=cost.get_active_cost_item(), attributes=attributes)
cost.disable_editing_cost_item() cost.disable_editing_cost_item()
cost.load_cost_items() cost.load_cost_schedule_tree()
def assign_cost_item_type(ifc, cost, spatial, cost_item, prop_name):
product_types = spatial.get_selected_product_types()
[
ifc.run("control.assign_control", relating_control=cost_item, related_object=product_type)
for product_type in product_types
]
cost.load_cost_item_types(cost_item)
def unassign_cost_item_type(ifc, cost, spatial, cost_item, product_types):
if not product_types:
product_types = spatial.get_selected_product_types()
[
ifc.run("control.unassign_control", relating_control=cost_item, related_object=product_type)
for product_type in product_types
]
cost.load_cost_item_types(cost_item)
def load_cost_item_types(cost):
cost_item = cost.get_active_cost_item()
cost.load_cost_item_types(cost_item)
def assign_cost_item_quantity(ifc, cost, cost_item, related_object_type, prop_name):
products = cost.get_products(related_object_type)
if products:
ifc.run("cost.assign_cost_item_quantity", cost_item=cost_item, products=products, prop_name=prop_name)
cost.load_cost_item_quantities(cost_item)
def load_cost_item_quantities(cost):
cost_item = cost.get_highlighted_cost_item()
cost.load_cost_item_quantities(cost_item)
def assign_cost_value(ifc, cost_item, cost_rate):
ifc.run("cost.assign_cost_value", cost_item=cost_item, cost_rate=cost_rate)
def load_schedule_of_rates(cost, schedule_of_rates):
cost.load_schedule_of_rates(schedule_of_rates)
def unassign_cost_item_quantity(ifc, cost, cost_item, products):
ifc.run("cost.unassign_cost_item_quantity", cost_item=cost_item, products=products)
cost.load_cost_item_quantities(cost_item)
def enable_editing_cost_item_quantities(cost, cost_item):
cost.enable_editing_cost_item_quantities(cost_item)
def enable_editing_cost_item_values(cost, cost_item):
cost.enable_editing_cost_item_values(cost_item)
def add_cost_item_quantity(ifc, cost_item, ifc_class):
ifc.run("cost.add_cost_item_quantity", cost_item=cost_item, ifc_class=ifc_class)
def remove_cost_item_quantity(ifc, cost_item, physical_quantity):
ifc.run("cost.remove_cost_item_quantity", cost_item=cost_item, physical_quantity=physical_quantity)
def enable_editing_cost_item_quantity(cost, physical_quantity):
cost.load_cost_item_quantity_attributes(physical_quantity)
cost.enable_editing_cost_item_quantity(physical_quantity)
def disable_editing_cost_item_quantity(cost):
cost.disable_editing_cost_item_quantity()
def edit_cost_item_quantity(ifc, cost, physical_quantity):
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()
# cost.load_cost_item_quantities(cost.get_active_cost_item())
def add_cost_value(ifc, cost, parent, cost_type, cost_category):
value = ifc.run("cost.add_cost_value", parent=parent)
ifc.run(
"cost.edit_cost_value",
cost_value=value,
attributes=cost.get_attributes_for_cost_value(cost_type, cost_category))
def remove_cost_value(ifc, parent, cost_value):
ifc.run("cost.remove_cost_value", parent=parent, cost_value=cost_value)
def enable_editing_cost_item_value(cost, cost_value):
cost.load_cost_item_value_attributes(cost_value)
cost.enable_editing_cost_item_value(cost_value)
def disable_editing_cost_item_value(cost):
cost.disable_editing_cost_item_value()
def enable_editing_cost_item_value_formula(cost, cost_value):
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, cost, cost_value):
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, cost, cost_value):
attributes = cost.get_cost_value_attributes()
ifc.run("cost.edit_cost_value", cost_value=cost_value, attributes=attributes)
cost.disable_editing_cost_item_value()
#cost.load_cost_item_values(cost.get_active_cost_item())
def copy_cost_item_values(ifc, cost, source, destination):
ifc.run("cost.copy_cost_item_values", source=source, destination=destination)
def select_cost_item_products(cost, spatial, cost_item, include_nested):
products = cost.get_cost_item_products(cost_item, include_nested)
spatial.select_products(products)
def select_cost_schedule_products(cost, spatial, cost_schedule):
products = cost.get_cost_schedule_products(cost_schedule)
spatial.select_products(products)
def import_cost_schedule_csv(cost, file_path, is_schedule_of_rates):
cost.import_cost_schedule_csv(file_path, is_schedule_of_rates)
def add_cost_column(cost, name):
cost.add_cost_column(name)
def remove_cost_column(cost, name):
cost.remove_cost_column(name)
def expand_cost_item_rate(cost, cost_item):
cost.expand_cost_item_rate(cost_item)
def contract_cost_item_rate(cost, cost_item):
cost.contract_cost_item_rate(cost_item)
def calculate_cost_item_resource_value(ifc, cost_item):
ifc.run("cost.calculate_cost_item_resource_value", cost_item=cost_item)
+36 -2
View File
@@ -127,23 +127,57 @@ class Context:
@interface @interface
class Cost: class Cost:
def add_cost_column(cls, name): pass
def clean_up_cost_item_tree(cls, cost_item): pass def clean_up_cost_item_tree(cls, cost_item): pass
def contract_cost_item_rate(cls, cost_item): pass
def contract_cost_item(cls, cost_item): pass def contract_cost_item(cls, cost_item): pass
def contract_cost_items(cls): pass def contract_cost_items(cls): pass
def create_new_cost_item_li(cls, props, cost_item, level_index): pass def create_new_cost_item_li(props_collection, cost_item, level_index, type): pass
def disable_editing_cost_item_quantity(cls): pass
def disable_editing_cost_item_value(cls): pass
def disable_editing_cost_item(cls): pass def disable_editing_cost_item(cls): pass
def disable_editing_cost_schedule(cls): pass def disable_editing_cost_schedule(cls): pass
def enable_editing_cost_item_attributes(cls, cost_item): pass def enable_editing_cost_item_attributes(cls, cost_item): pass
def enable_editing_cost_item_quantities(cls, cost_item): pass
def enable_editing_cost_item_quantity(cls, physical_quantity): pass
def enable_editing_cost_item_value_formula(cls, cost_value): pass
def enable_editing_cost_item_value(cls, cost_value): pass
def enable_editing_cost_item_values(cls, cost_item): pass
def enable_editing_cost_items(cls, cost_schedule): pass def enable_editing_cost_items(cls, cost_schedule): pass
def enable_editing_cost_schedule_attributes(cls, cost_schedule): pass def enable_editing_cost_schedule_attributes(cls, cost_schedule): pass
def expand_cost_item_rate(cls, cost_item): pass
def expand_cost_item(cls, cost_item): pass def expand_cost_item(cls, cost_item): pass
def expand_cost_items(cls): pass def expand_cost_items(cls): pass
def get_active_cost_item(cls): pass def get_active_cost_item(cls): pass
def get_all_nested_cost_items(cls, cost_item): pass
def get_cost_item_attributes(cls, cost_item): pass def get_cost_item_attributes(cls, cost_item): pass
def get_cost_item_products(cls): pass
def get_cost_item_quantity_attributes(cls): pass
def get_cost_item_value_formula(cls): pass
def get_cost_schedule_attributes(cls): pass def get_cost_schedule_attributes(cls): pass
def load_cost_items(cls): pass def get_cost_schedule_products(cls, cost_schedule): pass
def get_attributes_for_cost_value(cls, cost_type, cost_category): pass
def get_cost_value_attributes(cls): pass
def get_cost_value_unit_component(cls): pass
def get_direct_cost_item_products(cls): pass
def get_highlighted_cost_item(cls): pass
def get_nested_cost_items(cls, cost_item): pass
def get_products(cls, related_object_type): pass
def get_root_cost_items(cls, cost_schedule): pass
def get_schedule_cost_items(cls, cost_schedule): pass
def import_cost_schedule_csv(cls, file_path, is_schedule_of_rates): pass
def is_active_schedule_of_rates(cls): pass
def load_cost_item_attributes(cls): pass def load_cost_item_attributes(cls): pass
def load_cost_item_quantities(cls, cost_item): pass
def load_cost_item_quantity_attributes(cls, physical_quantity): pass
def load_cost_item_types(cls, cost_item): pass
def load_cost_item_value_attributes(cls, cost_value): pass
def load_cost_item_value_formula_attributes(cls, cost_value): pass
def load_cost_schedule_tree(cls): pass
def load_schedule_of_rates_tree(cls, schedule_of_rates): pass
def play_chaching_sound(cls): pass def play_chaching_sound(cls): pass
def print_all_cost_items(cls, cost_schedule): pass
def remove_cost_column(cls, name): pass
@interface @interface
class Debug: class Debug:
+415 -45
View File
@@ -2,6 +2,7 @@ import os
import bpy import bpy
import blenderbim.tool as tool import blenderbim.tool as tool
import ifcopenshell.util.date import ifcopenshell.util.date
import ifcopenshell.util.cost
import blenderbim.bim.helper import blenderbim.bim.helper
import json import json
@@ -15,22 +16,34 @@ class Cost(blenderbim.core.tool.Cost):
@classmethod @classmethod
def disable_editing_cost_schedule(cls): def disable_editing_cost_schedule(cls):
bpy.context.scene.BIMCostProperties.active_cost_schedule_id = 0 bpy.context.scene.BIMCostProperties.active_cost_schedule_id = 0
cls.disable_editing_cost_item()
@classmethod @classmethod
def enable_editing_cost_schedule_attributes(cls, cost_schedule): def enable_editing_cost_schedule_attributes(cls, cost_schedule):
def special_import(name, prop, data):
if name in ["SubmittedOn", "UpdateDate"]:
prop.string_value = "" if prop.is_null else ifcopenshell.util.date.ifc2datetime(data[name]).isoformat()
return True
bpy.context.scene.BIMCostProperties.active_cost_schedule_id = cost_schedule.id() bpy.context.scene.BIMCostProperties.active_cost_schedule_id = cost_schedule.id()
bpy.context.scene.BIMCostProperties.is_editing = "COST_SCHEDULE_ATTRIBUTES" bpy.context.scene.BIMCostProperties.is_editing = "COST_SCHEDULE_ATTRIBUTES"
@classmethod @classmethod
def load_cost_schedule_attributes(cls, cost_schedule): def load_cost_schedule_attributes(cls, cost_schedule):
def special_import(name, prop, data):
if name in ["SubmittedOn", "UpdateDate"]:
prop.string_value = "" if prop.is_null else ifcopenshell.util.date.ifc2datetime(data[name]).isoformat()
return True
props = bpy.context.scene.BIMCostProperties props = bpy.context.scene.BIMCostProperties
props.cost_schedule_attributes.clear() props.cost_schedule_attributes.clear()
blenderbim.bim.helper.import_attributes(cost_schedule, props.cost_schedule_attributes) blenderbim.bim.helper.import_attributes2(cost_schedule, props.cost_schedule_attributes, callback=special_import)
@classmethod
def enable_editing_cost_items(cls, cost_schedule):
props = bpy.context.scene.BIMCostProperties
props.active_cost_schedule_id = cost_schedule.id()
props.is_editing = "COST_ITEMS"
@classmethod
def play_sound(cls):
if bpy.context.preferences.addons["blenderbim"].preferences.should_play_chaching_sound:
cls.play_chaching_sound() # lol
@classmethod @classmethod
def play_chaching_sound(cls): def play_chaching_sound(cls):
@@ -50,55 +63,33 @@ class Cost(blenderbim.core.tool.Cost):
pass # ah well pass # ah well
@classmethod @classmethod
def enable_editing_cost_items(cls, cost_schedule): def load_cost_schedule_tree(cls):
props = bpy.context.scene.BIMCostProperties props = bpy.context.scene.BIMCostProperties
props.is_cost_update_enabled = False props.is_cost_update_enabled = False
props.active_cost_schedule_id = cost_schedule.id()
props.is_editing = "COST_ITEMS"
props.is_cost_update_enabled = True
@classmethod
def play_chaching_sound(cls):
if bpy.context.preferences.addons["blenderbim"].preferences.should_play_chaching_sound:
cls.play_chaching_sound() # lol
@classmethod
def load_cost_items(cls):
props = bpy.context.scene.BIMCostProperties
cost_schedule = tool.Ifc.get().by_id(props.active_cost_schedule_id) cost_schedule = tool.Ifc.get().by_id(props.active_cost_schedule_id)
props.cost_items.clear() props.cost_items.clear()
if not hasattr(cls, "contracted_cost_items"): if not hasattr(cls, "contracted_cost_items"):
cls.contracted_cost_items = json.loads(props.contracted_cost_items) cls.contracted_cost_items = json.loads(props.contracted_cost_items)
for rel in cost_schedule.Controls or []: [
for cost_item in rel.RelatedObjects: cls.create_new_cost_item_li(props.cost_items, cost_item, 0, type="cost")
cls.create_new_cost_item_li(props, cost_item, 0) for rel in cost_schedule.Controls or []
for cost_item in rel.RelatedObjects or []
@classmethod ]
def create_new_cost_item_li(cls, props, cost_item, level_index): props.is_cost_update_enabled = True
new = props.cost_items.add()
new.ifc_definition_id = cost_item.id()
new.name = cost_item.Name or "Unnamed"
new.identification = cost_item.Identification or "XXX"
new.is_expanded = cost_item.id() not in cls.contracted_cost_items
new.level_index = level_index
if cost_item.IsNestedBy:
new.has_children = True
if new.is_expanded:
for rel in cost_item.IsNestedBy:
for sub_cost_item in rel.RelatedObjects:
cls.create_new_cost_item_li(props, sub_cost_item, level_index + 1)
@classmethod @classmethod
def expand_cost_item(cls, cost_item): def expand_cost_item(cls, cost_item):
props = bpy.context.scene.BIMCostProperties props = bpy.context.scene.BIMCostProperties
cls.contracted_cost_items = json.loads(props.contracted_cost_items) if not hasattr(cls, "contracted_cost_items"):
cls.contracted_cost_items = json.loads(props.contracted_cost_items)
cls.contracted_cost_items.remove(cost_item.id()) cls.contracted_cost_items.remove(cost_item.id())
props.contracted_cost_items = json.dumps(cls.contracted_cost_items) props.contracted_cost_items = json.dumps(cls.contracted_cost_items)
@classmethod @classmethod
def expand_cost_items(cls): def expand_cost_items(cls):
props = bpy.context.scene.BIMCostProperties props = bpy.context.scene.BIMCostProperties
cls.contracted_cost_items = json.loads(props.contracted_cost_items) if not hasattr(cls, "contracted_cost_items"):
cls.contracted_cost_items = json.loads(props.contracted_cost_items)
for cost_item in props.cost_items: for cost_item in props.cost_items:
if cost_item.ifc_definition_id in cls.contracted_cost_items: if cost_item.ifc_definition_id in cls.contracted_cost_items:
cls.contracted_cost_items.remove(cost_item.ifc_definition_id) cls.contracted_cost_items.remove(cost_item.ifc_definition_id)
@@ -107,14 +98,16 @@ class Cost(blenderbim.core.tool.Cost):
@classmethod @classmethod
def contract_cost_item(cls, cost_item): def contract_cost_item(cls, cost_item):
props = bpy.context.scene.BIMCostProperties props = bpy.context.scene.BIMCostProperties
cls.contracted_cost_items = json.loads(props.contracted_cost_items) if not hasattr(cls, "contracted_cost_items"):
cls.contracted_cost_items = json.loads(props.contracted_cost_items)
cls.contracted_cost_items.append(cost_item.id()) cls.contracted_cost_items.append(cost_item.id())
props.contracted_cost_items = json.dumps(cls.contracted_cost_items) props.contracted_cost_items = json.dumps(cls.contracted_cost_items)
@classmethod @classmethod
def contract_cost_items(cls): def contract_cost_items(cls):
props = bpy.context.scene.BIMCostProperties props = bpy.context.scene.BIMCostProperties
cls.contracted_cost_items = json.loads(props.contracted_cost_items) if not hasattr(cls, "contracted_cost_items"):
cls.contracted_cost_items = json.loads(props.contracted_cost_items)
for cost_item in props.cost_items: for cost_item in props.cost_items:
if cost_item.ifc_definition_id not in cls.contracted_cost_items: if cost_item.ifc_definition_id not in cls.contracted_cost_items:
cls.contracted_cost_items.append(cost_item.ifc_definition_id) cls.contracted_cost_items.append(cost_item.ifc_definition_id)
@@ -123,13 +116,14 @@ class Cost(blenderbim.core.tool.Cost):
@classmethod @classmethod
def clean_up_cost_item_tree(cls, cost_item): def clean_up_cost_item_tree(cls, cost_item):
props = bpy.context.scene.BIMCostProperties props = bpy.context.scene.BIMCostProperties
cls.contracted_cost_items = json.loads(props.contracted_cost_items) if not hasattr(cls, "contracted_cost_items"):
cls.contracted_cost_items = json.loads(props.contracted_cost_items)
if props.active_cost_item_id == cost_item.id():
props.active_cost_item_id = 0
if props.active_cost_item_index in cls.contracted_cost_items: if props.active_cost_item_index in cls.contracted_cost_items:
cls.contracted_cost_items.remove(props.active_cost_item_index) cls.contracted_cost_items.remove(props.active_cost_item_index)
props.contracted_cost_items = json.dumps(cls.contracted_cost_items) props.contracted_cost_items = json.dumps(cls.contracted_cost_items)
bpy.ops.bim.enable_editing_cost_items(cost_schedule=props.active_cost_schedule_id) bpy.ops.bim.enable_editing_cost_items(cost_schedule=props.active_cost_schedule_id)
if props.active_cost_item_id == cost_item.id():
props.active_cost_item_id = 0
@classmethod @classmethod
def enable_editing_cost_item_attributes(cls, cost_item): def enable_editing_cost_item_attributes(cls, cost_item):
@@ -153,6 +147,382 @@ class Cost(blenderbim.core.tool.Cost):
@classmethod @classmethod
def get_active_cost_item(cls): def get_active_cost_item(cls):
if bpy.context.scene.BIMCostProperties.active_cost_item_id == 0: props = bpy.context.scene.BIMCostProperties
if props.active_cost_item_id == 0:
return None return None
return tool.Ifc.get().by_id(bpy.context.scene.BIMCostProperties.active_cost_item_id) return tool.Ifc.get().by_id(bpy.context.scene.BIMCostProperties.active_cost_item_id)
@classmethod
def get_highlighted_cost_item(cls):
props = bpy.context.scene.BIMCostProperties
if props.active_cost_item_index < len(props.cost_items):
return tool.Ifc.get().by_id(props.cost_items[props.active_cost_item_index].ifc_definition_id)
return None
@classmethod
def load_cost_item_types(cls, cost_item=None):
if not cost_item:
return
props = bpy.context.scene.BIMCostProperties
props.cost_item_type_products.clear()
# TODO implement process and resource types
# props.cost_item_processes.clear()
# props.cost_item_resources.clear()
for rel in cost_item.Controls or []:
for related_object in rel.RelatedObjects:
if related_object.is_a("IfcTypeProduct"):
new = props.cost_item_type_products.add()
# TODO implement process and resource types
# elif related_object.is_a("IfcProcess"):
# new = props.cost_item_processes.add()
# elif related_object.is_a("IfcResource"):
# new = props.cost_item_resources.add()
new.ifc_definition_id = related_object.id()
new.name = related_object.Name or "Unnamed"
@classmethod
def load_cost_item_quantities(cls, cost_item=None):
if not cost_item:
cost_item = cls.get_active_cost_item()
if not cost_item:
return
props = bpy.context.scene.BIMCostProperties
props.cost_item_products.clear()
props.cost_item_processes.clear()
props.cost_item_resources.clear()
# for control_id, quantity_ids in cost_item.Controls.items() or {}:
for rel in cost_item.Controls or []:
# control_id, quantity_ids
for related_object in rel.RelatedObjects:
if related_object.is_a("IfcProduct"):
new = props.cost_item_products.add()
elif related_object.is_a("IfcProcess"):
new = props.cost_item_processes.add()
elif related_object.is_a("IfcResource"):
new = props.cost_item_resources.add()
new.ifc_definition_id = related_object.id()
new.name = related_object.Name or "Unnamed"
total_quantity = 0
qtos = ifcopenshell.util.element.get_psets(related_object, qtos_only=True)
for qset_name, quantities in qtos.items():
qto = tool.Ifc.get().by_id(quantities["id"])
for quantity in qto.Quantities:
if quantity in cost_item.CostQuantities:
total_quantity += quantity[3]
new.total_quantity = total_quantity
@classmethod
def get_products(cls, related_object_type=None):
props = bpy.context.scene.BIMCostProperties
if related_object_type == "PRODUCT":
products = tool.Spatial.get_selected_products()
elif related_object_type == "PROCESS":
products = [tool.Sequence.get_highlighted_task()]
elif related_object_type == "RESOURCE":
products = [tool.Resource.get_highlighted_resource()]
return products or []
@classmethod
def enable_editing_cost_item_quantities(cls, cost_item=None):
props = bpy.context.scene.BIMCostProperties
props.active_cost_item_id = cost_item.id()
props.cost_item_editing_type = "QUANTITIES"
@classmethod
def enable_editing_cost_item_quantity(cls, physical_quantity=None):
bpy.context.scene.BIMCostProperties.active_cost_item_quantity_id = physical_quantity.id()
@classmethod
def load_cost_item_quantity_attributes(cls, physical_quantity=None):
props = bpy.context.scene.BIMCostProperties
props.quantity_attributes.clear()
blenderbim.bim.helper.import_attributes2(physical_quantity, props.quantity_attributes)
@classmethod
def enable_editing_cost_item_values(cls, cost_item=None):
props = bpy.context.scene.BIMCostProperties
props.active_cost_item_id = cost_item.id()
props.cost_item_editing_type = "VALUES"
@classmethod
def disable_editing_cost_item_quantity(cls):
bpy.context.scene.BIMCostProperties.active_cost_item_quantity_id = 0
@classmethod
def get_cost_item_quantity_attributes(cls):
props = bpy.context.scene.BIMCostProperties
return blenderbim.bim.helper.export_attributes(props.quantity_attributes)
@classmethod
def get_attributes_for_cost_value(cls, cost_type, cost_category):
if cost_type == "FIXED":
category = None
attributes = {"AppliedValue": 0.0}
elif cost_type == "SUM":
category = "*"
attributes = {"Category": category}
elif cost_type == "CATEGORY":
category = cost_category
attributes = {"Category": category}
return attributes
@classmethod
def load_cost_item_value_attributes(cls, cost_value=None):
def import_attributes(name, prop, data, cost_value, is_rates, props_collection):
if name == "AppliedValue":
# TODO: for now, only support simple IfcValues (which are effectively IfcMonetaryMeasure)
prop = props_collection.add()
prop.data_type = "float"
prop.name = "AppliedValue"
prop.is_optional = True
prop.float_value = (
0.0
if prop.is_null
else ifcopenshell.util.cost.calculate_applied_value(
tool.Ifc.get().by_id(props.active_cost_item_id), cost_value
)
)
return True
if name == "UnitBasis" and is_rates:
prop = props_collection.add()
prop.name = "UnitBasisValue"
prop.data_type = "float"
prop.is_null = data["UnitBasis"] is None
prop.is_optional = True
if data["UnitBasis"] and data["UnitBasis"].ValueComponent:
prop.float_value = data["UnitBasis"].ValueComponent.wrappedValue or 0
else:
prop.float_value = 0
prop = props_collection.add()
prop.name = "UnitBasisUnit"
prop.data_type = "enum"
prop.is_null = prop.is_optional = False
units = {}
def format_unit(unit):
if unit.is_a("IfcContextDependentUnit"):
return f"{unit.UnitType} / {unit.Name}"
else:
name = unit.Name
if unit.get_info().get("Prefix", None):
name = f"{unit.Prefix} {name}"
return f"{unit.UnitType} / {name}"
for unit in tool.Ifc.get().by_type("IfcNamedUnit"):
if unit.get_info().get("UnitType", None) in [
"AREAUNIT",
"LENGTHUNIT",
"TIMEUNIT",
"VOLUMEUNIT",
"MASSUNIT",
"USERDEFINED",
]:
units[unit.id()] = format_unit(unit)
prop.enum_items = json.dumps(units)
if data["UnitBasis"] and data["UnitBasis"].UnitComponent:
# prop.enum_value = prop.enum_items[data["UnitBasis"].UnitComponent.id()]
print(prop.enum_items)
for key, value in json.loads(prop.enum_items).items():
if value == format_unit(data["UnitBasis"].UnitComponent):
prop.enum_value = key
break
return True
props = bpy.context.scene.BIMCostProperties
props.cost_value_attributes.clear()
is_rates = cls.is_active_schedule_of_rates()
callback = lambda name, prop, data: import_attributes(
name, prop, data, cost_value, is_rates, props.cost_value_attributes
)
blenderbim.bim.helper.import_attributes2(cost_value, props.cost_value_attributes, callback=callback)
@classmethod
def is_active_schedule_of_rates(cls):
return (
tool.Ifc.get().by_id(bpy.context.scene.BIMCostProperties.active_cost_schedule_id).PredefinedType
== "SCHEDULEOFRATES"
)
@classmethod
def enable_editing_cost_item_value(cls, cost_value=None):
props = bpy.context.scene.BIMCostProperties
props.active_cost_value_id = cost_value.id()
props.cost_value_editing_type = "ATTRIBUTES"
@classmethod
def disable_editing_cost_item_value(cls):
props = bpy.context.scene.BIMCostProperties
props.active_cost_value_id = 0
props.cost_value_editing_type = ""
@classmethod
def load_cost_item_value_formula_attributes(cls, cost_value=None):
props = bpy.context.scene.BIMCostProperties
props.cost_value_attributes.clear() # why is this necessary?
bpy.context.scene.BIMCostProperties.cost_value_formula = ifcopenshell.util.cost.serialise_cost_value(cost_value)
@classmethod
def enable_editing_cost_item_value_formula(cls, cost_value=None):
props = bpy.context.scene.BIMCostProperties
props.active_cost_value_id = cost_value.id()
props.cost_value_editing_type = "FORMULA"
@classmethod
def get_cost_item_value_formula(cls):
return bpy.context.scene.BIMCostProperties.cost_value_formula
@classmethod
def get_cost_value_attributes(cls):
def export_attributes(attributes, prop):
if prop.name == "UnitBasisValue":
if prop.is_null:
attributes["UnitBasis"] = None
return True
attributes["UnitBasis"] = {
"ValueComponent": prop.float_value or 1,
"UnitComponent": cls.get_cost_value_unit_component(),
}
print(attributes)
return True
if prop.name == "UnitBasisUnit":
return True
props = bpy.context.scene.BIMCostProperties
callback = lambda attributes, prop: export_attributes(attributes, prop)
return blenderbim.bim.helper.export_attributes(props.cost_value_attributes, callback)
@classmethod
def get_cost_value_unit_component(cls):
return tool.Ifc.get().by_id(
int(bpy.context.scene.BIMCostProperties.cost_value_attributes.get("UnitBasisUnit").enum_value)
)
@classmethod
def get_direct_cost_item_products(cls, cost_item):
return [related_object for r in cost_item.Controls or [] for related_object in r.RelatedObjects]
@classmethod
def get_cost_item_products(cls, cost_item, include_nested=False):
if not include_nested:
return cls.get_direct_cost_item_products(cost_item)
else:
return [
product
for nested_cost_item in cls.get_all_nested_cost_items(cost_item)
for product in cls.get_direct_cost_item_products(nested_cost_item)
]
@classmethod
def get_all_nested_cost_items(cls, cost_item):
for cost_item in cls.get_nested_cost_items(cost_item):
yield cost_item
yield from cls.get_all_nested_cost_items(cost_item)
@classmethod
def get_nested_cost_items(cls, cost_item):
return [obj for rel in cost_item.IsNestedBy for obj in rel.RelatedObjects]
@classmethod
def print_all_cost_items(cls, cost_schedule):
print(cls.get_schedule_cost_items(cost_schedule))
@classmethod
def get_schedule_cost_items(cls, cost_schedule):
for cost_item in cls.get_root_cost_items(cost_schedule):
yield cost_item
yield from cls.get_all_nested_cost_items(cost_item)
@classmethod
def get_root_cost_items(cls, cost_schedule):
return [
related_object
for rel in cost_schedule.Controls or []
for related_object in rel.RelatedObjects
if related_object.is_a("IfcCostItem")
]
@classmethod
def get_cost_schedule_products(cls, cost_schedule):
products = []
for cost_item in cls.get_root_cost_items(cost_schedule):
products.extend(cls.get_cost_item_products(cost_item, include_nested=True))
return products
@classmethod
def import_cost_schedule_csv(cls, file_path=None, is_schedule_of_rates=False):
if not file_path:
return
from ifc5d.csv2ifc import Csv2Ifc
import time
start = time.time()
csv2ifc = Csv2Ifc()
csv2ifc.csv = file_path
csv2ifc.file = tool.Ifc.get()
csv2ifc.is_schedule_of_rates = is_schedule_of_rates
csv2ifc.execute()
print("Import finished in {:.2f} seconds".format(time.time() - start))
@classmethod
def add_cost_column(cls, name):
props = bpy.context.scene.BIMCostProperties
new = props.columns.add()
new.name = name
@classmethod
def remove_cost_column(cls, name):
props = bpy.context.scene.BIMCostProperties
props.columns.remove(props.columns.find(name))
@classmethod
def expand_cost_item_rate(cls, cost_item):
props = bpy.context.scene.BIMCostProperties
contracted_cost_item_rates = json.loads(props.contracted_cost_item_rates)
contracted_cost_item_rates.remove(cost_item)
props.contracted_cost_item_rates = json.dumps(contracted_cost_item_rates)
cls.load_schedule_of_rates(schedule_of_rates=tool.Ifc.get().by_id(int(props.schedule_of_rates)))
@classmethod
def contract_cost_item_rate(cls, cost_item):
props = bpy.context.scene.BIMCostProperties
contracted_cost_item_rates = json.loads(props.contracted_cost_item_rates)
contracted_cost_item_rates.append(cost_item)
props.contracted_cost_item_rates = json.dumps(contracted_cost_item_rates)
cls.load_schedule_of_rates(schedule_of_rates=tool.Ifc.get().by_id(int(props.schedule_of_rates)))
@classmethod
def create_new_cost_item_li(cls, props_collection, cost_item, level_index, type="cost_rate"):
new = props_collection.add()
new.ifc_definition_id = cost_item.id()
new.name = cost_item.Name or "Unnamed"
new.identification = cost_item.Identification or "XXX"
new.is_expanded = (
cost_item.id() not in cls.contracted_cost_item_rates
if type == "cost_rate"
else cost_item.id() not in cls.contracted_cost_items
)
new.level_index = level_index
if cost_item.IsNestedBy:
new.has_children = True
if new.is_expanded:
[
cls.create_new_cost_item_li(props_collection, sub_cost_item, level_index + 1, type)
for rel in cost_item.IsNestedBy
for sub_cost_item in rel.RelatedObjects
]
@classmethod
def load_schedule_of_rates_tree(cls, schedule_of_rates):
props = bpy.context.scene.BIMCostProperties
props.is_cost_update_enabled = False
props.cost_item_rates.clear()
props.columns.clear()
cls.contracted_cost_item_rates = json.loads(props.contracted_cost_item_rates)
for rel in schedule_of_rates.Controls or []:
[
cls.create_new_cost_item_li(props.cost_item_rates, cost_item, 0, type="cost_rate")
for cost_item in rel.RelatedObjects
]
props.is_cost_update_enabled = True