Skip to content
This repository was archived by the owner on Nov 24, 2024. It is now read-only.

Commit 761b4c0

Browse files
committed
Optimisations for construction sequencing task trees where there are thousands of tasks
1 parent ee0f7f1 commit 761b4c0

4 files changed

Lines changed: 71 additions & 25 deletions

File tree

src/blenderbim/blenderbim/bim/module/sequence/__init__.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,10 +42,12 @@
4242
operator.UnassignProduct,
4343
operator.GenerateGanttChart,
4444
operator.ImportP6,
45+
operator.LoadTaskProperties,
4546
prop.WorkPlan,
4647
prop.BIMWorkPlanProperties,
4748
prop.Task,
4849
prop.BIMWorkScheduleProperties,
50+
prop.BIMTaskTreeProperties,
4951
prop.WorkCalendar,
5052
prop.BIMWorkCalendarProperties,
5153
ui.BIM_PT_work_plans,
@@ -64,12 +66,14 @@ def menu_func_import(self, context):
6466
def register():
6567
bpy.types.Scene.BIMWorkPlanProperties = bpy.props.PointerProperty(type=prop.BIMWorkPlanProperties)
6668
bpy.types.Scene.BIMWorkScheduleProperties = bpy.props.PointerProperty(type=prop.BIMWorkScheduleProperties)
69+
bpy.types.Scene.BIMTaskTreeProperties = bpy.props.PointerProperty(type=prop.BIMTaskTreeProperties)
6770
bpy.types.Scene.BIMWorkCalendarProperties = bpy.props.PointerProperty(type=prop.BIMWorkCalendarProperties)
6871
bpy.types.TOPBAR_MT_file_import.append(menu_func_import)
6972

7073

7174
def unregister():
7275
del bpy.types.Scene.BIMWorkPlanProperties
7376
del bpy.types.Scene.BIMWorkScheduleProperties
77+
del bpy.types.Scene.BIMTaskTreeProperties
7478
del bpy.types.Scene.BIMWorkCalendarProperties
7579
bpy.types.TOPBAR_MT_file_import.remove(menu_func_import)

src/blenderbim/blenderbim/bim/module/sequence/operator.py

Lines changed: 45 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -223,32 +223,22 @@ class EnableEditingTasks(bpy.types.Operator):
223223

224224
def execute(self, context):
225225
self.props = context.scene.BIMWorkScheduleProperties
226+
self.tprops = context.scene.BIMTaskTreeProperties
226227
self.props.active_work_schedule_id = self.work_schedule
227-
while len(self.props.tasks) > 0:
228-
self.props.tasks.remove(0)
228+
while len(self.tprops.tasks) > 0:
229+
self.tprops.tasks.remove(0)
229230

230231
self.contracted_tasks = json.loads(self.props.contracted_tasks)
231232
for related_object_id in Data.work_schedules[self.work_schedule]["RelatedObjects"]:
232233
self.create_new_task_li(related_object_id, 0)
234+
bpy.ops.bim.load_task_properties()
233235
self.props.is_editing = "TASKS"
234236
return {"FINISHED"}
235237

236238
def create_new_task_li(self, related_object_id, level_index):
237239
task = Data.tasks[related_object_id]
238-
new = self.props.tasks.add()
240+
new = self.tprops.tasks.add()
239241
new.ifc_definition_id = related_object_id
240-
new.name = task["Name"] or "Unnamed"
241-
new.identification = task["Identification"] or "XXX"
242-
if task["TaskTime"]:
243-
task_time = Data.task_times[task["TaskTime"]]
244-
new.start = self.canonicalise_time(task_time["ScheduleStart"])
245-
new.finish = self.canonicalise_time(task_time["ScheduleFinish"])
246-
# TODO: duration
247-
new.duration = "-"
248-
else:
249-
new.start = "-"
250-
new.finish = "-"
251-
new.duration = "-"
252242
new.is_expanded = related_object_id not in self.contracted_tasks
253243
new.level_index = level_index
254244
if task["RelatedObjects"]:
@@ -258,6 +248,38 @@ def create_new_task_li(self, related_object_id, level_index):
258248
self.create_new_task_li(related_object_id, level_index + 1)
259249
return {"FINISHED"}
260250

