mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-08-10 01:41:57 +00:00
BBIM 4D features & fixes:
- feature to re-order tasks - fixes for task sorting - further workSchedule UI/UX improvements - forgotten bits and bobs
This commit is contained in:
@@ -97,6 +97,7 @@ classes = (
|
||||
operator.RemoveWorkPlan,
|
||||
operator.RemoveWorkSchedule,
|
||||
operator.RemoveWorkTime,
|
||||
operator.ReorderTask,
|
||||
operator.SelectTaskRelatedProducts,
|
||||
operator.SelectTaskRelatedInputs,
|
||||
operator.SelectWorkScheduleProducts,
|
||||
|
||||
@@ -223,6 +223,9 @@ class SequenceData:
|
||||
if rel.is_a("IfcRelAssignsToControl") and rel.RelatingControl:
|
||||
if rel.RelatingControl.is_a("IfcWorkCalendar"):
|
||||
data["HasAssignmentsWorkCalendar"].append(rel.RelatingControl.id())
|
||||
data["NestingIndex"] = None
|
||||
for rel in task.Nests or []:
|
||||
data["NestingIndex"] = rel.RelatedObjects.index(task)
|
||||
cls.data["tasks"][task.id()] = data
|
||||
|
||||
@classmethod
|
||||
|
||||
@@ -275,13 +275,13 @@ class EditTaskTime(bpy.types.Operator, tool.Ifc.Operator):
|
||||
|
||||
|
||||
class EnableEditingTask(bpy.types.Operator):
|
||||
bl_idname = "bim.enable_editing_task"
|
||||
bl_label = "Enable Editing Task"
|
||||
bl_idname = "bim.enable_editing_task_attributes"
|
||||
bl_label = "Enable Editing Task Attributes"
|
||||
bl_options = {"REGISTER", "UNDO"}
|
||||
task: bpy.props.IntProperty()
|
||||
|
||||
def execute(self, context):
|
||||
core.enable_editing_task(tool.Sequence, task=tool.Ifc.get().by_id(self.task))
|
||||
core.enable_editing_task_attributes(tool.Sequence, task=tool.Ifc.get().by_id(self.task))
|
||||
return {"FINISHED"}
|
||||
|
||||
|
||||
@@ -1295,7 +1295,7 @@ class CopyTask(bpy.types.Operator, tool.Ifc.Operator):
|
||||
|
||||
|
||||
class LoadProductTasks(bpy.types.Operator):
|
||||
bl_idname = "bim.load_product_tasks"
|
||||
bl_idname = "bim.load_product_related_tasks"
|
||||
bl_label = "Load Product Tasks"
|
||||
bl_options = {"REGISTER", "UNDO"}
|
||||
|
||||
@@ -1310,7 +1310,7 @@ class LoadProductTasks(bpy.types.Operator):
|
||||
return True
|
||||
|
||||
def execute(self, context):
|
||||
core.load_product_tasks(
|
||||
core.load_product_related_tasks(
|
||||
tool.Sequence, product=tool.Ifc.get().by_id(context.active_object.BIMObjectProperties.ifc_definition_id)
|
||||
)
|
||||
return {"FINISHED"}
|
||||
@@ -1355,3 +1355,18 @@ class SelectUnassignedWorkScheduleProducts(bpy.types.Operator):
|
||||
if isinstance(r, str):
|
||||
self.report({"WARNING"}, r)
|
||||
return {"FINISHED"}
|
||||
|
||||
|
||||
class ReorderTask(bpy.types.Operator, tool.Ifc.Operator):
|
||||
bl_idname = "bim.reorder_task_nesting"
|
||||
bl_label = "Reorder Nesting"
|
||||
bl_options = {"REGISTER", "UNDO"}
|
||||
new_index: bpy.props.IntProperty()
|
||||
task: bpy.props.IntProperty()
|
||||
|
||||
def _execute(self, context):
|
||||
r = core.reorder_task_nesting(
|
||||
tool.Ifc, tool.Sequence, task=tool.Ifc.get().by_id(self.task), new_index=self.new_index
|
||||
)
|
||||
if isinstance(r, str):
|
||||
self.report({"WARNING"}, r)
|
||||
|
||||
@@ -284,9 +284,14 @@ def update_color_progress(self, context):
|
||||
color[1] = color_progress.g
|
||||
color[2] = color_progress.b
|
||||
|
||||
|
||||
def update_sort_reversed(self, context):
|
||||
if context.scene.BIMWorkScheduleProperties.active_work_schedule_id:
|
||||
core.create_task_tree(tool.Sequence, work_schedule=tool.Ifc.get().by_id(context.scene.BIMWorkScheduleProperties.active_work_schedule_id))
|
||||
core.load_task_tree(
|
||||
tool.Sequence,
|
||||
work_schedule=tool.Ifc.get().by_id(context.scene.BIMWorkScheduleProperties.active_work_schedule_id),
|
||||
)
|
||||
|
||||
|
||||
class Task(PropertyGroup):
|
||||
name: StringProperty(name="Name", update=updateTaskName)
|
||||
@@ -359,7 +364,8 @@ class BIMWorkScheduleProperties(PropertyGroup):
|
||||
active_task_id: IntProperty(name="Active Task Id")
|
||||
task_attributes: CollectionProperty(name="Task Attributes", type=Attribute)
|
||||
should_show_visualisation_ui: BoolProperty(name="Should Show Visualisation UI", default=False)
|
||||
should_show_bar_visual_option: BoolProperty(name="Add to task bar", default=False)
|
||||
should_show_task_bar_selection: BoolProperty(name="Add to task bar", default=False)
|
||||
should_show_snapshot_ui: BoolProperty(name="Should Show Snapshot UI", default=False)
|
||||
should_show_column_ui: BoolProperty(name="Should Show Column UI", default=False)
|
||||
columns: CollectionProperty(name="Columns", type=Attribute)
|
||||
active_column_index: IntProperty(name="Active Column Index")
|
||||
@@ -417,6 +423,8 @@ class BIMWorkScheduleProperties(PropertyGroup):
|
||||
product_output_tasks: CollectionProperty(name="Product Task Outputs", type=TaskProduct)
|
||||
active_product_output_task_index: IntProperty(name="Active Product Output Task Index")
|
||||
active_product_input_task_index: IntProperty(name="Active Product Input Task Index")
|
||||
enable_reorder: BoolProperty(name="Enable Reorder", default=False)
|
||||
show_task_operators: BoolProperty(name="Show Task Options", default=True)
|
||||
|
||||
|
||||
class BIMTaskTreeProperties(PropertyGroup):
|
||||
|
||||
@@ -170,7 +170,9 @@ class BIM_PT_work_schedules(Panel):
|
||||
row1 = col.row(align=True)
|
||||
row1.alignment = "RIGHT"
|
||||
row1.prop(self.props, "should_show_column_ui", text="Schedule Columns", icon="SHORTDISPLAY")
|
||||
row1.prop(self.props, "should_show_visualisation_ui", text="Animation Options", icon="CAMERA_STEREO")
|
||||
row2 = col.row(align=True)
|
||||
row2.prop(self.props, "should_show_visualisation_ui", text="Animation Options", icon="CAMERA_STEREO")
|
||||
row2.prop(self.props, "should_show_snapshot_ui", text="Snapshot Options", icon="CAMERA_STEREO")
|
||||
row.operator("bim.disable_editing_work_schedule", text="Disable editing", icon="CANCEL")
|
||||
else:
|
||||
row.operator(
|
||||
@@ -189,6 +191,8 @@ class BIM_PT_work_schedules(Panel):
|
||||
self.draw_column_ui()
|
||||
if self.props.should_show_visualisation_ui:
|
||||
self.draw_visualisation_ui()
|
||||
if self.props.should_show_snapshot_ui:
|
||||
self.draw_snapshot_ui()
|
||||
self.draw_editable_task_ui(work_schedule_id)
|
||||
|
||||
def draw_task_operators(self):
|
||||
@@ -206,14 +210,23 @@ class BIM_PT_work_schedules(Panel):
|
||||
row.operator("bim.edit_task", text="", icon="CHECKMARK")
|
||||
row.operator("bim.disable_editing_task", text="", icon="CANCEL")
|
||||
else:
|
||||
row.prop(self.props, "should_show_bar_visual_option", text="", icon="NLA_PUSHDOWN")
|
||||
row.operator("bim.enable_editing_task_sequence", text="", icon="TRACKING").task = ifc_definition_id
|
||||
row.operator("bim.enable_editing_task_time", text="", icon="TIME").task = ifc_definition_id
|
||||
row.operator("bim.enable_editing_task_calendar", text="", icon="VIEW_ORTHO").task = ifc_definition_id
|
||||
row.operator("bim.enable_editing_task", text="", icon="GREASEPENCIL").task = ifc_definition_id
|
||||
row.operator("bim.add_task", text="", icon="ADD").task = ifc_definition_id
|
||||
row.operator("bim.duplicate_task", text="", icon="DUPLICATE").task = ifc_definition_id
|
||||
row.operator("bim.remove_task", text="", icon="X").task = ifc_definition_id
|
||||
row.prop(self.props, "show_task_operators", text="Edit", icon="GREASEPENCIL")
|
||||
if self.props.show_task_operators:
|
||||
row2 = self.layout.row(align=True)
|
||||
row2.alignment = "RIGHT"
|
||||
|
||||
row2.prop(self.props, "enable_reorder", text="", icon="SORTALPHA")
|
||||
row2.operator("bim.enable_editing_task_sequence", text="", icon="TRACKING").task = ifc_definition_id
|
||||
row2.operator("bim.enable_editing_task_time", text="", icon="TIME").task = ifc_definition_id
|
||||
row2.operator(
|
||||
"bim.enable_editing_task_calendar", text="", icon="VIEW_ORTHO"
|
||||
).task = ifc_definition_id
|
||||
row2.operator(
|
||||
"bim.enable_editing_task_attributes", text="", icon="GREASEPENCIL"
|
||||
).task = ifc_definition_id
|
||||
row.operator("bim.add_task", text="Add", icon="ADD").task = ifc_definition_id
|
||||
row.operator("bim.duplicate_task", text="Copy", icon="DUPLICATE").task = ifc_definition_id
|
||||
row.operator("bim.remove_task", text="Delete", icon="X").task = ifc_definition_id
|
||||
|
||||
def draw_column_ui(self):
|
||||
row = self.layout.row()
|
||||
@@ -281,26 +294,35 @@ class BIM_PT_work_schedules(Panel):
|
||||
row.prop(self.animation_props, "should_show_task_bar_options", text="Task Bar", icon="NLA_PUSHDOWN")
|
||||
if self.animation_props.should_show_task_bar_options:
|
||||
row = self.layout.row()
|
||||
row.operator("bim.add_task_bars", text="Add Bar Visual", icon="NLA_PUSHDOWN")
|
||||
row.label(text="Task Bar Options", icon="NLA_PUSHDOWN")
|
||||
row.alignment = "LEFT"
|
||||
row = self.layout.row(align=True)
|
||||
row.prop(self.props, "should_show_task_bar_selection", text="Enable Selection", icon="NLA_PUSHDOWN")
|
||||
row.operator("bim.add_task_bars", text="Generate bars", icon="NLA_PUSHDOWN")
|
||||
|
||||
grid = self.layout.grid_flow(columns=2, even_columns=True)
|
||||
# Column1
|
||||
col = grid.column()
|
||||
row1 = col.row(align=True)
|
||||
row1.label(text="Bar Colors", icon="NLA_PUSHDOWN")
|
||||
|
||||
row2 = col.row(align=True)
|
||||
row2.prop(self.animation_props, "color_progress")
|
||||
row = col.row(align=True)
|
||||
row.prop(self.animation_props, "color_progress")
|
||||
|
||||
row3 = col.row(align=True)
|
||||
row3.prop(self.animation_props, "color_full")
|
||||
row = col.row(align=True)
|
||||
row.prop(self.animation_props, "color_full")
|
||||
|
||||
if self.animation_props.is_editing:
|
||||
self.draw_visualisation_settings_ui()
|
||||
|
||||
row = self.layout.row()
|
||||
row = self.layout.row(align=True)
|
||||
op = row.operator("bim.visualise_work_schedule_date_range", text="Create Animation", icon="OUTLINER_OB_CAMERA")
|
||||
op.work_schedule = self.props.active_work_schedule_id
|
||||
|
||||
def draw_snapshot_ui(self):
|
||||
row = self.layout.row(align=True)
|
||||
row.label(text="Create Construction Snapshot:")
|
||||
row = self.layout.row(align=True)
|
||||
op = row.operator("bim.datepicker", text=self.props.visualisation_start or "Date", icon="REW")
|
||||
op.target_prop = "BIMWorkScheduleProperties.visualisation_start"
|
||||
op = row.operator("bim.visualise_work_schedule_date", text="Create SnapShot", icon="RESTRICT_RENDER_OFF")
|
||||
op.work_schedule = self.props.active_work_schedule_id
|
||||
|
||||
@@ -572,7 +594,7 @@ class BIM_UL_task_resources(UIList):
|
||||
if item:
|
||||
row = layout.row(align=True)
|
||||
row.prop(item, "name", emboss=False, text="")
|
||||
row.prop(item, "schedule_usage", emboss=False, text="")
|
||||
row.label(text=str(item.schedule_usage))
|
||||
|
||||
|
||||
class BIM_UL_animation_colors(UIList):
|
||||
@@ -636,7 +658,7 @@ class BIM_UL_tasks(UIList):
|
||||
text="",
|
||||
emboss=False,
|
||||
)
|
||||
if self.props.should_show_bar_visual_option:
|
||||
if self.props.should_show_task_bar_selection:
|
||||
row.prop(
|
||||
item,
|
||||
"has_bar_visual",
|
||||
@@ -644,6 +666,8 @@ class BIM_UL_tasks(UIList):
|
||||
text="",
|
||||
emboss=False,
|
||||
)
|
||||
if self.props.enable_reorder:
|
||||
self.draw_order_operator(row, item.ifc_definition_id)
|
||||
if self.props.active_task_id:
|
||||
if self.props.editing_task_type == "SEQUENCE" and self.props.active_task_id != item.ifc_definition_id:
|
||||
if item.is_predecessor:
|
||||
@@ -658,6 +682,18 @@ class BIM_UL_tasks(UIList):
|
||||
op = row.operator("bim.assign_successor", text="", icon="TRACKING_FORWARDS", emboss=False)
|
||||
op.task = item.ifc_definition_id
|
||||
|
||||
def draw_order_operator(self, row, ifc_definition_id):
|
||||
task = SequenceData.data["tasks"][ifc_definition_id]
|
||||
if task["NestingIndex"] is not None:
|
||||
if task["NestingIndex"] == 0:
|
||||
op = row.operator("bim.reorder_task_nesting", icon="TRIA_DOWN", text="")
|
||||
op.task = ifc_definition_id
|
||||
op.new_index = task["NestingIndex"] + 1
|
||||
elif task["NestingIndex"] > 0:
|
||||
op = row.operator("bim.reorder_task_nesting", icon="TRIA_UP", text="")
|
||||
op.task = ifc_definition_id
|
||||
op.new_index = task["NestingIndex"] - 1
|
||||
|
||||
def draw_hierarchy(self, row, item):
|
||||
for i in range(0, item.level_index):
|
||||
row.label(text="", icon="BLANK1")
|
||||
@@ -878,7 +914,7 @@ class BIM_PT_4D_Tools(Panel):
|
||||
def draw(self, context):
|
||||
self.props = context.scene.BIMWorkScheduleProperties
|
||||
row = self.layout.row()
|
||||
row.operator("bim.load_product_tasks", text="Load Tasks", icon="FILE_REFRESH")
|
||||
row.operator("bim.load_product_related_tasks", text="Load Tasks", icon="FILE_REFRESH")
|
||||
|
||||
grid = self.layout.grid_flow(columns=2, even_columns=True)
|
||||
col1 = grid.column()
|
||||
|
||||
@@ -170,3 +170,15 @@ def unassign_resource(ifc, spatial, resource=None, products=None):
|
||||
products = spatial.get_selected_products()
|
||||
for product in products:
|
||||
ifc.run("resource.unassign_resource", relating_resource=resource, related_object=product)
|
||||
|
||||
|
||||
def edit_productivity_pset(ifc, resource_tool):
|
||||
resource = resource_tool.get_highlighted_resource()
|
||||
if resource is None:
|
||||
return
|
||||
productivity = resource_tool.get_productivity(resource)
|
||||
if productivity:
|
||||
pset = ifc.get().by_id(productivity["id"])
|
||||
else:
|
||||
pset = ifc.run("pset.add_pset", product=resource, name="EPset_Productivity")
|
||||
ifc.run("pset.edit_pset", pset=pset, properties=resource_tool.get_productivity_attributes())
|
||||
|
||||
@@ -74,47 +74,47 @@ def enable_editing_work_schedule(sequence, work_schedule=None):
|
||||
|
||||
def enable_editing_work_schedule_tasks(sequence, work_schedule=None):
|
||||
sequence.enable_editing_work_schedule_tasks(work_schedule)
|
||||
sequence.create_task_tree(work_schedule)
|
||||
sequence.load_task_tree(work_schedule)
|
||||
sequence.load_task_properties()
|
||||
|
||||
|
||||
def create_task_tree(sequence, work_schedule):
|
||||
sequence.create_task_tree(work_schedule)
|
||||
def load_task_tree(sequence, work_schedule):
|
||||
sequence.load_task_tree(work_schedule)
|
||||
sequence.load_task_properties()
|
||||
|
||||
|
||||
def expand_task(sequence, task=None):
|
||||
sequence.expand_task(task)
|
||||
work_schedule = sequence.get_active_work_schedule()
|
||||
sequence.create_task_tree(work_schedule)
|
||||
sequence.load_task_tree(work_schedule)
|
||||
sequence.load_task_properties()
|
||||
|
||||
|
||||
def expand_all_tasks(sequence):
|
||||
sequence.expand_all_tasks()
|
||||
work_schedule = sequence.get_active_work_schedule()
|
||||
sequence.create_task_tree(work_schedule)
|
||||
sequence.load_task_tree(work_schedule)
|
||||
sequence.load_task_properties()
|
||||
|
||||
|
||||
def contract_task(sequence, task=None):
|
||||
sequence.contract_task(task)
|
||||
work_schedule = sequence.get_active_work_schedule()
|
||||
sequence.create_task_tree(work_schedule)
|
||||
sequence.load_task_tree(work_schedule)
|
||||
sequence.load_task_properties()
|
||||
|
||||
|
||||
def contract_all_tasks(sequence):
|
||||
sequence.contract_all_tasks()
|
||||
work_schedule = sequence.get_active_work_schedule()
|
||||
sequence.create_task_tree(work_schedule)
|
||||
sequence.load_task_tree(work_schedule)
|
||||
sequence.load_task_properties()
|
||||
|
||||
|
||||
def remove_task(ifc, sequence, task=None):
|
||||
ifc.run("sequence.remove_task", task=task)
|
||||
work_schedule = sequence.get_active_work_schedule()
|
||||
sequence.create_task_tree(work_schedule)
|
||||
sequence.load_task_tree(work_schedule)
|
||||
sequence.load_task_properties()
|
||||
sequence.disable_selecting_deleted_task()
|
||||
|
||||
@@ -129,21 +129,24 @@ def disable_editing_work_schedule(sequence):
|
||||
|
||||
def add_summary_task(ifc, sequence, work_schedule=None):
|
||||
ifc.run("sequence.add_task", work_schedule=work_schedule)
|
||||
sequence.create_task_tree(work_schedule)
|
||||
sequence.load_task_tree(work_schedule)
|
||||
sequence.load_task_properties()
|
||||
|
||||
|
||||
def add_task(ifc, sequence, parent_task=None):
|
||||
ifc.run("sequence.add_task", parent_task=parent_task)
|
||||
work_schedule = sequence.get_active_work_schedule()
|
||||
sequence.create_task_tree(work_schedule)
|
||||
sequence.load_task_tree(work_schedule)
|
||||
sequence.load_task_properties()
|
||||
|
||||
|
||||
def enable_editing_task(sequence, task=None):
|
||||
sequence.load_task_attributes(task)
|
||||
sequence.enable_editing_task(task)
|
||||
|
||||
def enable_editing_task_attributes(sequence, task=None):
|
||||
sequence.load_task_attributes(task)
|
||||
sequence.enable_editing_task_attributes(task)
|
||||
|
||||
|
||||
def edit_task(ifc, sequence, task=None):
|
||||
attributes = sequence.get_task_attributes()
|
||||
@@ -165,7 +168,7 @@ def copy_task_attribute(ifc, sequence, attribute_name=None):
|
||||
def duplicate_task(ifc, sequence, task=None):
|
||||
ifc.run("sequence.duplicate_task", task=task)
|
||||
work_schedule = sequence.get_active_work_schedule()
|
||||
sequence.create_task_tree(work_schedule)
|
||||
sequence.load_task_tree(work_schedule)
|
||||
sequence.load_task_properties()
|
||||
|
||||
|
||||
@@ -464,7 +467,7 @@ def calculate_task_duration(ifc, sequence, task=None):
|
||||
ifc.run("sequence.calculate_task_duration", task=task)
|
||||
work_schedule = sequence.get_active_work_schedule()
|
||||
if work_schedule:
|
||||
sequence.create_task_tree(work_schedule)
|
||||
sequence.load_task_tree(work_schedule)
|
||||
sequence.load_task_properties()
|
||||
|
||||
|
||||
@@ -473,6 +476,8 @@ def highlight_task(sequence, task=None):
|
||||
is_work_schedule_active = sequence.is_work_schedule_active(work_schedule)
|
||||
if is_work_schedule_active:
|
||||
sequence.highlight_task(task)
|
||||
else:
|
||||
return "Work schedule is not active"
|
||||
|
||||
|
||||
def highlight_product_related_task(sequence, spatial, product_type=None):
|
||||
@@ -537,5 +542,17 @@ def generate_gantt_chart(sequence, work_schedule):
|
||||
sequence.generate_gantt_browser_chart(json)
|
||||
|
||||
|
||||
def load_product_tasks(sequence, product=None):
|
||||
sequence.load_product_tasks(product)
|
||||
def load_product_related_tasks(sequence, product=None):
|
||||
sequence.load_product_related_tasks(product)
|
||||
|
||||
|
||||
def reorder_task_nesting(ifc, sequence, task, new_index):
|
||||
is_sorting_enabled = sequence.is_sorting_enabled()
|
||||
is_sort_reversed = sequence.is_sort_reversed()
|
||||
if is_sorting_enabled or is_sort_reversed:
|
||||
return "Remove manual sorting"
|
||||
else:
|
||||
ifc.run("nest.reorder_nesting", item= task, new_index= new_index)
|
||||
work_schedule= sequence.get_active_work_schedule()
|
||||
sequence.load_task_tree(work_schedule)
|
||||
sequence.load_task_properties()
|
||||
@@ -562,32 +562,37 @@ class Qto:
|
||||
|
||||
@interface
|
||||
class Resource:
|
||||
def load_resources(cls): pass
|
||||
def load_resource_properties(cls): pass
|
||||
def clear_productivity_data(cls, props): pass
|
||||
def contract_resource(cls, resource): pass
|
||||
def disable_editing_resource_cost_value(cls): pass
|
||||
def disable_editing_resource_quantity(cls): pass
|
||||
def disable_editing_resource(cls): pass
|
||||
def disable_resource_editing_ui(cls): pass
|
||||
def load_resource_attributes(cls, resource): pass
|
||||
def enable_editing_resource(cls, resource): pass
|
||||
def get_resource_attributes(cls): pass
|
||||
def enable_editing_resource_time(cls, resource): pass
|
||||
def get_resource_time(cls, resource): pass
|
||||
def load_resource_time_attributes(cls, resource_time): pass
|
||||
def get_resource_time_attributes(cls): pass
|
||||
def enable_editing_resource_costs(cls, resource): pass
|
||||
def disable_editing_resource_cost_value(cls): pass
|
||||
def enable_editing_resource_cost_value_formula(cls, cost_value): pass
|
||||
def load_cost_value_attributes(cls, cost_value): pass
|
||||
def edit_productivity_pset(cls, resource, attributes): pass
|
||||
def enable_editing_cost_value_attributes(cls, cost_value): pass
|
||||
def get_resource_cost_value_formula(cls): pass
|
||||
def get_resource_cost_value_attributes(cls): pass
|
||||
def enable_editing_resource_base_quantity(cls, resource): pass
|
||||
def enable_editing_resource_cost_value_formula(cls, cost_value): pass
|
||||
def enable_editing_resource_costs(cls, resource): pass
|
||||
def enable_editing_resource_quantity(cls, resource_quantity): pass
|
||||
def disable_editing_resource_quantity(cls): pass
|
||||
def get_resource_quantity_attributes(cls): pass
|
||||
def enable_editing_resource_time(cls, resource): pass
|
||||
def enable_editing_resource(cls, resource): pass
|
||||
def expand_resource(cls, resource): pass
|
||||
def contract_resource(cls, resource): pass
|
||||
def get_highlighted_resource(cls): pass
|
||||
def get_productivity_attributes(cls): pass
|
||||
def get_productivity(cls, resource, should_inherit): pass
|
||||
def get_resource_attributes(cls): pass
|
||||
def get_resource_cost_value_attributes(cls): pass
|
||||
def get_resource_cost_value_formula(cls): pass
|
||||
def get_resource_quantity_attributes(cls): pass
|
||||
def get_resource_time_attributes(cls): pass
|
||||
def get_resource_time(cls, resource): pass
|
||||
def import_resources(cls, file_path): pass
|
||||
|
||||
def load_cost_value_attributes(cls, cost_value): pass
|
||||
def load_productivity_data(cls): pass
|
||||
def load_resource_attributes(cls, resource): pass
|
||||
def load_resource_properties(cls): pass
|
||||
def load_resource_time_attributes(cls, resource_time): pass
|
||||
def load_resources(cls): pass
|
||||
|
||||
@interface
|
||||
class Root:
|
||||
@@ -635,7 +640,7 @@ class Sequence:
|
||||
def contract_task(cls, task): pass
|
||||
def create_bars(cls, tasks): pass
|
||||
def create_new_task_json(cls, task, json, type_map=None): pass
|
||||
def create_task_tree(cls, work_schedule): pass
|
||||
def load_task_tree(cls, work_schedule): pass
|
||||
def create_tasks_json(cls, work_schedule=None): pass
|
||||
def disable_editing_rel_sequence(cls): pass
|
||||
def disable_editing_task_animation_colors(cls): pass
|
||||
@@ -653,7 +658,7 @@ class Sequence:
|
||||
def enable_editing_task_calendar(cls, task): pass
|
||||
def enable_editing_task_sequence(cls, task): pass
|
||||
def enable_editing_task_time(cls, task): pass
|
||||
def enable_editing_task(cls, task): pass
|
||||
def enable_editing_task_attributes(cls, task): pass
|
||||
def enable_editing_work_calendar_times(cls, work_calendar): pass
|
||||
def enable_editing_work_calendar(cls, work_calendar): pass
|
||||
def enable_editing_work_plan_schedules(cls, work_plan): pass
|
||||
@@ -700,7 +705,7 @@ class Sequence:
|
||||
def highlight_task(cls, task): pass
|
||||
def is_work_schedule_active(cls, work_schedule): pass
|
||||
def load_lag_time_attributes(cls, lag_time): pass
|
||||
def load_product_tasks(cls, product): pass
|
||||
def load_product_related_tasks(cls, product): pass
|
||||
def load_rel_sequence_attributes(cls, rel_sequence): pass
|
||||
def load_resources(cls): pass
|
||||
def load_task_animation_colors(cls): pass
|
||||
|
||||
@@ -30,6 +30,8 @@ from datetime import datetime
|
||||
from dateutil import parser
|
||||
import ifcopenshell.util.date as ifcdateutils
|
||||
import ifcopenshell.util.cost
|
||||
import ifcopenshell.util.resource
|
||||
import blenderbim.bim.schema
|
||||
|
||||
|
||||
class Resource(blenderbim.core.tool.Resource):
|
||||
@@ -58,6 +60,7 @@ class Resource(blenderbim.core.tool.Resource):
|
||||
if not resource.HasContext:
|
||||
continue
|
||||
create_new_resource_li(resource, 0)
|
||||
cls.load_productivity_data()
|
||||
props.is_editing = True
|
||||
|
||||
@classmethod
|
||||
@@ -299,8 +302,83 @@ class Resource(blenderbim.core.tool.Resource):
|
||||
|
||||
@classmethod
|
||||
def get_highlighted_resource(cls):
|
||||
return tool.Ifc.get().by_id(
|
||||
bpy.context.scene.BIMResourceTreeProperties.resources[
|
||||
bpy.context.scene.BIMResourceProperties.active_resource_index
|
||||
resources = len(bpy.context.scene.BIMResourceTreeProperties.resources)
|
||||
if resources and resources > bpy.context.scene.BIMResourceProperties.active_resource_index:
|
||||
return tool.Ifc.get().by_id(
|
||||
bpy.context.scene.BIMResourceTreeProperties.resources[
|
||||
bpy.context.scene.BIMResourceProperties.active_resource_index
|
||||
].ifc_definition_id
|
||||
)
|
||||
)
|
||||
|
||||
@classmethod
|
||||
def clear_productivity_data(cls, props):
|
||||
for duration_prop in props.quantity_consumed or []:
|
||||
if duration_prop.name == "BaseQuantityConsumed":
|
||||
duration_prop.years = 0
|
||||
duration_prop.months = 0
|
||||
duration_prop.days = 0
|
||||
duration_prop.hours = 0
|
||||
duration_prop.minutes = 0
|
||||
duration_prop.seconds = 0
|
||||
props.quantity_produced = 0
|
||||
props.quantity_produced_name = ""
|
||||
|
||||
@classmethod
|
||||
def load_productivity_data(cls):
|
||||
duration_props = None
|
||||
for collection_prop in bpy.context.scene.BIMResourceProductivity.quantity_consumed:
|
||||
duration_props = collection_prop if collection_prop.name == "BaseQuantityConsumed" else None
|
||||
break
|
||||
if not duration_props:
|
||||
duration_props = bpy.context.scene.BIMResourceProductivity.quantity_consumed.add()
|
||||
duration_props.name = "BaseQuantityConsumed"
|
||||
cls.clear_productivity_data(bpy.context.scene.BIMResourceProductivity)
|
||||
current_resource = tool.Resource.get_highlighted_resource()
|
||||
if current_resource:
|
||||
productivity = cls.get_productivity(current_resource)
|
||||
print("Resource:", current_resource, "productivity", productivity)
|
||||
if productivity:
|
||||
bpy.context.scene.BIMResourceProductivity.quantity_produced = (
|
||||
ifcopenshell.util.resource.get_quantity_produced(productivity)
|
||||
)
|
||||
bpy.context.scene.BIMResourceProductivity.quantity_produced_name = (
|
||||
ifcopenshell.util.resource.get_quantity_produced_name(productivity)
|
||||
)
|
||||
time_consumed = ifcopenshell.util.resource.get_unit_consumed(productivity)
|
||||
if time_consumed:
|
||||
durations_attributes = helper.parse_duration_as_blender_props(time_consumed)
|
||||
duration_props.years = durations_attributes["years"]
|
||||
duration_props.months = durations_attributes["months"]
|
||||
duration_props.days = durations_attributes["days"]
|
||||
duration_props.hours = durations_attributes["hours"]
|
||||
duration_props.minutes = durations_attributes["minutes"]
|
||||
duration_props.seconds = durations_attributes["seconds"]
|
||||
|
||||
@classmethod
|
||||
def get_productivity_attributes(cls):
|
||||
props = bpy.context.scene.BIMResourceProductivity
|
||||
productivity = {}
|
||||
if props.quantity_consumed:
|
||||
productivity["BaseQuantityConsumed"] = helper.simplify_duration(
|
||||
props.quantity_consumed, "ELAPSEDTIME", "BaseQuantityConsumed"
|
||||
)
|
||||
productivity["BaseQuantityProducedValue"] = props.quantity_produced
|
||||
productivity["BaseQuantityProducedName"] = props.quantity_produced_name
|
||||
return productivity
|
||||
|
||||
@classmethod
|
||||
def get_productivity(cls, resource, should_inherit=False):
|
||||
return ifcopenshell.util.resource.get_productivity(resource, should_inherit=should_inherit)
|
||||
|
||||
@classmethod
|
||||
def edit_productivity_pset(cls, resource, attributes):
|
||||
productivity = cls.get_productivity(resource)
|
||||
if productivity:
|
||||
pset = tool.Ifc.get().by_id(productivity["id"])
|
||||
else:
|
||||
pset = tool.Ifc.run("pset.add_pset", product=resource, name="EPset_Productivity")
|
||||
tool.Ifc.run(
|
||||
"pset.edit_pset",
|
||||
pset=pset,
|
||||
properties=attributes,
|
||||
)
|
||||
@@ -27,6 +27,7 @@ import ifcopenshell.util.element
|
||||
import ifcopenshell.util.unit
|
||||
import json
|
||||
import blenderbim.core.tool
|
||||
import blenderbim.core
|
||||
import blenderbim.tool as tool
|
||||
import blenderbim.bim.helper
|
||||
import blenderbim.bim.module.sequence.helper as helper
|
||||
@@ -132,7 +133,7 @@ class Sequence(blenderbim.core.tool.Sequence):
|
||||
props.editing_type = "TASKS"
|
||||
|
||||
@classmethod
|
||||
def create_task_tree(cls, work_schedule):
|
||||
def load_task_tree(cls, work_schedule):
|
||||
bpy.context.scene.BIMTaskTreeProperties.tasks.clear()
|
||||
props = bpy.context.scene.BIMWorkScheduleProperties
|
||||
cls.contracted_tasks = json.loads(props.contracted_tasks)
|
||||
@@ -145,25 +146,26 @@ class Sequence(blenderbim.core.tool.Sequence):
|
||||
def get_sorted_tasks_ids(cls, tasks):
|
||||
def get_sort_key(task):
|
||||
# Sorting only applies to actual tasks, not the WBS
|
||||
for rel in task.IsNestedBy:
|
||||
for object in rel.RelatedObjects:
|
||||
if object.is_a("IfcTask"):
|
||||
return "0000000000" + (task.Identification or "")
|
||||
if not bpy.context.scene.BIMWorkScheduleProperties.sort_column:
|
||||
return task.Identification or ""
|
||||
# for rel in task.IsNestedBy:
|
||||
# for object in rel.RelatedObjects:
|
||||
# if object.is_a("IfcTask"):
|
||||
# return "0000000000" + (task.Identification or "")
|
||||
column_type, name = bpy.context.scene.BIMWorkScheduleProperties.sort_column.split(".")
|
||||
if column_type == "IfcTask":
|
||||
return task.Name or ""
|
||||
return task.get_info(task)[name] or ""
|
||||
elif column_type == "IfcTaskTime" and task.TaskTime:
|
||||
return task.TaskTime.Name or ""
|
||||
return task.TaskTime.get_info(task)[name]
|
||||
return task.Identification or ""
|
||||
|
||||
def natural_sort_key(i, _nsre=re.compile("([0-9]+)")):
|
||||
s = sort_keys[i]
|
||||
return [int(text) if text.isdigit() else text.lower() for text in _nsre.split(s)]
|
||||
|
||||
sort_keys = {task.id(): get_sort_key(task) for task in tasks}
|
||||
related_object_ids = sorted(sort_keys, key=natural_sort_key)
|
||||
if bpy.context.scene.BIMWorkScheduleProperties.sort_column:
|
||||
sort_keys = {task.id(): get_sort_key(task) for task in tasks}
|
||||
related_object_ids = sorted(sort_keys, key=natural_sort_key)
|
||||
else:
|
||||
related_object_ids = [task.id() for task in tasks]
|
||||
if bpy.context.scene.BIMWorkScheduleProperties.is_sort_reversed:
|
||||
related_object_ids.reverse()
|
||||
return related_object_ids
|
||||
@@ -328,7 +330,7 @@ class Sequence(blenderbim.core.tool.Sequence):
|
||||
blenderbim.bim.helper.import_attributes2(task, props.task_attributes)
|
||||
|
||||
@classmethod
|
||||
def enable_editing_task(cls, task):
|
||||
def enable_editing_task_attributes(cls, task):
|
||||
props = bpy.context.scene.BIMWorkScheduleProperties
|
||||
props.active_task_id = task.id()
|
||||
props.editing_task_type = "ATTRIBUTES"
|
||||
@@ -407,16 +409,15 @@ class Sequence(blenderbim.core.tool.Sequence):
|
||||
def load_task_resources(cls, resources):
|
||||
props = bpy.context.scene.BIMWorkScheduleProperties
|
||||
props.task_resources.clear()
|
||||
if resources:
|
||||
for resource in resources:
|
||||
new = props.task_resources.add()
|
||||
new.ifc_definition_id = resource.id()
|
||||
new.name = resource.Name or "Unnamed"
|
||||
new.schedule_usage = resource.Usage.ScheduleUsage or 1 if resource.Usage else 0
|
||||
for resource in resources or []:
|
||||
new = props.task_resources.add()
|
||||
new.ifc_definition_id = resource.id()
|
||||
new.name = resource.Name or "Unnamed"
|
||||
new.schedule_usage = resource.Usage.ScheduleUsage or 1 if resource.Usage else 0
|
||||
|
||||
@classmethod
|
||||
def load_resources(cls):
|
||||
bpy.ops.bim.load_resources() # remove and refactor
|
||||
blenderbim.core.resource.load_resources(tool.Resource)
|
||||
|
||||
@classmethod
|
||||
def get_task_inputs(cls, task):
|
||||
@@ -428,10 +429,22 @@ class Sequence(blenderbim.core.tool.Sequence):
|
||||
is_deep = bpy.context.scene.BIMWorkScheduleProperties.show_nested_outputs
|
||||
return ifcopenshell.util.sequence.get_task_outputs(task, is_deep)
|
||||
|
||||
@classmethod
|
||||
def are_entities_same_class(cls, entities):
|
||||
if not entities:
|
||||
return False
|
||||
if len(entities) == 1:
|
||||
return True
|
||||
first = entities[0]
|
||||
for entity in entities:
|
||||
if entity.is_a() != first.is_a():
|
||||
return False
|
||||
return True
|
||||
|
||||
@classmethod
|
||||
def get_task_resources(cls, task):
|
||||
is_deep = bpy.context.scene.BIMWorkScheduleProperties.show_nested_resources
|
||||
return ifcopenshell.util.sequence.get_task_resource(task, is_deep)
|
||||
return ifcopenshell.util.sequence.get_task_resources(task, is_deep)
|
||||
|
||||
@classmethod
|
||||
def load_task_inputs(cls, inputs):
|
||||
@@ -732,6 +745,8 @@ class Sequence(blenderbim.core.tool.Sequence):
|
||||
def remove_task_column(cls, name):
|
||||
props = bpy.context.scene.BIMWorkScheduleProperties
|
||||
props.columns.remove(props.columns.find(name))
|
||||
if props.sort_column == name:
|
||||
props.sort_column = ""
|
||||
|
||||
@classmethod
|
||||
def set_task_sort_column(cls, column):
|
||||
@@ -779,7 +794,7 @@ class Sequence(blenderbim.core.tool.Sequence):
|
||||
bpy.context.scene.BIMWorkScheduleProperties.contracted_tasks = json.dumps(contracted_tasks)
|
||||
expand_ancestors(parent_task)
|
||||
work_schedule = cls.get_active_work_schedule()
|
||||
cls.create_task_tree(work_schedule)
|
||||
cls.load_task_tree(work_schedule)
|
||||
cls.load_task_properties()
|
||||
|
||||
task_props = bpy.context.scene.BIMTaskTreeProperties
|
||||
@@ -1510,9 +1525,8 @@ class Sequence(blenderbim.core.tool.Sequence):
|
||||
webbrowser.open("file://" + os.path.join(bpy.context.scene.BIMProperties.data_dir, "gantt", "index.html"))
|
||||
|
||||
@classmethod
|
||||
def load_product_tasks(cls, product):
|
||||
def load_product_related_tasks(cls, product):
|
||||
props = bpy.context.scene.BIMWorkScheduleProperties
|
||||
props.is_task_update_enabled = False
|
||||
props.product_input_tasks.clear()
|
||||
props.product_output_tasks.clear()
|
||||
task_inputs, task_ouputs = ifcopenshell.util.sequence.get_tasks_for_product(product)
|
||||
@@ -1540,3 +1554,11 @@ class Sequence(blenderbim.core.tool.Sequence):
|
||||
task_inputs = [task for task in task_inputs or [] if cls.get_work_schedule(task) == work_schedule]
|
||||
task_ouputs = [task for task in task_ouputs or [] if cls.get_work_schedule(task) == work_schedule]
|
||||
return bool(task_inputs or task_ouputs)
|
||||
|
||||
@classmethod
|
||||
def is_sorting_enabled(cls):
|
||||
return bpy.context.scene.BIMWorkScheduleProperties.sort_column
|
||||
|
||||
@classmethod
|
||||
def is_sort_reversed(cls):
|
||||
return bpy.context.scene.BIMWorkScheduleProperties.is_sort_reversed
|
||||
|
||||
@@ -225,7 +225,7 @@ Scenario: Enable editing task
|
||||
And I press "bim.enable_editing_work_schedule_tasks(work_schedule={work_schedule})"
|
||||
And I press "bim.add_summary_task(work_schedule={work_schedule})"
|
||||
And the variable "task" is "IfcStore.get_file().by_type('IfcTask')[0].id()"
|
||||
When I press "bim.enable_editing_task(task={task})"
|
||||
When I press "bim.enable_editing_task_attributes(task={task})"
|
||||
Then nothing happens
|
||||
|
||||
Scenario: Copy task attribute
|
||||
@@ -236,7 +236,7 @@ Scenario: Copy task attribute
|
||||
And I press "bim.add_summary_task(work_schedule={work_schedule})"
|
||||
And I press "bim.add_summary_task(work_schedule={work_schedule})"
|
||||
And the variable "task" is "IfcStore.get_file().by_type('IfcTask')[0].id()"
|
||||
And I press "bim.enable_editing_task(task={task})"
|
||||
And I press "bim.enable_editing_task_attributes(task={task})"
|
||||
And I set "scene.BIMWorkScheduleProperties.task_attributes[2].string_value" to "Foo"
|
||||
When I set "scene.BIMTaskTreeProperties.tasks[1].is_selected" to "True"
|
||||
And I press "bim.copy_task_attribute(name='Description')"
|
||||
@@ -253,7 +253,7 @@ Scenario: Unassign task Successor
|
||||
And the variable "nested_task_one" is "IfcStore.get_file().by_type('IfcTask')[1].id()"
|
||||
When I press "bim.add_task(task={task})"
|
||||
And the variable "nested_task_two" is "IfcStore.get_file().by_type('IfcTask')[2].id()"
|
||||
And I press "bim.enable_editing_task(task={nested_task_one})"
|
||||
And I press "bim.enable_editing_task_attributes(task={nested_task_one})"
|
||||
And I press "bim.assign_successor(task={nested_task_two})"
|
||||
When I press "bim.unassign_successor(task={nested_task_two})"
|
||||
Then nothing happens
|
||||
@@ -269,7 +269,7 @@ Scenario: Edit time Lag
|
||||
And the variable "nested_task_one" is "IfcStore.get_file().by_type('IfcTask')[1].id()"
|
||||
When I press "bim.add_task(task={task})"
|
||||
And the variable "nested_task_two" is "IfcStore.get_file().by_type('IfcTask')[2].id()"
|
||||
And I press "bim.enable_editing_task(task={nested_task_one})"
|
||||
And I press "bim.enable_editing_task_attributes(task={nested_task_one})"
|
||||
When I press "bim.assign_successor(task={nested_task_two})"
|
||||
And the variable "rel_sequence" is "IfcStore.get_file().by_type('IfcRelSequence')[0].id()"
|
||||
When I press "bim.assign_lag_time(sequence={rel_sequence})"
|
||||
@@ -290,7 +290,7 @@ Scenario: Unassign time Lag
|
||||
And the variable "nested_task_one" is "IfcStore.get_file().by_type('IfcTask')[1].id()"
|
||||
When I press "bim.add_task(task={task})"
|
||||
And the variable "nested_task_two" is "IfcStore.get_file().by_type('IfcTask')[2].id()"
|
||||
And I press "bim.enable_editing_task(task={nested_task_one})"
|
||||
And I press "bim.enable_editing_task_attributes(task={nested_task_one})"
|
||||
When I press "bim.assign_successor(task={nested_task_two})"
|
||||
And the variable "rel_sequence" is "IfcStore.get_file().by_type('IfcRelSequence')[0].id()"
|
||||
When I press "bim.assign_lag_time(sequence={rel_sequence})"
|
||||
@@ -309,7 +309,7 @@ Scenario: Edit Sequence Relationship
|
||||
And the variable "nested_task_one" is "IfcStore.get_file().by_type('IfcTask')[1].id()"
|
||||
When I press "bim.add_task(task={task})"
|
||||
And the variable "nested_task_two" is "IfcStore.get_file().by_type('IfcTask')[2].id()"
|
||||
And I press "bim.enable_editing_task(task={nested_task_one})"
|
||||
And I press "bim.enable_editing_task_attributes(task={nested_task_one})"
|
||||
When I press "bim.assign_successor(task={nested_task_two})"
|
||||
And the variable "rel_sequence" is "IfcStore.get_file().by_type('IfcRelSequence')[0].id()"
|
||||
And I press "bim.enable_editing_sequence_attributes(sequence={rel_sequence})"
|
||||
@@ -340,7 +340,7 @@ Scenario: Animate the construction of a wall
|
||||
And I press "bim.enable_editing_work_schedule_tasks(work_schedule={work_schedule})"
|
||||
And I press "bim.add_summary_task(work_schedule={work_schedule})"
|
||||
And the variable "task" is "IfcStore.get_file().by_type('IfcTask')[0].id()"
|
||||
And I press "bim.enable_editing_task(task={task})"
|
||||
And I press "bim.enable_editing_task_attributes(task={task})"
|
||||
And I set "scene.BIMWorkScheduleProperties.task_attributes.get('PredefinedType').enum_value" to "CONSTRUCTION"
|
||||
And I press "bim.edit_task"
|
||||
And I press "bim.enable_editing_task_time(task={task})"
|
||||
@@ -376,7 +376,7 @@ Scenario: Animate the demolition of a wall
|
||||
And I press "bim.enable_editing_work_schedule_tasks(work_schedule={work_schedule})"
|
||||
And I press "bim.add_summary_task(work_schedule={work_schedule})"
|
||||
And the variable "task" is "IfcStore.get_file().by_type('IfcTask')[0].id()"
|
||||
And I press "bim.enable_editing_task(task={task})"
|
||||
And I press "bim.enable_editing_task_attributes(task={task})"
|
||||
And I set "scene.BIMWorkScheduleProperties.task_attributes.get('PredefinedType').enum_value" to "DEMOLITION"
|
||||
And I press "bim.edit_task"
|
||||
And I press "bim.enable_editing_task_time(task={task})"
|
||||
@@ -415,7 +415,7 @@ Scenario: Animate the operation of a wall
|
||||
And I press "bim.enable_editing_work_schedule_tasks(work_schedule={work_schedule})"
|
||||
And I press "bim.add_summary_task(work_schedule={work_schedule})"
|
||||
And the variable "task" is "IfcStore.get_file().by_type('IfcTask')[0].id()"
|
||||
And I press "bim.enable_editing_task(task={task})"
|
||||
And I press "bim.enable_editing_task_attributes(task={task})"
|
||||
And I set "scene.BIMWorkScheduleProperties.task_attributes.get('PredefinedType').enum_value" to "OPERATION"
|
||||
And I press "bim.edit_task"
|
||||
And I press "bim.enable_editing_task_time(task={task})"
|
||||
@@ -448,7 +448,7 @@ Scenario: Animate the movement of a wall
|
||||
And I press "bim.enable_editing_work_schedule_tasks(work_schedule={work_schedule})"
|
||||
And I press "bim.add_summary_task(work_schedule={work_schedule})"
|
||||
And the variable "task" is "IfcStore.get_file().by_type('IfcTask')[0].id()"
|
||||
And I press "bim.enable_editing_task(task={task})"
|
||||
And I press "bim.enable_editing_task_attributes(task={task})"
|
||||
And I set "scene.BIMWorkScheduleProperties.task_attributes.get('PredefinedType').enum_value" to "MOVE"
|
||||
And I press "bim.edit_task"
|
||||
And I press "bim.enable_editing_task_time(task={task})"
|
||||
@@ -539,7 +539,7 @@ Scenario: Generate Gantt Chart
|
||||
And I press "bim.enable_editing_work_schedule_tasks(work_schedule={work_schedule})"
|
||||
And I press "bim.add_summary_task(work_schedule={work_schedule})"
|
||||
And the variable "task" is "IfcStore.get_file().by_type('IfcTask')[0].id()"
|
||||
And I press "bim.enable_editing_task(task={task})"
|
||||
And I press "bim.enable_editing_task_attributes(task={task})"
|
||||
And I set "scene.BIMWorkScheduleProperties.task_attributes.get('PredefinedType').enum_value" to "CONSTRUCTION"
|
||||
And I press "bim.edit_task"
|
||||
And I press "bim.enable_editing_task_time(task={task})"
|
||||
@@ -788,7 +788,7 @@ Scenario: Duplicate Task
|
||||
And the variable "nested_task_one" is "IfcStore.get_file().by_type('IfcTask')[1].id()"
|
||||
When I press "bim.add_task(task={task})"
|
||||
And the variable "nested_task_two" is "IfcStore.get_file().by_type('IfcTask')[2].id()"
|
||||
And I press "bim.enable_editing_task(task={nested_task_one})"
|
||||
And I press "bim.enable_editing_task_attributes(task={nested_task_one})"
|
||||
And I press "bim.assign_successor(task={nested_task_two})"
|
||||
When I press "bim.duplicate_task(task={task})"
|
||||
Then nothing happens
|
||||
@@ -804,7 +804,7 @@ Scenario: Duplicate Task and edit sequence Relationship
|
||||
And the variable "nested_task_one" is "IfcStore.get_file().by_type('IfcTask')[1].id()"
|
||||
When I press "bim.add_task(task={task})"
|
||||
And the variable "nested_task_two" is "IfcStore.get_file().by_type('IfcTask')[2].id()"
|
||||
And I press "bim.enable_editing_task(task={nested_task_one})"
|
||||
And I press "bim.enable_editing_task_attributes(task={nested_task_one})"
|
||||
And I press "bim.assign_successor(task={nested_task_two})"
|
||||
And I press "bim.duplicate_task(task={task})"
|
||||
When I press "bim.enable_editing_task_sequence(task={nested_task_one})"
|
||||
|
||||
@@ -0,0 +1,102 @@
|
||||
# IfcOpenShell - IFC toolkit and geometry engine
|
||||
# Copyright (C) 2021 Dion Moult <dion@thinkmoult.com>
|
||||
#
|
||||
# This file is part of IfcOpenShell.
|
||||
#
|
||||
# IfcOpenShell is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Lesser General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# IfcOpenShell is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU Lesser General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Lesser General Public License
|
||||
# along with IfcOpenShell. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
import ifcopenshell.util.element
|
||||
import ifcopenshell.util.date
|
||||
|
||||
|
||||
def get_productivity(resource, should_inherit=True):
|
||||
productivity = ifcopenshell.util.element.get_psets(
|
||||
resource
|
||||
).get("EPset_Productivity", None)
|
||||
if should_inherit and not productivity:
|
||||
# Proposal for Schema - If instance doesn't have any productivity, inherit it's parent's productivity
|
||||
if not resource.Nests:
|
||||
return None
|
||||
else:
|
||||
parent_resource = resource.Nests[0].RelatingObject
|
||||
productivity = ifcopenshell.util.element.get_psets(
|
||||
parent_resource
|
||||
).get("EPset_Productivity", None)
|
||||
return productivity
|
||||
|
||||
def get_unit_consumed(productivity):
|
||||
duration = productivity.get("BaseQuantityConsumed", None)
|
||||
if not duration:
|
||||
return
|
||||
return ifcopenshell.util.date.ifc2datetime(duration)
|
||||
|
||||
def get_quantity_produced(productivity):
|
||||
if not productivity:
|
||||
return 0
|
||||
return productivity.get("BaseQuantityProducedValue", 0)
|
||||
|
||||
def get_quantity_produced_name(productivity):
|
||||
if not productivity:
|
||||
return ""
|
||||
return productivity.get("BaseQuantityProducedName", "")
|
||||
|
||||
def get_total_quantity_produced(resource, quantity_name_in_process):
|
||||
def get_product_quantity(product, quantity_name):
|
||||
psets = ifcopenshell.util.element.get_psets(product)
|
||||
for pset in psets.values():
|
||||
for name, value in pset.items():
|
||||
if name == quantity_name:
|
||||
return float(value)
|
||||
|
||||
total = 0
|
||||
products = get_parametric_resource_products(resource)
|
||||
if quantity_name_in_process == "Count":
|
||||
total = len(products)
|
||||
else:
|
||||
for product in products:
|
||||
total += get_product_quantity(product, quantity_name_in_process)
|
||||
return total
|
||||
|
||||
def get_parametric_resource_products(resource):
|
||||
products = []
|
||||
for rel in resource.HasAssignments or []:
|
||||
if not rel.is_a("IfcRelAssignsToProcess"):
|
||||
continue
|
||||
for rel2 in rel.RelatingProcess.HasAssignments or []:
|
||||
if not rel2.is_a("IfcRelAssignsToProduct"):
|
||||
continue
|
||||
products.append(rel2.RelatingProduct)
|
||||
return products
|
||||
|
||||
def get_resource_required_work(resource):
|
||||
productivity = get_productivity(resource)
|
||||
if productivity:
|
||||
quantity_produced = get_quantity_produced(productivity)
|
||||
time_consumed = get_unit_consumed(productivity)
|
||||
quantity_name_in_process = get_quantity_produced_name(productivity)
|
||||
total_quantity_to_produce = get_total_quantity_produced(resource, quantity_name_in_process)
|
||||
if not time_consumed or not quantity_produced or not total_quantity_to_produce:
|
||||
return
|
||||
iso_string = ""
|
||||
if "T" in productivity.get("BaseQuantityConsumed", ""):
|
||||
seconds = (time_consumed.days * 24 * 60 * 60) + time_consumed.seconds
|
||||
productivity_ratio = seconds / quantity_produced
|
||||
required_work = total_quantity_to_produce * productivity_ratio
|
||||
iso_string = f"PT{required_work / 60 / 60}H"
|
||||
else:
|
||||
days = time_consumed.days + (time_consumed.seconds / (24 * 60 * 60))
|
||||
productivity_ratio = days / quantity_produced
|
||||
required_work = total_quantity_to_produce * productivity_ratio
|
||||
iso_string = f"P{required_work}D"
|
||||
return iso_string
|
||||
Reference in New Issue
Block a user