mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-08-10 17:58:20 +00:00
You can now view & and highlight cost items assigned to an object, from Viewport Selection
This commit is contained in:
@@ -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"
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
Reference in New Issue
Block a user