BBIM: refactor gantt generation operator

This commit is contained in:
Sigma Dimensions
2023-01-20 11:26:32 +01:00
parent 893fd50b85
commit caf9034839
4 changed files with 81 additions and 57 deletions
@@ -464,62 +464,9 @@ class GenerateGanttChart(bpy.types.Operator):
work_schedule: bpy.props.IntProperty()
def execute(self, context):
self.file = IfcStore.get_file()
self.json = []
self.sequence_type_map = {
None: "FS",
"START_START": "SS",
"START_FINISH": "SF",
"FINISH_START": "FS",
"FINISH_FINISH": "FF",
"USERDEFINED": "FS",
"NOTDEFINED": "FS",
}
Data.load(self.file)
for task_id in Data.work_schedules[self.work_schedule]["RelatedObjects"]:
self.create_new_task_json(task_id)
with open(os.path.join(context.scene.BIMProperties.data_dir, "gantt", "index.html"), "w") as f:
with open(os.path.join(context.scene.BIMProperties.data_dir, "gantt", "index.mustache"), "r") as t:
f.write(pystache.render(t.read(), {"json_data": json.dumps(self.json)}))
webbrowser.open("file://" + os.path.join(context.scene.BIMProperties.data_dir, "gantt", "index.html"))
core.generate_gantt_chart(tool.Sequence, work_schedule=tool.Ifc.get().by_id(self.work_schedule))
return {"FINISHED"}
def create_new_task_json(self, task_id):
task = self.file.by_id(task_id)
data = {
"pID": task.id(),
"pName": task.Name,
"pCaption": task.Name,
"pStart": task.TaskTime.ScheduleStart if task.TaskTime else "",
"pEnd": task.TaskTime.ScheduleFinish if task.TaskTime else "",
"pPlanStart": task.TaskTime.ScheduleStart if task.TaskTime else "",
"pPlanEnd": task.TaskTime.ScheduleFinish if task.TaskTime else "",
"pMile": 1 if task.IsMilestone else 0,
"pComp": 0,
"pGroup": 1 if task.IsNestedBy else 0,
"pParent": task.Nests[0].RelatingObject.id() if task.Nests else 0,
"pOpen": 1,
"pCost": 1,
"ifcduration": task.TaskTime.ScheduleDuration if task.TaskTime else "",
}
if task.TaskTime and task.TaskTime.IsCritical:
data["pClass"] = "gtaskred"
elif data["pGroup"]:
data["pClass"] = "ggroupblack"
elif data["pMile"]:
data["pClass"] = "gmilestone"
else:
data["pClass"] = "gtaskblue"
data["pDepend"] = ",".join(
[
"{}{}".format(rel.RelatingProcess.id(), self.sequence_type_map[rel.SequenceType])
for rel in task.IsSuccessorFrom or []
]
)
self.json.append(data)
for task_id in Data.tasks[task_id]["RelatedObjects"]:
self.create_new_task_json(task_id)
class AddWorkCalendar(bpy.types.Operator, tool.Ifc.Operator):
bl_idname = "bim.add_work_calendar"
@@ -1097,7 +1044,7 @@ class VisualiseWorkScheduleDateRange(bpy.types.Operator):
@classmethod
def poll(cls, context):
has_start, has_finish = bpy.context.scene.BIMWorkScheduleProperties.visualisation_start, bpy.context.scene.BIMWorkScheduleProperties.visualisation_finish
return bool(has_start and has_finish)
return bool(has_start and has_finish) and not "-" in (has_start, has_finish)
def execute(self, context):
core.visualise_work_schedule_date_range(tool.Sequence, work_schedule=tool.Ifc.get().by_id(self.work_schedule))
@@ -1364,3 +1311,13 @@ class DisableEditingTaskAnimationColors(bpy.types.Operator):
def execute(self, context):
core.disable_editing_task_animation_colors(tool.Sequence)
return {"FINISHED"}
class CopyTask(bpy.types.Operator):
bl_idname = "bim.copy_task"
bl_label = "Copy Task"
bl_options = {"REGISTER", "UNDO"}
task: bpy.props.IntProperty()
def execute(self, context):
core.copy_task(tool.Ifc, tool.Sequence, task=tool.Ifc.get().by_id(self.task))
return {"FINISHED"}
+5 -1
View File
@@ -500,4 +500,8 @@ def visualise_work_schedule_date_range(sequence, work_schedule=None):
product_frames = sequence.get_animation_product_frames(work_schedule, settings)
sequence.load_task_animation_colors()
sequence.animate_objects(settings, product_frames)
sequence.add_text_animation_handler(settings)
sequence.add_text_animation_handler(settings)
def generate_gantt_chart(sequence, work_schedule):
json = sequence.create_tasks_json(work_schedule)
sequence.generate_gantt_browser_chart(json)
+1 -1
View File
@@ -501,7 +501,7 @@ class Sequence:
def expand_task(cls, task): pass
def find_related_output_tasks(cls, column): pass
def get_active_task(cls): pass
def get_active_work_schedule_id(cls): pass
def get_active_work_schedule(cls): pass
def get_checked_tasks(cls): pass
def get_direct_nested_tasks(cls, task):pass
def get_direct_task_outputs(cls, task): pass
@@ -18,10 +18,13 @@
import bpy
import re
import os
import isodate
import ifcopenshell
import ifcopenshell.util.sequence
import ifcopenshell.util.date
import ifcopenshell.util.element
import ifcopenshell.util.unit
import json
import blenderbim.core.tool
import blenderbim.tool as tool
@@ -30,6 +33,8 @@ import blenderbim.bim.module.sequence.helper as helper
from dateutil import parser
from datetime import datetime
import mathutils
import pystache
import webbrowser
class Sequence(blenderbim.core.tool.Sequence):
@@ -1271,3 +1276,61 @@ class Sequence(blenderbim.core.tool.Sequence):
obj.data.BIMDateTextProperties.start = bpy.context.scene.BIMWorkScheduleProperties.visualisation_start
obj.data.BIMDateTextProperties.finish = bpy.context.scene.BIMWorkScheduleProperties.visualisation_finish
append_handler(animate_text_handler)
@classmethod
def create_tasks_json(cls, work_schedule=None):
sequence_type_map = {
None: "FS",
"START_START": "SS",
"START_FINISH": "SF",
"FINISH_START": "FS",
"FINISH_FINISH": "FF",
"USERDEFINED": "FS",
"NOTDEFINED": "FS",
}
tasks_json = []
for task in ifcopenshell.util.sequence.get_root_tasks(work_schedule):
cls.create_new_task_json(task, tasks_json, sequence_type_map)
return tasks_json
@classmethod
def create_new_task_json(cls, task, json, type_map=None):
task_time = task.TaskTime
data = {
"pID": task.id(),
"pName": task.Name,
"pCaption": task.Name,
"pStart": task_time.ScheduleStart if task_time else "",
"pEnd": task_time.ScheduleFinish if task_time else "",
"pPlanStart": task_time.ScheduleStart if task_time else "",
"pPlanEnd": task_time.ScheduleFinish if task_time else "",
"pMile": 1 if task.IsMilestone else 0,
"pComp": 0,
"pGroup": 1 if task.IsNestedBy else 0,
"pParent": task.Nests[0].RelatingObject.id() if task.Nests else 0,
"pOpen": 1,
"pCost": 1,
"ifcduration": task_time.ScheduleDuration if task_time else "",
}
if task_time and task_time.IsCritical:
data["pClass"] = "gtaskred"
elif data["pGroup"]:
data["pClass"] = "ggroupblack"
elif data["pMile"]:
data["pClass"] = "gmilestone"
else:
data["pClass"] = "gtaskblue"
data["pDepend"] = ",".join([f"{rel.RelatingProcess.id()}{type_map[rel.SequenceType]}" for rel in task.IsSuccessorFrom or []])
json.append(data)
for nested_task in ifcopenshell.util.sequence.get_nested_tasks(task):
cls.create_new_task_json(nested_task, json, type_map)
@classmethod
def generate_gantt_browser_chart(cls, task_json):
with open(os.path.join(bpy.context.scene.BIMProperties.data_dir, "gantt", "index.html"), "w") as f:
with open(os.path.join(bpy.context.scene.BIMProperties.data_dir, "gantt", "index.mustache"), "r") as t:
f.write(pystache.render(t.read(), {"json_data": json.dumps(task_json)}))
webbrowser.open("file://" + os.path.join(bpy.context.scene.BIMProperties.data_dir, "gantt", "index.html"))