251+
252+
class LoadTaskProperties(bpy.types.Operator):
253+
bl_idname = "bim.load_task_properties"
254+
bl_label = "Load Task Properties"
255+
task: bpy.props.IntProperty()
256+
257+
def execute(self, context):
258+
self.props = context.scene.BIMWorkScheduleProperties
259+
self.tprops = context.scene.BIMTaskTreeProperties
260+
self.props.is_task_update_enabled = False
261+
for item in self.tprops.tasks:
262+
if self.task and item.ifc_definition_id != self.task:
263+
continue
264+
task = Data.tasks[item.ifc_definition_id]
265+
item.name = task["Name"] or "Unnamed"
266+
item.identification = task["Identification"] or "XXX"
267+
if self.props.active_task_id:
268+
item.is_predecessor = self.props.active_task_id in task["IsPredecessorTo"]
269+
item.is_successor = self.props.active_task_id in task["IsSuccessorFrom"]
270+
if task["TaskTime"]:
271+
task_time = Data.task_times[task["TaskTime"]]
272+
item.start = self.canonicalise_time(task_time["ScheduleStart"])
273+
item.finish = self.canonicalise_time(task_time["ScheduleFinish"])
274+
# TODO: duration
275+
item.duration = "-"
276+
else:
277+
item.start = "-"
278+
item.finish = "-"
279+
item.duration = "-"
280+
self.props.is_task_update_enabled = True
281+
return {"FINISHED"}
282+
261283
def canonicalise_time(self, time):
262284
if not time:
263285
return "-"
@@ -400,6 +422,7 @@ def execute(self, context):
400422
new.enum_value = data[attribute.name()]
401423
props.active_task_time_id = task_time_id
402424
props.active_task_id = self.task
425+
bpy.ops.bim.load_task_properties()
403426
return {"FINISHED"}
404427

405428
def add_task_time(self):
@@ -448,7 +471,7 @@ def execute(self, context):
448471
)
449472
Data.load(IfcStore.get_file())
450473
bpy.ops.bim.disable_editing_task_time()
451-
bpy.ops.bim.enable_editing_tasks(work_schedule=props.active_work_schedule_id)
474+
bpy.ops.bim.load_task_properties(task=props.active_task_id)
452475
return {"FINISHED"}
453476

454477
def convert_strings_to_date_times(self, attributes):
@@ -498,6 +521,7 @@ def execute(self, context):
498521
if data[attribute.name()]:
499522
new.enum_value = data[attribute.name()]
500523
props.active_task_id = self.task
524+
bpy.ops.bim.load_task_properties()
501525
return {"FINISHED"}
502526

503527

@@ -535,7 +559,7 @@ def execute(self, context):
535559
)
536560
Data.load(IfcStore.get_file())
537561
bpy.ops.bim.disable_editing_task()
538-
bpy.ops.bim.enable_editing_tasks(work_schedule=props.active_work_schedule_id)
562+
bpy.ops.bim.load_task_properties(task=props.active_task_id)
539563
return {"FINISHED"}
540564

541565

@@ -554,6 +578,7 @@ def execute(self, context):
554578
related_process=IfcStore.get_file().by_id(props.active_task_id),
555579
)
556580
Data.load(self.file)
581+
bpy.ops.bim.load_task_properties(task=self.task)
557582
return {"FINISHED"}
558583

559584

@@ -572,6 +597,7 @@ def execute(self, context):
572597
related_process=IfcStore.get_file().by_id(self.task),
573598
)
574599
Data.load(self.file)
600+
bpy.ops.bim.load_task_properties(task=self.task)
575601
return {"FINISHED"}
576602

577603

@@ -590,6 +616,7 @@ def execute(self, context):
590616
related_process=IfcStore.get_file().by_id(props.active_task_id),
591617
)
592618
Data.load(self.file)
619+
bpy.ops.bim.load_task_properties(task=self.task)
593620
return {"FINISHED"}
594621

595622

@@ -608,6 +635,7 @@ def execute(self, context):
608635
related_process=self.file.by_id(self.task),
609636
)
610637
Data.load(self.file)
638+
bpy.ops.bim.load_task_properties(task=self.task)
611639
return {"FINISHED"}
612640

613641

src/blenderbim/blenderbim/bim/module/sequence/prop.py

Lines changed: 18 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -18,10 +18,10 @@
1818

1919

