You can now count elements, tasks, and resources parametrically for cost items

This commit is contained in:
Dion Moult
2021-08-26 15:48:04 +10:00
parent 2cfa1d8bc0
commit 00f779fc49
7 changed files with 119 additions and 49 deletions
+1 -1
View File
@@ -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(
+59 -25
View File
@@ -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