mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-09-22 08:18:37 +00:00
start refactoring costing operators into core & tool
This commit is contained in:
@@ -25,16 +25,18 @@ import blenderbim.bim.helper
|
|||||||
import blenderbim.tool as tool
|
import blenderbim.tool as tool
|
||||||
from blenderbim.bim.ifc import IfcStore
|
from blenderbim.bim.ifc import IfcStore
|
||||||
from bpy_extras.io_utils import ImportHelper
|
from bpy_extras.io_utils import ImportHelper
|
||||||
|
import blenderbim.tool as tool
|
||||||
|
import blenderbim.core.cost as core
|
||||||
|
|
||||||
|
|
||||||
class AddCostSchedule(bpy.types.Operator, tool.Ifc.Operator):
|
class AddCostSchedule(bpy.types.Operator, tool.Ifc.Operator):
|
||||||
bl_idname = "bim.add_cost_schedule"
|
bl_idname = "bim.add_cost_schedule"
|
||||||
bl_label = "Add Cost Schedule"
|
bl_label = "Add Cost Schedule"
|
||||||
bl_options = {"REGISTER", "UNDO"}
|
bl_options = {"REGISTER", "UNDO"}
|
||||||
|
bl_description = "Add a new cost schedule"
|
||||||
|
|
||||||
def _execute(self, context):
|
def _execute(self, context):
|
||||||
ifcopenshell.api.run("cost.add_cost_schedule", IfcStore.get_file())
|
core.add_cost_schedule(tool.Ifc)
|
||||||
return {"FINISHED"}
|
|
||||||
|
|
||||||
|
|
||||||
class EditCostSchedule(bpy.types.Operator, tool.Ifc.Operator):
|
class EditCostSchedule(bpy.types.Operator, tool.Ifc.Operator):
|
||||||
@@ -43,16 +45,11 @@ class EditCostSchedule(bpy.types.Operator, tool.Ifc.Operator):
|
|||||||
bl_options = {"REGISTER", "UNDO"}
|
bl_options = {"REGISTER", "UNDO"}
|
||||||
|
|
||||||
def _execute(self, context):
|
def _execute(self, context):
|
||||||
props = context.scene.BIMCostProperties
|
core.edit_cost_schedule(
|
||||||
attributes = blenderbim.bim.helper.export_attributes(props.cost_schedule_attributes)
|
tool.Ifc,
|
||||||
self.file = IfcStore.get_file()
|
tool.Cost,
|
||||||
ifcopenshell.api.run(
|
cost_schedule=tool.Ifc.get().by_id(context.scene.BIMCostProperties.active_cost_schedule_id),
|
||||||
"cost.edit_cost_schedule",
|
|
||||||
self.file,
|
|
||||||
**{"cost_schedule": self.file.by_id(props.active_cost_schedule_id), "attributes": attributes},
|
|
||||||
)
|
)
|
||||||
bpy.ops.bim.disable_editing_cost_schedule()
|
|
||||||
return {"FINISHED"}
|
|
||||||
|
|
||||||
|
|
||||||
class RemoveCostSchedule(bpy.types.Operator, tool.Ifc.Operator):
|
class RemoveCostSchedule(bpy.types.Operator, tool.Ifc.Operator):
|
||||||
@@ -62,39 +59,18 @@ class RemoveCostSchedule(bpy.types.Operator, tool.Ifc.Operator):
|
|||||||
cost_schedule: bpy.props.IntProperty()
|
cost_schedule: bpy.props.IntProperty()
|
||||||
|
|
||||||
def _execute(self, context):
|
def _execute(self, context):
|
||||||
ifcopenshell.api.run(
|
core.remove_cost_schedule(tool.Ifc, cost_schedule=tool.Ifc.get().by_id(self.cost_schedule))
|
||||||
"cost.remove_cost_schedule",
|
|
||||||
IfcStore.get_file(),
|
|
||||||
cost_schedule=IfcStore.get_file().by_id(self.cost_schedule),
|
|
||||||
)
|
|
||||||
return {"FINISHED"}
|
|
||||||
|
|
||||||
|
|
||||||
class EnableEditingCostSchedule(bpy.types.Operator, tool.Ifc.Operator):
|
class EnableEditingCostSchedule(bpy.types.Operator, tool.Ifc.Operator):
|
||||||
bl_idname = "bim.enable_editing_cost_schedule"
|
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"
|
||||||
cost_schedule: bpy.props.IntProperty()
|
cost_schedule: bpy.props.IntProperty()
|
||||||
|
|
||||||
def _execute(self, context):
|
def _execute(self, context):
|
||||||
self.props = context.scene.BIMCostProperties
|
core.enable_editing_cost_schedule_attributes(tool.Cost, cost_schedule=tool.Ifc.get().by_id(self.cost_schedule))
|
||||||
self.props.active_cost_schedule_id = self.cost_schedule
|
|
||||||
self.props.cost_schedule_attributes.clear()
|
|
||||||
self.enable_editing_cost_schedule()
|
|
||||||
self.props.is_editing = "COST_SCHEDULE"
|
|
||||||
return {"FINISHED"}
|
|
||||||
|
|
||||||
def enable_editing_cost_schedule(self):
|
|
||||||
blenderbim.bim.helper.import_attributes2(
|
|
||||||
tool.Ifc.get().by_id(self.cost_schedule),
|
|
||||||
self.props.cost_schedule_attributes,
|
|
||||||
callback=self.import_attributes,
|
|
||||||
)
|
|
||||||
|
|
||||||
def import_attributes(self, 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
|
|
||||||
|
|
||||||
|
|
||||||
class EnableEditingCostItems(bpy.types.Operator, tool.Ifc.Operator):
|
class EnableEditingCostItems(bpy.types.Operator, tool.Ifc.Operator):
|
||||||
@@ -104,50 +80,7 @@ class EnableEditingCostItems(bpy.types.Operator, tool.Ifc.Operator):
|
|||||||
cost_schedule: bpy.props.IntProperty()
|
cost_schedule: bpy.props.IntProperty()
|
||||||
|
|
||||||
def _execute(self, context):
|
def _execute(self, context):
|
||||||
if context.preferences.addons["blenderbim"].preferences.should_play_chaching_sound:
|
core.enable_editing_cost_items(tool.Cost, cost_schedule=tool.Ifc.get().by_id(self.cost_schedule))
|
||||||
self.play_chaching_sound() # lol
|
|
||||||
self.props = context.scene.BIMCostProperties
|
|
||||||
self.props.is_cost_update_enabled = False
|
|
||||||
self.props.active_cost_schedule_id = self.cost_schedule
|
|
||||||
self.props.cost_items.clear()
|
|
||||||
|
|
||||||
self.contracted_cost_items = json.loads(self.props.contracted_cost_items)
|
|
||||||
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_editing = "COST_ITEMS"
|
|
||||||
self.props.is_cost_update_enabled = True
|
|
||||||
return {"FINISHED"}
|
|
||||||
|
|
||||||
def play_chaching_sound(self):
|
|
||||||
# TODO: make pitch higher as costs rise
|
|
||||||
try:
|
|
||||||
import aud
|
|
||||||
|
|
||||||
device = aud.Device()
|
|
||||||
# chaching.mp3 is by Lucish_ CC-BY-3.0 https://freesound.org/people/Lucish_/sounds/554841/
|
|
||||||
sound = aud.Sound(os.path.join(context.scene.BIMProperties.data_dir, "chaching.mp3"))
|
|
||||||
handle = device.play(sound)
|
|
||||||
sound_buffered = aud.Sound.buffer(sound)
|
|
||||||
handle_buffered = device.play(sound_buffered)
|
|
||||||
handle.stop()
|
|
||||||
handle_buffered.stop()
|
|
||||||
except:
|
|
||||||
pass # ah well
|
|
||||||
|
|
||||||
def create_new_cost_item_li(self, cost_item, level_index):
|
|
||||||
new = self.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 self.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:
|
|
||||||
self.create_new_cost_item_li(sub_cost_item, level_index + 1)
|
|
||||||
|
|
||||||
|
|
||||||
class DisableEditingCostSchedule(bpy.types.Operator, tool.Ifc.Operator):
|
class DisableEditingCostSchedule(bpy.types.Operator, tool.Ifc.Operator):
|
||||||
@@ -156,68 +89,62 @@ class DisableEditingCostSchedule(bpy.types.Operator, tool.Ifc.Operator):
|
|||||||
bl_options = {"REGISTER", "UNDO"}
|
bl_options = {"REGISTER", "UNDO"}
|
||||||
|
|
||||||
def _execute(self, context):
|
def _execute(self, context):
|
||||||
context.scene.BIMCostProperties.active_cost_schedule_id = 0
|
core.disable_editing_cost_schedule(tool.Cost)
|
||||||
return {"FINISHED"}
|
|
||||||
|
|
||||||
|
|
||||||
class AddSummaryCostItem(bpy.types.Operator, tool.Ifc.Operator):
|
class AddSummaryCostItem(bpy.types.Operator, tool.Ifc.Operator):
|
||||||
bl_idname = "bim.add_summary_cost_item"
|
bl_idname = "bim.add_summary_cost_item"
|
||||||
bl_label = "Add Cost Item"
|
bl_label = "Add Cost Item"
|
||||||
bl_options = {"REGISTER", "UNDO"}
|
bl_options = {"REGISTER", "UNDO"}
|
||||||
|
bl_description = "Add a summary cost item"
|
||||||
cost_schedule: bpy.props.IntProperty()
|
cost_schedule: bpy.props.IntProperty()
|
||||||
|
|
||||||
def _execute(self, context):
|
def _execute(self, context):
|
||||||
props = context.scene.BIMCostProperties
|
core.add_summary_cost_item(tool.Ifc, tool.Cost, cost_schedule=tool.Ifc.get().by_id(self.cost_schedule))
|
||||||
self.file = IfcStore.get_file()
|
|
||||||
ifcopenshell.api.run("cost.add_cost_item", self.file, **{"cost_schedule": self.file.by_id(self.cost_schedule)})
|
|
||||||
bpy.ops.bim.enable_editing_cost_items(cost_schedule=self.cost_schedule)
|
|
||||||
return {"FINISHED"}
|
|
||||||
|
|
||||||
|
|
||||||
class AddCostItem(bpy.types.Operator, tool.Ifc.Operator):
|
class AddCostItem(bpy.types.Operator, tool.Ifc.Operator):
|
||||||
bl_idname = "bim.add_cost_item"
|
bl_idname = "bim.add_cost_item"
|
||||||
bl_label = "Add Cost Item"
|
bl_label = "Add Cost Item"
|
||||||
bl_options = {"REGISTER", "UNDO"}
|
bl_options = {"REGISTER", "UNDO"}
|
||||||
|
bl_description = "Add a new cost item"
|
||||||
cost_item: bpy.props.IntProperty()
|
cost_item: bpy.props.IntProperty()
|
||||||
|
|
||||||
def _execute(self, context):
|
def _execute(self, context):
|
||||||
props = context.scene.BIMCostProperties
|
core.add_cost_item(tool.Ifc, tool.Cost, cost_item=tool.Ifc.get().by_id(self.cost_item))
|
||||||
self.file = IfcStore.get_file()
|
|
||||||
ifcopenshell.api.run("cost.add_cost_item", self.file, **{"cost_item": self.file.by_id(self.cost_item)})
|
|
||||||
bpy.ops.bim.enable_editing_cost_items(cost_schedule=props.active_cost_schedule_id)
|
|
||||||
return {"FINISHED"}
|
|
||||||
|
|
||||||
|
|
||||||
class ExpandCostItem(bpy.types.Operator, tool.Ifc.Operator):
|
class ExpandCostItem(bpy.types.Operator, tool.Ifc.Operator):
|
||||||
bl_idname = "bim.expand_cost_item"
|
bl_idname = "bim.expand_cost_item"
|
||||||
bl_label = "Expand Cost Item"
|
bl_label = "Expand Cost Item"
|
||||||
bl_options = {"REGISTER", "UNDO"}
|
bl_options = {"REGISTER", "UNDO"}
|
||||||
|
bl_description = "Expand this cost item"
|
||||||
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(tool.Cost, cost_item=tool.Ifc.get().by_id(self.cost_item))
|
||||||
self.file = IfcStore.get_file()
|
|
||||||
contracted_cost_items = json.loads(props.contracted_cost_items)
|
|
||||||
contracted_cost_items.remove(self.cost_item)
|
class ExpandCostItems(bpy.types.Operator, tool.Ifc.Operator):
|
||||||
props.contracted_cost_items = json.dumps(contracted_cost_items)
|
bl_idname = "bim.expand_cost_items"
|
||||||
bpy.ops.bim.enable_editing_cost_items(cost_schedule=props.active_cost_schedule_id)
|
bl_label = "Expand Cost Items"
|
||||||
return {"FINISHED"}
|
bl_options = {"REGISTER", "UNDO"}
|
||||||
|
bl_description = "Expand all cost items"
|
||||||
|
cost_items: bpy.props.StringProperty()
|
||||||
|
|
||||||
|
def _execute(self, context):
|
||||||
|
core.expand_cost_items(tool.Cost)
|
||||||
|
|
||||||
|
|
||||||
class ContractCostItem(bpy.types.Operator, tool.Ifc.Operator):
|
class ContractCostItem(bpy.types.Operator, tool.Ifc.Operator):
|
||||||
bl_idname = "bim.contract_cost_item"
|
bl_idname = "bim.contract_cost_item"
|
||||||
bl_label = "Contract Cost Item"
|
bl_label = "Contract Cost Item"
|
||||||
bl_options = {"REGISTER", "UNDO"}
|
bl_options = {"REGISTER", "UNDO"}
|
||||||
|
bl_description = "Contract a cost item"
|
||||||
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(tool.Cost, cost_item=tool.Ifc.get().by_id(self.cost_item))
|
||||||
self.file = IfcStore.get_file()
|
|
||||||
contracted_cost_items = json.loads(props.contracted_cost_items)
|
|
||||||
contracted_cost_items.append(self.cost_item)
|
|
||||||
props.contracted_cost_items = json.dumps(contracted_cost_items)
|
|
||||||
bpy.ops.bim.enable_editing_cost_items(cost_schedule=props.active_cost_schedule_id)
|
|
||||||
return {"FINISHED"}
|
|
||||||
|
|
||||||
|
|
||||||
class RemoveCostItem(bpy.types.Operator, tool.Ifc.Operator):
|
class RemoveCostItem(bpy.types.Operator, tool.Ifc.Operator):
|
||||||
@@ -227,37 +154,17 @@ class RemoveCostItem(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.remove_cost_item(tool.Ifc, tool.Cost, cost_item=tool.Ifc.get().by_id(self.cost_item))
|
||||||
self.file = IfcStore.get_file()
|
|
||||||
ifcopenshell.api.run(
|
|
||||||
"cost.remove_cost_item",
|
|
||||||
self.file,
|
|
||||||
cost_item=self.file.by_id(self.cost_item),
|
|
||||||
)
|
|
||||||
contracted_cost_items = json.loads(props.contracted_cost_items)
|
|
||||||
if props.active_cost_item_index in contracted_cost_items:
|
|
||||||
contracted_cost_items.remove(props.active_cost_item_index)
|
|
||||||
props.contracted_cost_items = json.dumps(contracted_cost_items)
|
|
||||||
bpy.ops.bim.enable_editing_cost_items(cost_schedule=props.active_cost_schedule_id)
|
|
||||||
if props.active_cost_item_id == self.cost_item:
|
|
||||||
props.active_cost_item_id = 0
|
|
||||||
return {"FINISHED"}
|
|
||||||
|
|
||||||
|
|
||||||
class EnableEditingCostItem(bpy.types.Operator, tool.Ifc.Operator):
|
class EnableEditingCostItem(bpy.types.Operator, tool.Ifc.Operator):
|
||||||
bl_idname = "bim.enable_editing_cost_item"
|
bl_idname = "bim.enable_editing_cost_item_attributes"
|
||||||
bl_label = "Enable Editing Cost Item"
|
bl_label = "Enable Editing Cost Item"
|
||||||
bl_options = {"REGISTER", "UNDO"}
|
bl_options = {"REGISTER", "UNDO"}
|
||||||
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_attributes(tool.Cost, cost_item=tool.Ifc.get().by_id(self.cost_item))
|
||||||
props.cost_item_attributes.clear()
|
|
||||||
|
|
||||||
blenderbim.bim.helper.import_attributes2(tool.Ifc.get().by_id(self.cost_item), props.cost_item_attributes)
|
|
||||||
props.active_cost_item_id = self.cost_item
|
|
||||||
props.cost_item_editing_type = "ATTRIBUTES"
|
|
||||||
return {"FINISHED"}
|
|
||||||
|
|
||||||
|
|
||||||
class DisableEditingCostItem(bpy.types.Operator, tool.Ifc.Operator):
|
class DisableEditingCostItem(bpy.types.Operator, tool.Ifc.Operator):
|
||||||
@@ -266,8 +173,7 @@ class DisableEditingCostItem(bpy.types.Operator, tool.Ifc.Operator):
|
|||||||
bl_options = {"REGISTER", "UNDO"}
|
bl_options = {"REGISTER", "UNDO"}
|
||||||
|
|
||||||
def _execute(self, context):
|
def _execute(self, context):
|
||||||
context.scene.BIMCostProperties.active_cost_item_id = 0
|
core.disable_editing_cost_item(tool.Cost)
|
||||||
return {"FINISHED"}
|
|
||||||
|
|
||||||
|
|
||||||
class EditCostItem(bpy.types.Operator, tool.Ifc.Operator):
|
class EditCostItem(bpy.types.Operator, tool.Ifc.Operator):
|
||||||
@@ -276,16 +182,7 @@ class EditCostItem(bpy.types.Operator, tool.Ifc.Operator):
|
|||||||
bl_options = {"REGISTER", "UNDO"}
|
bl_options = {"REGISTER", "UNDO"}
|
||||||
|
|
||||||
def _execute(self, context):
|
def _execute(self, context):
|
||||||
props = context.scene.BIMCostProperties
|
core.edit_cost_item(tool.Ifc, tool.Cost)
|
||||||
attributes = blenderbim.bim.helper.export_attributes(props.cost_item_attributes)
|
|
||||||
self.file = IfcStore.get_file()
|
|
||||||
ifcopenshell.api.run(
|
|
||||||
"cost.edit_cost_item",
|
|
||||||
self.file,
|
|
||||||
**{"cost_item": self.file.by_id(props.active_cost_item_id), "attributes": attributes},
|
|
||||||
)
|
|
||||||
bpy.ops.bim.disable_editing_cost_item()
|
|
||||||
bpy.ops.bim.enable_editing_cost_items(cost_schedule=props.active_cost_schedule_id)
|
|
||||||
return {"FINISHED"}
|
return {"FINISHED"}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -57,7 +57,8 @@ class BIM_PT_cost_schedules(Panel):
|
|||||||
op = row.operator("bim.select_cost_schedule_products", icon="RESTRICT_SELECT_OFF", text="")
|
op = row.operator("bim.select_cost_schedule_products", icon="RESTRICT_SELECT_OFF", text="")
|
||||||
op.cost_schedule = cost_schedule["id"]
|
op.cost_schedule = cost_schedule["id"]
|
||||||
row.prop(self.props, "should_show_column_ui", text="", icon="SHORTDISPLAY")
|
row.prop(self.props, "should_show_column_ui", text="", icon="SHORTDISPLAY")
|
||||||
if self.props.is_editing == "COST_SCHEDULE":
|
row.operator("bim.export_cost_schedule", text="", icon="EXPORT").cost_schedule = cost_schedule["id"]
|
||||||
|
if self.props.is_editing == "COST_SCHEDULE_ATTRIBUTES":
|
||||||
row.operator("bim.edit_cost_schedule", text="", icon="CHECKMARK")
|
row.operator("bim.edit_cost_schedule", text="", icon="CHECKMARK")
|
||||||
elif self.props.is_editing == "COST_ITEMS":
|
elif self.props.is_editing == "COST_ITEMS":
|
||||||
row.operator("bim.add_summary_cost_item", text="", icon="ADD").cost_schedule = cost_schedule["id"]
|
row.operator("bim.add_summary_cost_item", text="", icon="ADD").cost_schedule = cost_schedule["id"]
|
||||||
@@ -67,12 +68,12 @@ class BIM_PT_cost_schedules(Panel):
|
|||||||
else:
|
else:
|
||||||
row.operator("bim.enable_editing_cost_items", text="", icon="OUTLINER").cost_schedule = cost_schedule["id"]
|
row.operator("bim.enable_editing_cost_items", text="", icon="OUTLINER").cost_schedule = cost_schedule["id"]
|
||||||
row.operator(
|
row.operator(
|
||||||
"bim.enable_editing_cost_schedule", text="", icon="GREASEPENCIL"
|
"bim.enable_editing_cost_schedule_attributes", text="", icon="GREASEPENCIL"
|
||||||
).cost_schedule = cost_schedule["id"]
|
).cost_schedule = cost_schedule["id"]
|
||||||
row.operator("bim.remove_cost_schedule", text="", icon="X").cost_schedule = cost_schedule["id"]
|
row.operator("bim.remove_cost_schedule", text="", icon="X").cost_schedule = cost_schedule["id"]
|
||||||
|
|
||||||
if self.props.active_cost_schedule_id == cost_schedule["id"]:
|
if self.props.active_cost_schedule_id == cost_schedule["id"]:
|
||||||
if self.props.is_editing == "COST_SCHEDULE":
|
if self.props.is_editing == "COST_SCHEDULE_ATTRIBUTES":
|
||||||
self.draw_editable_cost_schedule_ui()
|
self.draw_editable_cost_schedule_ui()
|
||||||
elif self.props.is_editing == "COST_ITEMS":
|
elif self.props.is_editing == "COST_ITEMS":
|
||||||
if self.props.should_show_column_ui:
|
if self.props.should_show_column_ui:
|
||||||
@@ -110,7 +111,7 @@ class BIM_PT_cost_schedules(Panel):
|
|||||||
row.operator("bim.edit_cost_item", text="", icon="CHECKMARK")
|
row.operator("bim.edit_cost_item", text="", icon="CHECKMARK")
|
||||||
row.operator("bim.disable_editing_cost_item", text="", icon="CANCEL")
|
row.operator("bim.disable_editing_cost_item", text="", icon="CANCEL")
|
||||||
else:
|
else:
|
||||||
op = row.operator("bim.enable_editing_cost_item", text="", icon="GREASEPENCIL")
|
op = row.operator("bim.enable_editing_cost_item_attributes", text="", icon="GREASEPENCIL")
|
||||||
op.cost_item = ifc_definition_id
|
op.cost_item = ifc_definition_id
|
||||||
|
|
||||||
row.operator("bim.remove_cost_item", text="", icon="X").cost_item = ifc_definition_id
|
row.operator("bim.remove_cost_item", text="", icon="X").cost_item = ifc_definition_id
|
||||||
@@ -237,9 +238,7 @@ class BIM_PT_cost_item_types(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]
|
cost_item = self.props.cost_items[self.props.active_cost_item_index]
|
||||||
|
|
||||||
grid = self.layout.grid_flow(columns=3, even_columns=True)
|
grid = self.layout.grid_flow(columns=3, even_columns=True)
|
||||||
|
|
||||||
# Column1
|
# Column1
|
||||||
|
|||||||
@@ -0,0 +1,65 @@
|
|||||||
|
def add_cost_schedule(ifc):
|
||||||
|
ifc.run("cost.add_cost_schedule")
|
||||||
|
|
||||||
|
def edit_cost_schedule(ifc, cost, cost_schedule):
|
||||||
|
attributes = cost.get_cost_schedule_attributes()
|
||||||
|
ifc.run("cost.edit_cost_schedule", cost_schedule=cost_schedule, attributes=attributes)
|
||||||
|
cost.disable_editing_cost_schedule()
|
||||||
|
|
||||||
|
def disable_editing_cost_schedule(cost):
|
||||||
|
cost.disable_editing_cost_schedule()
|
||||||
|
|
||||||
|
def remove_cost_schedule(ifc, cost_schedule):
|
||||||
|
ifc.run("cost.remove_cost_schedule", cost_schedule=cost_schedule)
|
||||||
|
|
||||||
|
def enable_editing_cost_schedule_attributes(cost, cost_schedule):
|
||||||
|
cost.enable_editing_cost_schedule_attributes(cost_schedule)
|
||||||
|
cost.load_cost_items()
|
||||||
|
cost.play_chaching_sound()
|
||||||
|
|
||||||
|
def enable_editing_cost_items(cost, cost_schedule):
|
||||||
|
cost.enable_editing_cost_items(cost_schedule)
|
||||||
|
cost.load_cost_items()
|
||||||
|
|
||||||
|
def add_summary_cost_item(ifc, cost, cost_schedule):
|
||||||
|
ifc.run("cost.add_cost_item", cost_schedule=cost_schedule)
|
||||||
|
cost.load_cost_items()
|
||||||
|
|
||||||
|
def add_cost_item(ifc, cost, cost_item):
|
||||||
|
ifc.run("cost.add_cost_item", cost_item=cost_item)
|
||||||
|
cost.load_cost_items()
|
||||||
|
# cost.enable_editing_cost_schedule_attributes(cost_schedule)
|
||||||
|
|
||||||
|
def expand_cost_item(cost, cost_item):
|
||||||
|
cost.expand_cost_item(cost_item)
|
||||||
|
cost.load_cost_items()
|
||||||
|
|
||||||
|
def expand_cost_items(cost):
|
||||||
|
cost.expand_cost_items()
|
||||||
|
cost.load_cost_items()
|
||||||
|
|
||||||
|
def contract_cost_item(cost, cost_item):
|
||||||
|
cost.contract_cost_item(cost_item)
|
||||||
|
cost.load_cost_items()
|
||||||
|
|
||||||
|
def contract_cost_items(cost):
|
||||||
|
cost.contract_cost_items()
|
||||||
|
cost.load_cost_items()
|
||||||
|
|
||||||
|
def remove_cost_item(ifc, cost, cost_item):
|
||||||
|
ifc.run("cost.remove_cost_item", cost_item=cost_item)
|
||||||
|
cost.clean_up_cost_item_tree(cost_item)
|
||||||
|
cost.load_cost_items()
|
||||||
|
|
||||||
|
def enable_editing_cost_item_attributes(cost, cost_item):
|
||||||
|
cost.enable_editing_cost_item_attributes(cost_item)
|
||||||
|
cost.load_cost_item_attributes(cost_item)
|
||||||
|
|
||||||
|
def disable_editing_cost_item(cost):
|
||||||
|
cost.disable_editing_cost_item()
|
||||||
|
|
||||||
|
def edit_cost_item(ifc, cost):
|
||||||
|
attributes = cost.get_cost_item_attributes()
|
||||||
|
ifc.run("cost.edit_cost_item", cost_item=cost.get_active_cost_item(), attributes=attributes)
|
||||||
|
cost.disable_editing_cost_item()
|
||||||
|
cost.load_cost_items()
|
||||||
@@ -125,6 +125,25 @@ class Context:
|
|||||||
def import_attributes(cls): pass
|
def import_attributes(cls): pass
|
||||||
def set_context(cls, context): pass
|
def set_context(cls, context): pass
|
||||||
|
|
||||||
|
@interface
|
||||||
|
class Cost:
|
||||||
|
def clean_up_cost_item_tree(cls, cost_item): pass
|
||||||
|
def contract_cost_item(cls, cost_item): pass
|
||||||
|
def contract_cost_items(cls): pass
|
||||||
|
def create_new_cost_item_li(cls, props, cost_item, level_index): pass
|
||||||
|
def disable_editing_cost_item(cls): pass
|
||||||
|
def disable_editing_cost_schedule(cls): pass
|
||||||
|
def enable_editing_cost_item_attributes(cls, cost_item): pass
|
||||||
|
def enable_editing_cost_items(cls, cost_schedule): pass
|
||||||
|
def enable_editing_cost_schedule_attributes(cls, cost_schedule): pass
|
||||||
|
def expand_cost_item(cls, cost_item): pass
|
||||||
|
def expand_cost_items(cls): pass
|
||||||
|
def get_active_cost_item(cls): pass
|
||||||
|
def get_cost_item_attributes(cls, cost_item): pass
|
||||||
|
def get_cost_schedule_attributes(cls): pass
|
||||||
|
def load_cost_items(cls): pass
|
||||||
|
def load_cost_item_attributes(cls): pass
|
||||||
|
def play_chaching_sound(cls): pass
|
||||||
|
|
||||||
@interface
|
@interface
|
||||||
class Debug:
|
class Debug:
|
||||||
|
|||||||
@@ -50,3 +50,4 @@ from blenderbim.tool.surveyor import Surveyor
|
|||||||
from blenderbim.tool.system import System
|
from blenderbim.tool.system import System
|
||||||
from blenderbim.tool.type import Type
|
from blenderbim.tool.type import Type
|
||||||
from blenderbim.tool.unit import Unit
|
from blenderbim.tool.unit import Unit
|
||||||
|
from blenderbim.tool.cost import Cost
|
||||||
@@ -0,0 +1,158 @@
|
|||||||
|
import os
|
||||||
|
import bpy
|
||||||
|
import blenderbim.tool as tool
|
||||||
|
import ifcopenshell.util.date
|
||||||
|
import blenderbim.bim.helper
|
||||||
|
import json
|
||||||
|
|
||||||
|
|
||||||
|
class Cost(blenderbim.core.tool.Cost):
|
||||||
|
@classmethod
|
||||||
|
def get_cost_schedule_attributes(cls):
|
||||||
|
props = bpy.context.scene.BIMCostProperties
|
||||||
|
return blenderbim.bim.helper.export_attributes(props.cost_schedule_attributes)
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def disable_editing_cost_schedule(cls):
|
||||||
|
bpy.context.scene.BIMCostProperties.active_cost_schedule_id = 0
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
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.is_editing = "COST_SCHEDULE_ATTRIBUTES"
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def load_cost_schedule_attributes(cls, cost_schedule):
|
||||||
|
props = bpy.context.scene.BIMCostProperties
|
||||||
|
props.cost_schedule_attributes.clear()
|
||||||
|
blenderbim.bim.helper.import_attributes(cost_schedule, props.cost_schedule_attributes)
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def play_chaching_sound(cls):
|
||||||
|
# TODO: make pitch higher as costs rise
|
||||||
|
try:
|
||||||
|
import aud
|
||||||
|
|
||||||
|
device = aud.Device()
|
||||||
|
# chaching.mp3 is by Lucish_ CC-BY-3.0 https://freesound.org/people/Lucish_/sounds/554841/
|
||||||
|
sound = aud.Sound(os.path.join(bpy.context.scene.BIMProperties.data_dir, "chaching.mp3"))
|
||||||
|
handle = device.play(sound)
|
||||||
|
sound_buffered = aud.Sound.buffer(sound)
|
||||||
|
handle_buffered = device.play(sound_buffered)
|
||||||
|
handle.stop()
|
||||||
|
handle_buffered.stop()
|
||||||
|
except:
|
||||||
|
pass # ah well
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def enable_editing_cost_items(cls, cost_schedule):
|
||||||
|
props = bpy.context.scene.BIMCostProperties
|
||||||
|
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)
|
||||||
|
props.cost_items.clear()
|
||||||
|
if not hasattr(cls, "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_item, 0)
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def create_new_cost_item_li(cls, props, cost_item, level_index):
|
||||||
|
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
|
||||||
|
def expand_cost_item(cls, cost_item):
|
||||||
|
props = bpy.context.scene.BIMCostProperties
|
||||||
|
cls.contracted_cost_items = json.loads(props.contracted_cost_items)
|
||||||
|
cls.contracted_cost_items.remove(cost_item.id())
|
||||||
|
props.contracted_cost_items = json.dumps(cls.contracted_cost_items)
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def expand_cost_items(cls):
|
||||||
|
props = bpy.context.scene.BIMCostProperties
|
||||||
|
cls.contracted_cost_items = json.loads(props.contracted_cost_items)
|
||||||
|
for cost_item in props.cost_items:
|
||||||
|
if cost_item.ifc_definition_id in cls.contracted_cost_items:
|
||||||
|
cls.contracted_cost_items.remove(cost_item.ifc_definition_id)
|
||||||
|
props.contracted_cost_items = json.dumps(cls.contracted_cost_items)
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def contract_cost_item(cls, cost_item):
|
||||||
|
props = bpy.context.scene.BIMCostProperties
|
||||||
|
cls.contracted_cost_items = json.loads(props.contracted_cost_items)
|
||||||
|
cls.contracted_cost_items.append(cost_item.id())
|
||||||
|
props.contracted_cost_items = json.dumps(cls.contracted_cost_items)
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def contract_cost_items(cls):
|
||||||
|
props = bpy.context.scene.BIMCostProperties
|
||||||
|
cls.contracted_cost_items = json.loads(props.contracted_cost_items)
|
||||||
|
for cost_item in props.cost_items:
|
||||||
|
if cost_item.ifc_definition_id not in cls.contracted_cost_items:
|
||||||
|
cls.contracted_cost_items.append(cost_item.ifc_definition_id)
|
||||||
|
props.contracted_cost_items = json.dumps(cls.contracted_cost_items)
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def clean_up_cost_item_tree(cls, cost_item):
|
||||||
|
props = bpy.context.scene.BIMCostProperties
|
||||||
|
cls.contracted_cost_items = json.loads(props.contracted_cost_items)
|
||||||
|
if props.active_cost_item_index in cls.contracted_cost_items:
|
||||||
|
cls.contracted_cost_items.remove(props.active_cost_item_index)
|
||||||
|
props.contracted_cost_items = json.dumps(cls.contracted_cost_items)
|
||||||
|
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
|
||||||
|
def enable_editing_cost_item_attributes(cls, cost_item):
|
||||||
|
bpy.context.scene.BIMCostProperties.active_cost_item_id = cost_item.id()
|
||||||
|
bpy.context.scene.BIMCostProperties.cost_item_editing_type = "ATTRIBUTES"
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def load_cost_item_attributes(cls, cost_item):
|
||||||
|
props = bpy.context.scene.BIMCostProperties
|
||||||
|
props.cost_item_attributes.clear()
|
||||||
|
blenderbim.bim.helper.import_attributes2(cost_item, props.cost_item_attributes)
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def disable_editing_cost_item(cls):
|
||||||
|
bpy.context.scene.BIMCostProperties.active_cost_item_id = 0
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def get_cost_item_attributes(cls):
|
||||||
|
props = bpy.context.scene.BIMCostProperties
|
||||||
|
return blenderbim.bim.helper.export_attributes(props.cost_item_attributes)
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def get_active_cost_item(cls):
|
||||||
|
if bpy.context.scene.BIMCostProperties.active_cost_item_id == 0:
|
||||||
|
return None
|
||||||
|
return tool.Ifc.get().by_id(bpy.context.scene.BIMCostProperties.active_cost_item_id)
|
||||||
@@ -10,14 +10,14 @@ Scenario: Enable editing cost schedule
|
|||||||
Given an empty IFC project
|
Given an empty IFC project
|
||||||
And I press "bim.add_cost_schedule"
|
And I press "bim.add_cost_schedule"
|
||||||
And the variable "cost_schedule" is "{ifc}.by_type('IfcCostSchedule')[0].id()"
|
And the variable "cost_schedule" is "{ifc}.by_type('IfcCostSchedule')[0].id()"
|
||||||
When I press "bim.enable_editing_cost_schedule(cost_schedule={cost_schedule})"
|
When I press "bim.enable_editing_cost_schedule_attributes(cost_schedule={cost_schedule})"
|
||||||
Then nothing happens
|
Then nothing happens
|
||||||
|
|
||||||
Scenario: Disable editing cost schedule
|
Scenario: Disable editing cost schedule
|
||||||
Given an empty IFC project
|
Given an empty IFC project
|
||||||
And I press "bim.add_cost_schedule"
|
And I press "bim.add_cost_schedule"
|
||||||
And the variable "cost_schedule" is "{ifc}.by_type('IfcCostSchedule')[0].id()"
|
And the variable "cost_schedule" is "{ifc}.by_type('IfcCostSchedule')[0].id()"
|
||||||
And I press "bim.enable_editing_cost_schedule(cost_schedule={cost_schedule})"
|
And I press "bim.enable_editing_cost_schedule_attributes(cost_schedule={cost_schedule})"
|
||||||
When I press "bim.disable_editing_cost_schedule"
|
When I press "bim.disable_editing_cost_schedule"
|
||||||
Then nothing happens
|
Then nothing happens
|
||||||
|
|
||||||
@@ -25,7 +25,7 @@ Scenario: Edit cost schedule
|
|||||||
Given an empty IFC project
|
Given an empty IFC project
|
||||||
And I press "bim.add_cost_schedule"
|
And I press "bim.add_cost_schedule"
|
||||||
And the variable "cost_schedule" is "{ifc}.by_type('IfcCostSchedule')[0].id()"
|
And the variable "cost_schedule" is "{ifc}.by_type('IfcCostSchedule')[0].id()"
|
||||||
And I press "bim.enable_editing_cost_schedule(cost_schedule={cost_schedule})"
|
And I press "bim.enable_editing_cost_schedule_attributes(cost_schedule={cost_schedule})"
|
||||||
When I press "bim.edit_cost_schedule"
|
When I press "bim.edit_cost_schedule"
|
||||||
Then nothing happens
|
Then nothing happens
|
||||||
|
|
||||||
@@ -76,7 +76,7 @@ Scenario: Enable editing cost item
|
|||||||
And I press "bim.enable_editing_cost_items(cost_schedule={cost_schedule})"
|
And I press "bim.enable_editing_cost_items(cost_schedule={cost_schedule})"
|
||||||
And I press "bim.add_summary_cost_item(cost_schedule={cost_schedule})"
|
And I press "bim.add_summary_cost_item(cost_schedule={cost_schedule})"
|
||||||
And the variable "cost_item" is "{ifc}.by_type('IfcCostItem')[0].id()"
|
And the variable "cost_item" is "{ifc}.by_type('IfcCostItem')[0].id()"
|
||||||
When I press "bim.enable_editing_cost_item(cost_item={cost_item})"
|
When I press "bim.enable_editing_cost_item_attributes(cost_item={cost_item})"
|
||||||
Then nothing happens
|
Then nothing happens
|
||||||
|
|
||||||
Scenario: Disable editing cost item
|
Scenario: Disable editing cost item
|
||||||
@@ -86,7 +86,7 @@ Scenario: Disable editing cost item
|
|||||||
And I press "bim.enable_editing_cost_items(cost_schedule={cost_schedule})"
|
And I press "bim.enable_editing_cost_items(cost_schedule={cost_schedule})"
|
||||||
And I press "bim.add_summary_cost_item(cost_schedule={cost_schedule})"
|
And I press "bim.add_summary_cost_item(cost_schedule={cost_schedule})"
|
||||||
And the variable "cost_item" is "{ifc}.by_type('IfcCostItem')[0].id()"
|
And the variable "cost_item" is "{ifc}.by_type('IfcCostItem')[0].id()"
|
||||||
And I press "bim.enable_editing_cost_item(cost_item={cost_item})"
|
And I press "bim.enable_editing_cost_item_attributes(cost_item={cost_item})"
|
||||||
When I press "bim.disable_editing_cost_item"
|
When I press "bim.disable_editing_cost_item"
|
||||||
Then nothing happens
|
Then nothing happens
|
||||||
|
|
||||||
@@ -97,7 +97,7 @@ Scenario: Edit cost item
|
|||||||
And I press "bim.enable_editing_cost_items(cost_schedule={cost_schedule})"
|
And I press "bim.enable_editing_cost_items(cost_schedule={cost_schedule})"
|
||||||
And I press "bim.add_summary_cost_item(cost_schedule={cost_schedule})"
|
And I press "bim.add_summary_cost_item(cost_schedule={cost_schedule})"
|
||||||
And the variable "cost_item" is "{ifc}.by_type('IfcCostItem')[0].id()"
|
And the variable "cost_item" is "{ifc}.by_type('IfcCostItem')[0].id()"
|
||||||
And I press "bim.enable_editing_cost_item(cost_item={cost_item})"
|
And I press "bim.enable_editing_cost_item_attributes(cost_item={cost_item})"
|
||||||
When I press "bim.edit_cost_item"
|
When I press "bim.edit_cost_item"
|
||||||
Then nothing happens
|
Then nothing happens
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user