mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-08-14 11:24:19 +00:00
features to guess schedule date range and setup default task columns, and code clean up
This commit is contained in:
committed by
Dion Moult
parent
3fd1209906
commit
8004a45b54
@@ -77,6 +77,7 @@ classes = (
|
||||
operator.ExportMSP,
|
||||
operator.ExportP6,
|
||||
operator.GenerateGanttChart,
|
||||
operator.GuessDateRange,
|
||||
operator.ImportMSP,
|
||||
operator.ImportP6,
|
||||
operator.ImportP6XER,
|
||||
@@ -97,6 +98,7 @@ classes = (
|
||||
operator.SelectTaskRelatedProducts,
|
||||
operator.SelectTaskRelatedInputs,
|
||||
operator.SetTaskSortColumn,
|
||||
operator.SetupDefaultTaskColumns,
|
||||
operator.UnassignLagTime,
|
||||
operator.UnassignPredecessor,
|
||||
operator.UnassignProcess,
|
||||
|
||||
@@ -71,7 +71,6 @@ def get_nested_tasks(task):
|
||||
def get_parent_task(task):
|
||||
return task.Nests[0].RelatingObject if task.Nests and task.Nests[0].RelatingObject.is_a("IfcTask") else None
|
||||
|
||||
|
||||
def get_task_work_schedule(task):
|
||||
parent_task = get_parent_task(task)
|
||||
if parent_task:
|
||||
@@ -95,11 +94,44 @@ def get_work_schedule_tasks(work_schedule):
|
||||
for root_task in get_root_tasks(work_schedule):
|
||||
nested_tasks = get_all_nested_tasks(root_task)
|
||||
tasks.extend(nested_tasks)
|
||||
|
||||
return tasks
|
||||
|
||||
def get_root_tasks(work_schedule):
|
||||
return [obj for rel in work_schedule.Controls for obj in rel.RelatedObjects if obj.is_a("IfcTask")]
|
||||
|
||||
def get_root_tasks_ids(work_schedule):
|
||||
return [obj.id() for rel in work_schedule.Controls for obj in rel.RelatedObjects if obj.is_a("IfcTask")]
|
||||
return [obj.id() for rel in work_schedule.Controls for obj in rel.RelatedObjects if obj.is_a("IfcTask")]
|
||||
|
||||
def guess_date_range(work_schedule):
|
||||
earliest = None
|
||||
latest = None
|
||||
root_tasks = get_root_tasks(work_schedule)
|
||||
tasks_with_assignements = []
|
||||
for task in root_tasks:
|
||||
if has_task_outputs(task):
|
||||
tasks_with_assignements.append(task)
|
||||
for sub_task in get_all_nested_tasks(task):
|
||||
if has_task_outputs(sub_task):
|
||||
tasks_with_assignements.append(sub_task)
|
||||
|
||||
for task in tasks_with_assignements:
|
||||
derived_start = derive_date(task, "ScheduleStart", is_earliest=True)
|
||||
derived_finish = derive_date(task, "ScheduleFinish", is_latest=True)
|
||||
if derived_start and (not earliest or derived_start < earliest):
|
||||
earliest = derived_start
|
||||
if derived_finish and (not latest or derived_finish > latest):
|
||||
latest = derived_finish
|
||||
return earliest, latest
|
||||
|
||||
def get_direct_task_outputs(task):
|
||||
return [rel.RelatingProduct for rel in task.HasAssignments if rel.is_a("IfcRelAssignsToProduct")]
|
||||
|
||||
def get_task_outputs(task, is_deep=False):
|
||||
if not is_deep:
|
||||
return get_direct_task_outputs(task)
|
||||
else:
|
||||
nested_tasks = get_all_nested_tasks(task)
|
||||
return [output for nested_task in nested_tasks for output in get_direct_task_outputs(nested_task)]
|
||||
|
||||
def has_task_outputs(task):
|
||||
return len(get_task_outputs(task)) > 0
|
||||
@@ -1086,6 +1086,15 @@ class VisualiseWorkScheduleDate(bpy.types.Operator):
|
||||
self.completed.update(products)
|
||||
|
||||
|
||||
class GuessDateRange(bpy.types.Operator, tool.Ifc.Operator):
|
||||
bl_idname = "bim.guess_date_range"
|
||||
bl_label = "Guess Work Schedule Date Range"
|
||||
bl_options = {"REGISTER", "UNDO"}
|
||||
work_schedule: bpy.props.IntProperty()
|
||||
|
||||
def _execute(self, context):
|
||||
core.guess_date_range(tool.Sequence, work_schedule=tool.Ifc.get().by_id(self.work_schedule))
|
||||
|
||||
class VisualiseWorkScheduleDateRange(bpy.types.Operator):
|
||||
bl_idname = "bim.visualise_work_schedule_date_range"
|
||||
bl_label = "Visualise Work Schedule Date Range"
|
||||
@@ -1452,6 +1461,14 @@ class AddTaskColumn(bpy.types.Operator):
|
||||
core.add_task_column(tool.Sequence, self.column_type, self.name, self.data_type)
|
||||
return {"FINISHED"}
|
||||
|
||||
class SetupDefaultTaskColumns(bpy.types.Operator):
|
||||
bl_idname = "bim.setup_default_task_columns"
|
||||
bl_label = "Setip Default Task Columns"
|
||||
bl_options = {"REGISTER", "UNDO"}
|
||||
|
||||
def execute(self, context):
|
||||
core.setup_default_task_columns(tool.Sequence)
|
||||
return {"FINISHED"}
|
||||
|
||||
class RemoveTaskColumn(bpy.types.Operator):
|
||||
bl_idname = "bim.remove_task_column"
|
||||
|
||||
@@ -193,16 +193,18 @@ class BIM_PT_work_schedules(Panel):
|
||||
row.operator("bim.remove_task", text="", icon="X").task = ifc_definition_id
|
||||
|
||||
def draw_column_ui(self):
|
||||
row = self.layout.row(align=True)
|
||||
row.operator("bim.setup_default_task_columns", text="Show Default Columns", icon="ANCHOR_BOTTOM")
|
||||
row = self.layout.row(align=True)
|
||||
row.prop(self.props, "column_types", text="")
|
||||
column_type = self.props.column_types
|
||||
if self.props.column_types == "IfcTask":
|
||||
if column_type == "IfcTask":
|
||||
row.prop(self.props, "task_columns", text="")
|
||||
name, data_type = self.props.task_columns.split("/")
|
||||
elif self.props.column_types == "IfcTaskTime":
|
||||
elif column_type == "IfcTaskTime":
|
||||
row.prop(self.props, "task_time_columns", text="")
|
||||
name, data_type = self.props.task_time_columns.split("/")
|
||||
elif self.props.column_types == "Special":
|
||||
elif column_type == "Special":
|
||||
row.prop(self.props, "other_columns", text="")
|
||||
column_type, name = self.props.other_columns.split(".")
|
||||
data_type = "string"
|
||||
@@ -223,6 +225,8 @@ class BIM_PT_work_schedules(Panel):
|
||||
op.target_prop = "BIMWorkScheduleProperties.visualisation_start"
|
||||
op = row.operator("bim.datepicker", text=self.props.visualisation_finish or "Finish Date", icon="FF")
|
||||
op.target_prop = "BIMWorkScheduleProperties.visualisation_finish"
|
||||
op = row.operator("bim.guess_date_range", text="Guess", icon="FILE_REFRESH")
|
||||
op.work_schedule = self.props.active_work_schedule_id
|
||||
op = row.operator("bim.visualise_work_schedule_date", text="", icon="RESTRICT_RENDER_OFF")
|
||||
op.work_schedule = self.props.active_work_schedule_id
|
||||
op = row.operator("bim.visualise_work_schedule_date_range", text="", icon="OUTLINER_OB_CAMERA")
|
||||
@@ -253,8 +257,8 @@ class BIM_PT_work_schedules(Panel):
|
||||
"active_task_index",
|
||||
)
|
||||
row = self.layout.row()
|
||||
row.operator("bim.expand_all_tasks", text="Expand All Tasks")
|
||||
row.operator("bim.contract_all_tasks", text="Contract All Tasks")
|
||||
row.operator("bim.expand_all_tasks", text="Expand All")
|
||||
row.operator("bim.contract_all_tasks", text="Contract All")
|
||||
if self.props.active_task_id and self.props.editing_task_type == "ATTRIBUTES":
|
||||
self.draw_editable_task_attributes_ui()
|
||||
elif self.props.active_task_id and self.props.editing_task_type == "CALENDAR":
|
||||
|
||||
@@ -469,3 +469,10 @@ def highlight_product_related_task(sequence, product_type=None):
|
||||
is_work_schedule_active = sequence.is_work_schedule_active(work_schedule)
|
||||
if is_work_schedule_active:
|
||||
sequence.highlight_task(task)
|
||||
|
||||
def guess_date_range(sequence, work_schedule=None):
|
||||
start, finish = sequence.guess_date_range(work_schedule)
|
||||
sequence.update_visualisation_date(start,finish)
|
||||
|
||||
def setup_default_task_columns(sequence):
|
||||
sequence.setup_default_task_columns()
|
||||
@@ -474,7 +474,6 @@ class Sequence:
|
||||
def get_work_plan_attributes(cls): pass
|
||||
def load_work_plan_attributes(cls, work_plan): pass
|
||||
def get_direct_nested_tasks(cls, task):pass
|
||||
def get_all_nested_tasks(cls, task): pass
|
||||
def enable_editing_work_plan(cls, work_plan): pass
|
||||
def disable_editing_work_plan(cls): pass
|
||||
def enable_editing_work_plan_schedules(cls, work_plan): pass
|
||||
@@ -544,7 +543,9 @@ class Sequence:
|
||||
def get_work_schedule(cls, task): pass
|
||||
def is_work_schedule_active(cls, work_schedule): pass
|
||||
def highlight_task(cls, task): pass
|
||||
|
||||
def setup_default_task_columns(cls): pass
|
||||
def guess_date_range(cls, task): pass
|
||||
def update_visualisation_date(cls, date): pass
|
||||
|
||||
|
||||
@interface
|
||||
|
||||
@@ -127,20 +127,11 @@ class Sequence(blenderbim.core.tool.Sequence):
|
||||
|
||||
@classmethod
|
||||
def create_task_tree(cls, work_schedule):
|
||||
def get_root_tasks_ids(work_schedule):
|
||||
related_objects_ids = []
|
||||
if work_schedule.Controls:
|
||||
for rel in work_schedule.Controls:
|
||||
for obj in rel.RelatedObjects:
|
||||
if obj.is_a("IfcTask"):
|
||||
related_objects_ids.append(obj.id())
|
||||
return related_objects_ids
|
||||
|
||||
bpy.context.scene.BIMTaskTreeProperties.tasks.clear()
|
||||
props = bpy.context.scene.BIMWorkScheduleProperties
|
||||
cls.contracted_tasks = json.loads(props.contracted_tasks)
|
||||
|
||||
related_objects_ids = get_root_tasks_ids(work_schedule)
|
||||
related_objects_ids = helper.get_root_tasks_ids(work_schedule)
|
||||
if not related_objects_ids:
|
||||
return
|
||||
cls.sort_keys = {i: cls.get_sort_key(tool.Ifc.get().by_id(i)) for i in related_objects_ids}
|
||||
@@ -466,25 +457,15 @@ class Sequence(blenderbim.core.tool.Sequence):
|
||||
@classmethod
|
||||
def get_direct_nested_tasks(cls, task):
|
||||
return helper.get_nested_tasks(task)
|
||||
|
||||
@classmethod
|
||||
def get_all_nested_tasks(cls, task):
|
||||
for nested_task in helper.get_nested_tasks(task):
|
||||
yield nested_task
|
||||
yield from cls.get_all_nested_tasks(nested_task)
|
||||
|
||||
@classmethod
|
||||
def get_direct_task_outputs(cls, task):
|
||||
return[rel.RelatingProduct for rel in task.HasAssignments if rel.is_a("IfcRelAssignsToProduct")]
|
||||
return helper.get_direct_task_outputs(task)
|
||||
|
||||
@classmethod
|
||||
def get_task_outputs(cls, task):
|
||||
if bpy.context.scene.BIMWorkScheduleProperties.is_nested_task_outputs:
|
||||
nested_tasks = cls.get_all_nested_tasks(task)
|
||||
outputs = [output for nested_task in nested_tasks for output in cls.get_direct_task_outputs(nested_task)]
|
||||
else:
|
||||
outputs = cls.get_direct_task_outputs(task)
|
||||
return outputs
|
||||
is_deep = bpy.context.scene.BIMWorkScheduleProperties.is_nested_task_outputs
|
||||
return helper.get_task_outputs(task, is_deep)
|
||||
|
||||
@classmethod
|
||||
def get_task_resources(cls, task):
|
||||
@@ -719,6 +700,30 @@ class Sequence(blenderbim.core.tool.Sequence):
|
||||
new.name = f"{column_type}.{name}"
|
||||
new.data_type = data_type
|
||||
|
||||
@classmethod
|
||||
def setup_default_task_columns(cls):
|
||||
items = [
|
||||
{
|
||||
"column_type": "IfcTaskTime",
|
||||
"name": "ScheduleStart",
|
||||
},
|
||||
{
|
||||
"column_type": "IfcTaskTime",
|
||||
"name": "ScheduleFinish",
|
||||
},
|
||||
{
|
||||
"column_type": "IfcTaskTime",
|
||||
"name": "ScheduleDuration",
|
||||
},
|
||||
]
|
||||
|
||||
props = bpy.context.scene.BIMWorkScheduleProperties
|
||||
props.columns.clear()
|
||||
for item in items:
|
||||
new = props.columns.add()
|
||||
new.name = f"{item['column_type']}.{item['name']}"
|
||||
new.data_type = "string"
|
||||
|
||||
@classmethod
|
||||
def remove_task_column(cls, name):
|
||||
props = bpy.context.scene.BIMWorkScheduleProperties
|
||||
@@ -759,14 +764,6 @@ class Sequence(blenderbim.core.tool.Sequence):
|
||||
True if work_schedule.id() == bpy.context.scene.BIMWorkScheduleProperties.active_work_schedule_id else False
|
||||
)
|
||||
|
||||
@classmethod
|
||||
def get_work_schedule(cls, task):
|
||||
for rel in task.HasAssignments or []:
|
||||
if rel.is_a("IfcRelAssignsToControl") and rel.RelatingControl.is_a("IfcWorkSchedule"):
|
||||
return rel.RelatingControl
|
||||
for rel in task.Nests or []:
|
||||
return cls.get_work_schedule(rel.RelatingObject)
|
||||
|
||||
@classmethod
|
||||
def highlight_task(cls, task):
|
||||
def expand_ancestors(task):
|
||||
@@ -787,3 +784,20 @@ class Sequence(blenderbim.core.tool.Sequence):
|
||||
expand_ancestors(task)
|
||||
task_index = [item.ifc_definition_id for item in task_props.tasks].index(task.id()) or 0
|
||||
bpy.context.scene.BIMWorkScheduleProperties.active_task_index = task_index
|
||||
|
||||
@classmethod
|
||||
def guess_date_range(cls, work_schedule):
|
||||
return helper.guess_date_range(work_schedule)
|
||||
|
||||
@classmethod
|
||||
def update_visualisation_date(cls, start_date, finish_date):
|
||||
def canonicalise_time(time):
|
||||
if not time:
|
||||
return "-"
|
||||
return time.strftime("%d/%m/%y")
|
||||
|
||||
print(start_date, finish_date)
|
||||
|
||||
props = bpy.context.scene.BIMWorkScheduleProperties
|
||||
props.visualisation_start = canonicalise_time(start_date)
|
||||
props.visualisation_finish = canonicalise_time(finish_date)
|
||||
Reference in New Issue
Block a user