2020
def updateTaskName(self, context):
21-
if self.name == "Unnamed":
21+
props = context.scene.BIMWorkScheduleProperties
22+
if not props.is_task_update_enabled or self.name == "Unnamed":
2223
return
2324
self.file = IfcStore.get_file()
24-
props = context.scene.BIMWorkScheduleProperties
2525
ifcopenshell.api.run(
2626
"sequence.edit_task",
2727
self.file,
@@ -34,10 +34,10 @@ def updateTaskName(self, context):
3434

3535

3636
def updateTaskIdentification(self, context):
37-
if self.identification == "X":
37+
props = context.scene.BIMWorkScheduleProperties
38+
if not props.is_task_update_enabled or self.identification == "XXX":
3839
return
3940
self.file = IfcStore.get_file()
40-
props = context.scene.BIMWorkScheduleProperties
4141
ifcopenshell.api.run(
4242
"sequence.edit_task",
4343
self.file,
@@ -58,6 +58,11 @@ def updateTaskTimeFinish(self, context):
5858

5959

6060
def updateTaskTimeDateTime(self, context, startfinish):
61+
props = context.scene.BIMWorkScheduleProperties
62+
63+
if not props.is_task_update_enabled:
64+
return
65+
6166
def canonicalise_time(time):
6267
if not time:
6368
return "-"
@@ -112,6 +117,8 @@ class Task(PropertyGroup):
112117
duration: StringProperty(name="Duration")
113118
start: StringProperty(name="Start", update=updateTaskTimeStart)
114119
finish: StringProperty(name="Finish", update=updateTaskTimeFinish)
120+
is_predecessor: BoolProperty(name="Is Predecessor")
121+
is_successor: BoolProperty(name="Is Successor")
115122

116123

117124
class WorkPlan(PropertyGroup):
@@ -132,14 +139,20 @@ class BIMWorkScheduleProperties(PropertyGroup):
132139
is_editing: StringProperty(name="Is Editing")
133140
active_work_schedule_index: IntProperty(name="Active Work Schedules Index")
134141
active_work_schedule_id: IntProperty(name="Active Work Schedules Id")
135-
tasks: CollectionProperty(name="Tasks", type=Task)
136142
active_task_index: IntProperty(name="Active Task Index")
137143
active_task_id: IntProperty(name="Active Task Id")
138144
task_attributes: CollectionProperty(name="Task Attributes", type=Attribute)
139145
should_show_times: BoolProperty(name="Should Show Times", default=True)
140146
active_task_time_id: IntProperty(name="Active Task Id")
141147
task_time_attributes: CollectionProperty(name="Task Time Attributes", type=Attribute)
142148
contracted_tasks: StringProperty(name="Contracted Task Items", default="[]")
149+
is_task_update_enabled: BoolProperty(name="Is Task Update Enabled", default=True)
150+
151+
152+
class BIMTaskTreeProperties(PropertyGroup):
153+
# This belongs by itself for performance reasons.
154+
# In Blender if you add thousands of tasks it makes other property access in the same group really slow.
155+
tasks: CollectionProperty(name="Tasks", type=Task)
143156

144157

145158
class WorkCalendar(PropertyGroup):

src/blenderbim/blenderbim/bim/module/sequence/ui.py

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,7 @@ def poll(cls, context):
8181

8282
def draw(self, context):
8383
self.props = context.scene.BIMWorkScheduleProperties
84+
self.tprops = context.scene.BIMTaskTreeProperties
8485

8586
if not Data.is_loaded:
8687
Data.load(IfcStore.get_file())
@@ -130,7 +131,7 @@ def draw_editable_task_ui(self, work_schedule_id):
130131
self.layout.template_list(
131132
"BIM_UL_tasks",
132133
"",
133-
self.props,
134+
self.tprops,
134135
"tasks",
135136
self.props,
136137
"active_task_index",
@@ -214,7 +215,7 @@ def draw_item(self, context, layout, data, item, icon, active_data, active_propn
214215
row.operator("bim.edit_task", text="", icon="CHECKMARK")
215216
row.operator("bim.disable_editing_task", text="", icon="CANCEL")
216217
elif props.active_task_id:
217-
if props.active_task_id in Data.tasks[item.ifc_definition_id]["IsPredecessorTo"]:
218+
if item.is_predecessor:
218219
row.operator(
219220
"bim.unassign_predecessor", text="", icon="BACK", emboss=False
220221
).task = item.ifc_definition_id
@@ -223,7 +224,7 @@ def draw_item(self, context, layout, data, item, icon, active_data, active_propn
223224
"bim.assign_predecessor", text="", icon="TRACKING_BACKWARDS", emboss=False
224225
).task = item.ifc_definition_id
225226

226-
if props.active_task_id in Data.tasks[item.ifc_definition_id]["IsSuccessorFrom"]:
227+
if item.is_successor:
227228
row.operator(
228229
"bim.unassign_successor", text="", icon="FORWARD", emboss=False
229230
).task = item.ifc_definition_id

0 commit comments

Comments
 (0)