You can now view & and highlight cost items assigned to an object, from Viewport Selection

This commit is contained in:
Sigma Dimensions
2023-03-29 00:41:59 +00:00
parent 3502b560f0
commit 7850f8c718
8 changed files with 171 additions and 27 deletions
@@ -68,6 +68,8 @@ classes = (
operator.ContractCostItemRate,
operator.CalculateCostItemResourceValue,
operator.ClearCostItemAssignments,
operator.HighlightProductCostItem,
operator.LoadProductCostItems,
operator.SelectUnassignedProducts,
operator.LoadCostItemElementQuantities,
operator.LoadCostItemTaskQuantities,
@@ -85,6 +87,8 @@ classes = (
ui.BIM_UL_cost_item_quantities,
ui.BIM_UL_cost_item_types,
ui.BIM_UL_cost_item_rates,
ui.BIM_UL_product_cost_items,
ui.BIM_PT_Costing_Tools,
)
@@ -456,9 +456,7 @@ class SelectCostItemProducts(bpy.types.Operator, tool.Ifc.Operator):
cost_item: bpy.props.IntProperty()
def _execute(self, context):
core.select_cost_item_products(
tool.Cost, tool.Spatial, cost_item=tool.Ifc.get().by_id(self.cost_item), include_nested=False
)
core.select_cost_item_products(tool.Cost, tool.Spatial, cost_item=tool.Ifc.get().by_id(self.cost_item))
return {"FINISHED"}
@@ -654,6 +652,38 @@ class ClearCostItemAssignments(bpy.types.Operator, tool.Ifc.Operator):
return {"FINISHED"}
class LoadProductCostItems(bpy.types.Operator):
bl_idname = "bim.load_product_cost_items"
bl_label = "Get Product Cost Assignments"
bl_options = {"REGISTER", "UNDO"}
product: bpy.props.IntProperty()
@classmethod
def poll(cls, context):
if not tool.Ifc.get():
return False
if not context.active_object.BIMObjectProperties.ifc_definition_id:
return False
return True
def execute(self, context):
core.load_product_cost_items(tool.Cost, product=tool.Ifc.get().by_id(self.product))
return {"FINISHED"}
class HighlightProductCostItem(bpy.types.Operator):
bl_idname = "bim.highlight_product_cost_item"
bl_label = "Highlight Product Cost Items"
bl_options = {"REGISTER", "UNDO"}
cost_item: bpy.props.IntProperty()
def execute(self, context):
r = core.highlight_product_cost_item(tool.Spatial, tool.Cost, cost_item=tool.Ifc.get().by_id(self.cost_item))
if isinstance(r, str):
self.report({"WARNING"}, r)
return {"FINISHED"}
class SelectUnassignedProducts(bpy.types.Operator):
bl_idname = "bim.select_unassigned_products"
bl_label = "Select Unassigned Products"
@@ -197,6 +197,8 @@ class BIMCostProperties(PropertyGroup):
cost_item_rates: CollectionProperty(name="Cost Item Rates", type=CostItem)
active_cost_item_rate_index: IntProperty(name="Active Cost Rate Index")
contracted_cost_item_rates: StringProperty(name="Contracted Cost Item Rates", default="[]")
product_cost_items: CollectionProperty(name="Product Cost Items", type=CostItem)
active_product_cost_item_index: IntProperty(name="Active Product Cost Item Index")
show_nested_elements: BoolProperty(name="Show Nested Tasks", default=False, update=update_active_cost_item_elements)
show_nested_tasks: BoolProperty(name="Show Nested Tasks", default=False, update=update_active_cost_item_tasks)
show_nested_resources: BoolProperty(
@@ -64,6 +64,9 @@ class BIM_PT_cost_schedules(Panel):
op = row.operator("bim.select_cost_schedule_products", icon="RESTRICT_SELECT_OFF", text="")
op.cost_schedule = cost_schedule["id"]
row.prop(self.props, "should_show_column_ui", text="", icon="SHORTDISPLAY")
row.operator("bim.select_unassigned_products", icon="RESTRICT_SELECT_OFF", text="Unassigned")
if self.props.is_editing == "COST_SCHEDULE_ATTRIBUTES":
row.operator("bim.edit_cost_schedule", text="", icon="CHECKMARK")
elif self.props.is_editing == "COST_ITEMS":
@@ -377,7 +380,7 @@ class BIM_PT_cost_item_quantities(Panel):
row2 = col.row()
op = row2.operator("bim.clear_cost_item_assignments", text="Clear assignments", icon="X")
op.cost_item = cost_item.ifc_definition_id
op.related_object_type = "IfcElement"
op.related_object_type = "PRODUCT"
if has_quantity_names:
row2 = col.row()
@@ -422,7 +425,7 @@ class BIM_PT_cost_item_quantities(Panel):
row2 = col.row()
op = row2.operator("bim.clear_cost_item_assignments", text="Clear assignments", icon="X")
op.cost_item = cost_item.ifc_definition_id
op.related_object_type = "IfcProcess"
op.related_object_type = "PROCESS"
if has_quantity_names:
row2 = col.row()
@@ -470,7 +473,7 @@ class BIM_PT_cost_item_quantities(Panel):
row2 = col.row()
op = row2.operator("bim.clear_cost_item_assignments", text="Clear assignments", icon="X")
op.cost_item = cost_item.ifc_definition_id
op.related_object_type = "IfcResource"
op.related_object_type = "RESOURCE"
if has_quantity_names:
row2 = col.row()
@@ -636,3 +639,41 @@ class BIM_UL_cost_item_quantities(UIList):
op = row.operator("bim.unassign_cost_item_quantity", text="", icon="X")
op.cost_item = cost_item.ifc_definition_id
op.related_object = item.ifc_definition_id
class BIM_UL_product_cost_items(UIList):
def draw_item(self, context, layout, data, item, icon, active_data, active_propname):
props = context.scene.BIMCostProperties
oprops = context.active_object.BIMObjectProperties
cost_item = props.cost_items[props.active_cost_item_index]
if item:
row = layout.row(align=True)
op = row.operator("bim.highlight_product_cost_item", text="", icon="STYLUS_PRESSURE")
op.cost_item = item.ifc_definition_id
row.split(factor=0.8)
row.label(text=item.name)
class BIM_PT_Costing_Tools(Panel):
bl_label = "5D Tools"
bl_idname = "BIM_PT_Costing_Tools"
bl_space_type = "VIEW_3D"
bl_region_type = "UI"
bl_category = "4D/5D Toolkit"
def draw(self, context):
self.props = context.scene.BIMCostProperties
row = self.layout.row()
row.operator(
"bim.load_product_cost_items", icon="FILE_REFRESH"
).product = context.active_object.BIMObjectProperties.ifc_definition_id
row = self.layout.row()
row.template_list(
"BIM_UL_product_cost_items",
"",
self.props,
"product_cost_items",
self.props,
"active_product_cost_item_index",
)
@@ -137,7 +137,7 @@ classes = (
ui.BIM_UL_task_resources,
ui.BIM_UL_task_outputs,
ui.BIM_UL_tasks,
ui.BIM_PT_Task_Tools,
ui.BIM_PT_4D_Tools,
ui.BIM_PT_Task_Bar_Creator,
ui.BIM_UL_animation_colors,
)
@@ -790,12 +790,31 @@ class BIM_PT_work_calendars(Panel):
draw_attributes(self.props.work_calendar_attributes, self.layout)
class BIM_PT_Task_Tools(Panel):
class BIM_PT_4D_Tools(Panel):
bl_label = "4D Tools"
bl_idname = "BIM_PT_4D_Tools"
bl_space_type = "VIEW_3D"
bl_region_type = "UI"
bl_category = "4D/5D Toolkit"
def draw(self, context):
row = self.layout.row()
row.operator(
"bim.highlight_product_related_task", text="Find Input-related Task ", icon="STYLUS_PRESSURE"
).product_type = "Input"
row = self.layout.row()
row.operator(
"bim.highlight_product_related_task", text="Go to Output-related Task ", icon="STYLUS_PRESSURE"
).product_type = "Output"
class BIM_PT_Task_Bar_Creator(Panel):
bl_label = "Task Bar Creator"
bl_idname = "BIM_PT_Task_Bar_Creator"
bl_space_type = "VIEW_3D"
bl_region_type = "UI"
bl_category = "Sequence Toolkit"
bl_options = {"DEFAULT_CLOSED"}
bl_parent_id = "BIM_PT_4D_Tools"
def draw(self, context):
self.animation_props = context.scene.BIMAnimationProperties
@@ -813,21 +832,3 @@ class BIM_PT_Task_Tools(Panel):
row3 = col.row(align=True)
row3.prop(self.animation_props, "color_full")
class BIM_PT_Task_Bar_Creator(Panel):
bl_label = "Task Tools"
bl_idname = "BIM_PT_Task_Tools"
bl_space_type = "VIEW_3D"
bl_region_type = "UI"
bl_category = "Sequence Toolkit"
def draw(self, context):
row = self.layout.row()
row.operator(
"bim.highlight_product_related_task", text="Find Input-related Task ", icon="STYLUS_PRESSURE"
).product_type = "Input"
row = self.layout.row()
row.operator(
"bim.highlight_product_related_task", text="Go to Output-related Task ", icon="STYLUS_PRESSURE"
).product_type = "Output"
+11
View File
@@ -247,3 +247,14 @@ def select_unassigned_products(ifc, cost, spatial):
cost_schedule = cost.get_active_cost_schedule()
selection = [product for product in products if not cost.has_cost_assignments(product, cost_schedule)]
spatial.select_products(selection)
def load_product_cost_items(cost, product):
cost.load_product_cost_items(product)
def highlight_product_cost_item(spatial, cost, cost_item):
cost_schedule = cost.get_cost_schedule(cost_item)
is_cost_schedule_active = cost.is_cost_schedule_active(cost_schedule)
if is_cost_schedule_active:
cost.highlight_cost_item(cost_item)
else:
return "Cost schedule is not active"
+55
View File
@@ -543,12 +543,47 @@ class Cost(blenderbim.core.tool.Cost):
name = f"{unit.Prefix} {name}"
return f"{unit.UnitType} / {name}"
@classmethod
def get_cost_schedule(cls, cost_item):
for rel in cost_item.HasAssignments or []:
if rel.is_a("IfcRelAssignsToControl") and rel.RelatingControl.is_a("IfcCostSchedule"):
return rel.RelatingControl
for rel in cost_item.Nests or []:
return cls.get_cost_schedule(rel.RelatingObject)
@classmethod
def is_cost_schedule_active(cls, cost_schedule):
return True if cost_schedule.id() == bpy.context.scene.BIMCostProperties.active_cost_schedule_id else False
@classmethod
def get_active_cost_schedule(cls):
if not bpy.context.scene.BIMCostProperties.active_cost_schedule_id:
return None
return tool.Ifc.get().by_id(bpy.context.scene.BIMCostProperties.active_cost_schedule_id)
@classmethod
def highlight_cost_item(cls, cost_item):
def expand_ancestors(cost_item):
cls.expand_cost_item(cost_item)
for rel in cost_item.Nests or []:
parent_cost = rel.RelatingObject if rel.RelatingObject.is_a("IfcCostItem") else None
if parent_cost:
expand_ancestors(parent_cost)
cls.load_cost_schedule_tree()
cost_props = bpy.context.scene.BIMCostProperties
if not cost_item.id() in [item.ifc_definition_id for item in cost_props.cost_items]:
expand_ancestors(cost_item)
cost_item_index = [item.ifc_definition_id for item in bpy.context.scene.BIMCostProperties.cost_items].index(
cost_item.id()
) or 0
bpy.context.scene.BIMCostProperties.active_cost_item_index = cost_item_index
@classmethod
def get_cost_items_for_product(cls, product):
return ifcopenshell.util.cost.get_cost_items_for_product(product)
@classmethod
def has_cost_assignments(cls, product, cost_schedule=None):
cost_items = ifcopenshell.util.cost.get_cost_items_for_product(product)
@@ -557,3 +592,23 @@ class Cost(blenderbim.core.tool.Cost):
cost_item for cost_item in cost_items or [] if cls.get_cost_schedule(cost_item) == cost_schedule
]
return bool(cost_items)
@classmethod
def load_product_cost_items(cls, product):
props = bpy.context.scene.BIMCostProperties
props.is_cost_update_enabled = False
props.product_cost_items.clear()
cost_items = ifcopenshell.util.cost.get_cost_items_for_product(product)
if cost_items:
for cost_item in cost_items:
new = props.product_cost_items.add()
new.name = cost_item.Name or "Unnamed"
new.ifc_definition_id = cost_item.id()
@classmethod
def is_root_cost_item(cls, cost_item):
if cost_item.HasAssignments:
for rel in cost_item.HasAssignments:
if rel.is_a("IfcRelAssignsToControl") and rel.RelatingControl.is_a("IfcCostSchedule"):
return True