mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-08-10 01:41:57 +00:00
You can now count elements, tasks, and resources parametrically for cost items
This commit is contained in:
@@ -183,7 +183,7 @@ class IfcStore:
|
||||
def commit_link_element(data):
|
||||
obj = bpy.data.objects.get(data["obj"])
|
||||
IfcStore.id_map[data["id"]] = obj
|
||||
if data["guid"]:
|
||||
if "guid" in data:
|
||||
IfcStore.guid_map[data["guid"]] = obj
|
||||
blenderbim.bim.handler.subscribe_to(obj, "mode", blenderbim.bim.handler.mode_callback)
|
||||
blenderbim.bim.handler.subscribe_to(obj, "name", blenderbim.bim.handler.name_callback)
|
||||
|
||||
@@ -637,10 +637,10 @@ class EnableEditingCostItemValue(bpy.types.Operator):
|
||||
data = Data.cost_values[self.cost_value]
|
||||
|
||||
blenderbim.bim.helper.import_attributes(
|
||||
data["type"],
|
||||
self.props.cost_value_attributes,
|
||||
data,
|
||||
lambda name, prop, data: self.import_attributes(name, prop, data, context)
|
||||
data["type"],
|
||||
self.props.cost_value_attributes,
|
||||
data,
|
||||
lambda name, prop, data: self.import_attributes(name, prop, data, context),
|
||||
)
|
||||
return {"FINISHED"}
|
||||
|
||||
@@ -715,8 +715,8 @@ class EditCostValue(bpy.types.Operator):
|
||||
def _execute(self, context):
|
||||
props = context.scene.BIMCostProperties
|
||||
attributes = blenderbim.bim.helper.export_attributes(
|
||||
props.cost_value_attributes,
|
||||
lambda attributes, prop: self.export_attributes(attributes, prop, context))
|
||||
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",
|
||||
|
||||
@@ -79,7 +79,7 @@ def update_schedule_of_rates(self, context):
|
||||
bpy.ops.bim.load_schedule_of_rates(cost_schedule=int(self.schedule_of_rates))
|
||||
|
||||
|
||||
def getQuantityTypes(self, context):
|
||||
def get_quantity_types(self, context):
|
||||
global quantitytypes_enum
|
||||
if len(quantitytypes_enum) == 0 and IfcStore.get_schema():
|
||||
quantitytypes_enum.extend(
|
||||
@@ -91,7 +91,7 @@ def getQuantityTypes(self, context):
|
||||
return quantitytypes_enum
|
||||
|
||||
|
||||
def getProductQuantityNames(self, context):
|
||||
def get_product_quantity_names(self, context):
|
||||
global productquantitynames_enum
|
||||
global productquantitynames_count
|
||||
ifc_file = IfcStore.get_file()
|
||||
@@ -115,7 +115,7 @@ def getProductQuantityNames(self, context):
|
||||
return productquantitynames_enum
|
||||
|
||||
|
||||
def getProcessQuantityNames(self, context):
|
||||
def get_process_quantity_names(self, context):
|
||||
global processquantitynames_enum
|
||||
global processquantitynames_id
|
||||
ifc_file = IfcStore.get_file()
|
||||
@@ -137,7 +137,7 @@ def getProcessQuantityNames(self, context):
|
||||
return processquantitynames_enum
|
||||
|
||||
|
||||
def getResourceQuantityNames(self, context):
|
||||
def get_resource_quantity_names(self, context):
|
||||
global resourcequantitynames_enum
|
||||
global resourcequantitynames_id
|
||||
ifc_file = IfcStore.get_file()
|
||||
@@ -166,7 +166,7 @@ def update_active_cost_item_index(self, context):
|
||||
bpy.ops.bim.load_cost_item_quantities()
|
||||
|
||||
|
||||
def updateCostItemIdentification(self, context):
|
||||
def update_cost_item_identification(self, context):
|
||||
props = context.scene.BIMCostProperties
|
||||
if not props.is_cost_update_enabled or self.identification == "XXX":
|
||||
return
|
||||
@@ -182,7 +182,7 @@ def updateCostItemIdentification(self, context):
|
||||
attribute.string_value = self.identification
|
||||
|
||||
|
||||
def updateCostItemName(self, context):
|
||||
def update_cost_item_name(self, context):
|
||||
props = context.scene.BIMCostProperties
|
||||
if not props.is_cost_update_enabled or self.name == "Unnamed":
|
||||
return
|
||||
@@ -199,8 +199,8 @@ def updateCostItemName(self, context):
|
||||
|
||||
|
||||
class CostItem(PropertyGroup):
|
||||
name: StringProperty(name="Name", update=updateCostItemName)
|
||||
identification: StringProperty(name="Identification", update=updateCostItemIdentification)
|
||||
name: StringProperty(name="Name", update=update_cost_item_name)
|
||||
identification: StringProperty(name="Identification", update=update_cost_item_identification)
|
||||
ifc_definition_id: IntProperty(name="IFC Definition ID")
|
||||
has_children: BoolProperty(name="Has Children")
|
||||
is_expanded: BoolProperty(name="Is Expanded")
|
||||
@@ -229,10 +229,10 @@ class BIMCostProperties(PropertyGroup):
|
||||
active_cost_item_index: IntProperty(name="Active Cost Item Index", update=update_active_cost_item_index)
|
||||
cost_item_attributes: CollectionProperty(name="Task Attributes", type=Attribute)
|
||||
contracted_cost_items: StringProperty(name="Contracted Cost Items", default="[]")
|
||||
quantity_types: EnumProperty(items=getQuantityTypes, name="Quantity Types")
|
||||
product_quantity_names: EnumProperty(items=getProductQuantityNames, name="Product Quantity Names")
|
||||
process_quantity_names: EnumProperty(items=getProcessQuantityNames, name="Process Quantity Names")
|
||||
resource_quantity_names: EnumProperty(items=getResourceQuantityNames, name="Resource Quantity Names")
|
||||
quantity_types: EnumProperty(items=get_quantity_types, name="Quantity Types")
|
||||
product_quantity_names: EnumProperty(items=get_product_quantity_names, name="Product Quantity Names")
|
||||
process_quantity_names: EnumProperty(items=get_process_quantity_names, name="Process Quantity Names")
|
||||
resource_quantity_names: EnumProperty(items=get_resource_quantity_names, name="Resource Quantity Names")
|
||||
active_cost_item_quantity_id: IntProperty(name="Active Cost Item Quantity Id")
|
||||
quantity_attributes: CollectionProperty(name="Quantity Attributes", type=Attribute)
|
||||
cost_types: EnumProperty(
|
||||
|
||||
@@ -373,11 +373,29 @@ class BIM_PT_cost_item_quantities(Panel):
|
||||
# Column1
|
||||
col = grid.column()
|
||||
|
||||
has_quantity_names = CostProp.get_product_quantity_names(self, context)
|
||||
|
||||
row2 = col.row(align=True)
|
||||
row2.label(text="Elements")
|
||||
op = row2.operator("bim.select_cost_item_products", icon="RESTRICT_SELECT_OFF", text="")
|
||||
op.cost_item = cost_item.ifc_definition_id
|
||||
|
||||
if context.selected_objects:
|
||||
if has_quantity_names:
|
||||
op = row2.operator("bim.assign_cost_item_quantity", text="", icon="PROPERTIES")
|
||||
op.related_object_type = "PRODUCT"
|
||||
op.cost_item = cost_item.ifc_definition_id
|
||||
op.prop_name = self.props.product_quantity_names
|
||||
|
||||
op = row2.operator("bim.assign_cost_item_quantity", text="", icon="ADD")
|
||||
op.related_object_type = "PRODUCT"
|
||||
op.cost_item = cost_item.ifc_definition_id
|
||||
op.prop_name = ""
|
||||
|
||||
op = row2.operator("bim.unassign_cost_item_quantity", text="", icon="REMOVE")
|
||||
op.cost_item = cost_item.ifc_definition_id
|
||||
op.related_object = 0
|
||||
|
||||
row2 = col.row()
|
||||
row2.template_list(
|
||||
"BIM_UL_cost_item_quantities",
|
||||
@@ -388,23 +406,32 @@ class BIM_PT_cost_item_quantities(Panel):
|
||||
"active_cost_item_product_index",
|
||||
)
|
||||
|
||||
row2 = col.row(align=True)
|
||||
row2.prop(self.props, "product_quantity_names", text="")
|
||||
op = row2.operator("bim.unassign_cost_item_quantity", text="", icon="REMOVE")
|
||||
op.cost_item = cost_item.ifc_definition_id
|
||||
op.related_object = 0
|
||||
if CostProp.productquantitynames_enum:
|
||||
op = row2.operator("bim.assign_cost_item_quantity", text="", icon="ADD")
|
||||
op.related_object_type = "PRODUCT"
|
||||
op.cost_item = cost_item.ifc_definition_id
|
||||
op.prop_name = self.props.product_quantity_names
|
||||
if has_quantity_names:
|
||||
row2 = col.row()
|
||||
row2.prop(self.props, "product_quantity_names", text="")
|
||||
|
||||
# Column2
|
||||
col = grid.column()
|
||||
|
||||
has_quantity_names = CostProp.get_process_quantity_names(self, context)
|
||||
|
||||
row2 = col.row(align=True)
|
||||
row2.label(text="Tasks")
|
||||
|
||||
tprops = context.scene.BIMTaskTreeProperties
|
||||
wprops = context.scene.BIMWorkScheduleProperties
|
||||
if tprops.tasks and wprops.active_task_index < len(tprops.tasks):
|
||||
if has_quantity_names:
|
||||
op = row2.operator("bim.assign_cost_item_quantity", text="", icon="PROPERTIES")
|
||||
op.related_object_type = "PROCESS"
|
||||
op.cost_item = cost_item.ifc_definition_id
|
||||
op.prop_name = self.props.process_quantity_names
|
||||
|
||||
op = row2.operator("bim.assign_cost_item_quantity", text="", icon="ADD")
|
||||
op.related_object_type = "PROCESS"
|
||||
op.cost_item = cost_item.ifc_definition_id
|
||||
op.prop_name = ""
|
||||
|
||||
row2 = col.row()
|
||||
row2.template_list(
|
||||
"BIM_UL_cost_item_quantities",
|
||||
@@ -415,20 +442,32 @@ class BIM_PT_cost_item_quantities(Panel):
|
||||
"active_cost_item_process_index",
|
||||
)
|
||||
|
||||
row2 = col.row(align=True)
|
||||
row2.prop(self.props, "process_quantity_names", text="")
|
||||
if CostProp.processquantitynames_enum:
|
||||
op = row2.operator("bim.assign_cost_item_quantity", text="", icon="ADD")
|
||||
op.related_object_type = "PROCESS"
|
||||
op.cost_item = cost_item.ifc_definition_id
|
||||
op.prop_name = self.props.process_quantity_names
|
||||
if has_quantity_names:
|
||||
row2 = col.row()
|
||||
row2.prop(self.props, "process_quantity_names", text="")
|
||||
|
||||
# Column3
|
||||
col = grid.column()
|
||||
|
||||
has_quantity_names = CostProp.get_resource_quantity_names(self, context)
|
||||
|
||||
row2 = col.row(align=True)
|
||||
row2.label(text="Resources")
|
||||
|
||||
rtprops = context.scene.BIMResourceTreeProperties
|
||||
rprops = context.scene.BIMResourceProperties
|
||||
if rtprops.resources and rprops.active_resource_index < len(rtprops.resources):
|
||||
if has_quantity_names:
|
||||
op = row2.operator("bim.assign_cost_item_quantity", text="", icon="PROPERTIES")
|
||||
op.related_object_type = "RESOURCE"
|
||||
op.cost_item = cost_item.ifc_definition_id
|
||||
op.prop_name = self.props.resource_quantity_names
|
||||
|
||||
op = row2.operator("bim.assign_cost_item_quantity", text="", icon="ADD")
|
||||
op.related_object_type = "RESOURCE"
|
||||
op.cost_item = cost_item.ifc_definition_id
|
||||
op.prop_name = ""
|
||||
|
||||
row2 = col.row()
|
||||
row2.template_list(
|
||||
"BIM_UL_cost_item_quantities",
|
||||
@@ -439,14 +478,9 @@ class BIM_PT_cost_item_quantities(Panel):
|
||||
"active_cost_item_resource_index",
|
||||
)
|
||||
|
||||
row2 = col.row(align=True)
|
||||
row2.prop(self.props, "resource_quantity_names", text="")
|
||||
if CostProp.resourcequantitynames_enum:
|
||||
op = row2.operator("bim.assign_cost_item_quantity", text="", icon="ADD")
|
||||
op.related_object_type = "RESOURCE"
|
||||
op.cost_item = cost_item.ifc_definition_id
|
||||
op.prop_name = self.props.resource_quantity_names
|
||||
|
||||
if has_quantity_names:
|
||||
row2 = col.row()
|
||||
row2.prop(self.props, "resource_quantity_names", text="")
|
||||
|
||||
class BIM_PT_cost_item_rates(Panel):
|
||||
bl_label = "IFC Cost Item Rates"
|
||||
|
||||
@@ -14,8 +14,10 @@ class Usecase:
|
||||
# This is a bold assumption
|
||||
# https://forums.buildingsmart.org/t/how-does-a-cost-item-know-that-it-is-counting-a-controlled-product/3564
|
||||
if self.settings["ifc_class"] == "IfcQuantityCount" and self.settings["cost_item"].Controls:
|
||||
count = 0
|
||||
for rel in self.settings["cost_item"].Controls:
|
||||
quantity[3] += len(rel.RelatedObjects)
|
||||
count += len(rel.RelatedObjects)
|
||||
quantity[3] = count
|
||||
quantities = list(self.settings["cost_item"].CostQuantities or [])
|
||||
quantities.append(quantity)
|
||||
self.settings["cost_item"].CostQuantities = quantities
|
||||
|
||||
@@ -9,7 +9,8 @@ class Usecase:
|
||||
self.settings[key] = value
|
||||
|
||||
def execute(self):
|
||||
self.quantities = set(self.settings["cost_item"].CostQuantities or [])
|
||||
if self.settings["prop_name"]:
|
||||
self.quantities = set(self.settings["cost_item"].CostQuantities or [])
|
||||
for product in self.settings["products"]:
|
||||
ifcopenshell.api.run(
|
||||
"control.assign_control",
|
||||
@@ -17,8 +18,12 @@ class Usecase:
|
||||
related_object=product,
|
||||
relating_control=self.settings["cost_item"],
|
||||
)
|
||||
self.add_quantity_from_related_object(product)
|
||||
self.settings["cost_item"].CostQuantities = list(self.quantities)
|
||||
if self.settings["prop_name"]:
|
||||
self.add_quantity_from_related_object(product)
|
||||
if self.settings["prop_name"]:
|
||||
self.settings["cost_item"].CostQuantities = list(self.quantities)
|
||||
else:
|
||||
self.update_cost_item_count()
|
||||
|
||||
def add_quantity_from_related_object(self, element):
|
||||
if not element.is_a("IfcObject"):
|
||||
@@ -33,3 +38,21 @@ class Usecase:
|
||||
for prop in qto.Quantities:
|
||||
if prop.is_a("IfcPhysicalSimpleQuantity") and prop.Name.lower() == self.settings["prop_name"].lower():
|
||||
self.quantities.add(prop)
|
||||
|
||||
def update_cost_item_count(self):
|
||||
# This is a bold assumption
|
||||
# https://forums.buildingsmart.org/t/how-does-a-cost-item-know-that-it-is-counting-a-controlled-product/3564
|
||||
if not self.settings["cost_item"].CostQuantities:
|
||||
return ifcopenshell.api.run(
|
||||
"cost.add_cost_item_quantity",
|
||||
self.file,
|
||||
cost_item=self.settings["cost_item"],
|
||||
ifc_class="IfcQuantityCount",
|
||||
)
|
||||
if len(self.settings["cost_item"].CostQuantities) == 1:
|
||||
quantity = self.settings["cost_item"].CostQuantities[0]
|
||||
if quantity.is_a("IfcQuantityCount"):
|
||||
count = 0
|
||||
for rel in self.settings["cost_item"].Controls:
|
||||
count += len(rel.RelatedObjects)
|
||||
quantity[3] = count
|
||||
|
||||
@@ -19,7 +19,6 @@ class Usecase:
|
||||
if related_object in self.settings["products"]:
|
||||
self.quantities.remove(quantity)
|
||||
self.settings["cost_item"].CostQuantities = list(self.quantities)
|
||||
|
||||
for product in self.settings["products"]:
|
||||
ifcopenshell.api.run(
|
||||
"control.unassign_control",
|
||||
@@ -27,3 +26,15 @@ class Usecase:
|
||||
related_object=product,
|
||||
relating_control=self.settings["cost_item"],
|
||||
)
|
||||
self.update_cost_item_count()
|
||||
|
||||
def update_cost_item_count(self):
|
||||
# This is a bold assumption
|
||||
# https://forums.buildingsmart.org/t/how-does-a-cost-item-know-that-it-is-counting-a-controlled-product/3564
|
||||
if len(self.settings["cost_item"].CostQuantities) == 1:
|
||||
quantity = self.settings["cost_item"].CostQuantities[0]
|
||||
if quantity.is_a("IfcQuantityCount"):
|
||||
count = 0
|
||||
for rel in self.settings["cost_item"].Controls:
|
||||
count += len(rel.RelatedObjects)
|
||||
quantity[3] = count
|
||||
|
||||
Reference in New Issue
Block a user