massive refactor of the sequence module

This commit is contained in:
Sigma Dimensions
2022-08-29 21:55:37 +01:00
parent ac3eb6fbda
commit 37dec500fd
19 changed files with 2208 additions and 1184 deletions
+8 -2
View File
@@ -16,6 +16,7 @@
# You should have received a copy of the GNU General Public License
# along with BlenderBIM Add-on. If not, see <http://www.gnu.org/licenses/>.
# from datetime import date
import bpy
import json
import math
@@ -46,6 +47,11 @@ def draw_attribute(attribute, layout, copy_operator=None):
value_name,
text=attribute.name,
)
if "ScheduleDuration" in attribute.name:
layout.prop(bpy.context.scene.BIMDuration, "duration_days",text="D")
layout.prop(bpy.context.scene.BIMDuration, "duration_hours",text="H")
layout.prop(bpy.context.scene.BIMDuration, "duration_minutes",text="M")
if attribute.is_optional:
layout.prop(attribute, "is_null", icon="RADIOBUT_OFF" if attribute.is_null else "RADIOBUT_ON", text="")
if copy_operator:
@@ -78,6 +84,7 @@ def import_attribute(attribute, props, data, callback=None):
new.is_optional = attribute.optional()
new.data_type = data_type if isinstance(data_type, str) else ""
is_handled_by_callback = callback(attribute.name(), new, data) if callback else None
if is_handled_by_callback:
pass # Our job is done
elif is_handled_by_callback is False:
@@ -96,8 +103,7 @@ def import_attribute(attribute, props, data, callback=None):
new.enum_items = json.dumps(ifcopenshell.util.attribute.get_enum_items(attribute))
if data[attribute.name()]:
new.enum_value = data[attribute.name()]
def export_attributes(props, callback=None):
attributes = {}
for prop in props:
@@ -102,7 +102,8 @@ class EnablePsetEditing(bpy.types.Operator):
def execute(self, context):
self.props = get_pset_props(context, self.obj, self.obj_type)
self.props.properties.clear()
ifc_definition_id = get_pset_obj_ifc_definition_id(context, self.obj, self.obj_type)
Data.load(IfcStore.get_file(), ifc_definition_id)
data = Data.psets if self.pset_id in Data.psets else Data.qtos
pset_data = data[self.pset_id]
self.props.active_pset_name = pset_data["Name"]
@@ -40,6 +40,7 @@ class LoadResources(bpy.types.Operator):
self.tprops.resources.clear()
self.contracted_resources = json.loads(self.props.contracted_resources)
Data.load(IfcStore.get_file())
for resource_id, data in Data.resources.items():
if not data["HasContext"]:
continue
@@ -116,7 +117,7 @@ class LoadResourceProperties(bpy.types.Operator):
class DisableEditingResource(bpy.types.Operator):
bl_idname = "bim.disable_editing_resource"
bl_label = "Disable Editing Workplan"
bl_label = "Disable Editing Resources"
bl_options = {"REGISTER", "UNDO"}
def execute(self, context):
@@ -20,6 +20,7 @@ import bpy
import ifcopenshell.api
from blenderbim.bim.ifc import IfcStore
from ifcopenshell.api.resource.data import Data
import blenderbim.bim.module.pset.data
from blenderbim.bim.prop import StrProperty, Attribute
from bpy.types import PropertyGroup
from bpy.props import (
@@ -70,6 +71,9 @@ def get_quantity_types(self, context):
return quantitytypes_enum
def update_active_resource_index(self, context):
blenderbim.bim.module.pset.data.refresh()
class Resource(PropertyGroup):
name: StringProperty(name="Name", update=updateResourceName)
ifc_definition_id: IntProperty(name="IFC Definition ID")
@@ -85,7 +89,7 @@ class BIMResourceTreeProperties(PropertyGroup):
class BIMResourceProperties(PropertyGroup):
resource_attributes: CollectionProperty(name="Resource Attributes", type=Attribute)
is_editing: BoolProperty(name="Is Editing")
active_resource_index: IntProperty(name="Active Resource Index")
active_resource_index: IntProperty(name="Active Resource Index", update=update_active_resource_index)
active_resource_id: IntProperty(name="Active Resource Id")
contracted_resources: StringProperty(name="Contracted Resources", default="[]")
is_resource_update_enabled: BoolProperty(name="Is Resource Update Enabled", default=True)
@@ -63,7 +63,7 @@ classes = (
operator.EnableEditingTaskCalendar,
operator.EnableEditingTaskSequence,
operator.EnableEditingTaskTime,
operator.EnableEditingTasks,
operator.EnableEditingWorkScheduleTasks,
operator.EnableEditingWorkCalendar,
operator.EnableEditingWorkCalendarTimes,
operator.EnableEditingWorkPlan,
@@ -92,6 +92,7 @@ classes = (
operator.RemoveWorkSchedule,
operator.RemoveWorkTime,
operator.SelectTaskRelatedProducts,
operator.SelectTaskRelatedInputs,
operator.SetTaskSortColumn,
operator.UnassignLagTime,
operator.UnassignPredecessor,
@@ -114,6 +115,7 @@ classes = (
prop.BIMWorkCalendarProperties,
prop.DatePickerProperties,
prop.BIMDateTextProperties,
prop.BIMDuration,
ui.BIM_PT_work_plans,
ui.BIM_PT_work_schedules,
ui.BIM_PT_work_calendars,
@@ -144,6 +146,7 @@ def register():
bpy.types.Scene.BIMTaskTreeProperties = bpy.props.PointerProperty(type=prop.BIMTaskTreeProperties)
bpy.types.Scene.BIMWorkCalendarProperties = bpy.props.PointerProperty(type=prop.BIMWorkCalendarProperties)
bpy.types.Scene.DatePickerProperties = bpy.props.PointerProperty(type=prop.DatePickerProperties)
bpy.types.Scene.BIMDuration = bpy.props.PointerProperty(type=prop.BIMDuration)
bpy.types.TextCurve.BIMDateTextProperties = bpy.props.PointerProperty(type=prop.BIMDateTextProperties)
bpy.types.TOPBAR_MT_file_export.append(menu_func_export)
bpy.types.TOPBAR_MT_file_import.append(menu_func_import)
@@ -155,6 +158,7 @@ def unregister():
del bpy.types.Scene.BIMTaskTreeProperties
del bpy.types.Scene.BIMWorkCalendarProperties
del bpy.types.Scene.DatePickerProperties
del bpy.types.Scene.BIMDuration
del bpy.types.TextCurve.BIMDateTextProperties
bpy.types.TOPBAR_MT_file_export.remove(menu_func_export)
bpy.types.TOPBAR_MT_file_import.remove(menu_func_import)
@@ -18,6 +18,7 @@
import bpy
import blenderbim.tool as tool
import ifcopenshell
def refresh():
@@ -25,20 +26,193 @@ def refresh():
class SequenceData:
data = {}
is_loaded = False
number_of_work_plans_loaded = 0
number_of_work_schedules_loaded = 0
number_of_tasks_loaded = 0
tasks = {}
@classmethod
def load(cls):
cls.data = {
"has_work_plans": cls.has_work_plans(),
"has_work_schedules": cls.has_work_schedules(),
"has_work_calendars": cls.has_work_calendars(),
}
cls.load_work_plans()
cls.load_work_schedules()
cls.load_work_calendars()
cls.load_work_times()
cls.load_recurrence_patterns()
cls.load_time_periods()
cls.load_sequences()
cls.load_lag_times()
cls.load_task_times()
cls.load_tasks()
cls.is_loaded = True
@classmethod
def has_work_plans(cls):
return bool(tool.Ifc.get().by_type("IfcWorkPlan"))
@classmethod
def has_work_calendars(cls):
return bool(tool.Ifc.get().by_type("IfcWorkCalendar"))
@classmethod
def number_of_work_plans_loaded(cls):
return len(tool.Ifc.get().by_type("IfcWorkPlan"))
@classmethod
def number_of_work_schedules_loaded(cls):
return len(tool.Ifc.get().by_type("IfcWorkSchedule"))
@classmethod
def has_work_schedules(cls):
return bool(tool.Ifc.get().by_type("IfcWorkSchedule"))
@classmethod
def load_work_plans(cls):
cls.work_plans = {}
cls.number_of_work_plans_loaded = len(tool.Ifc.get().by_type("IfcWorkPlan"))
cls.data["work_plans"] = {}
for work_plan in tool.Ifc.get().by_type("IfcWorkPlan"):
cls.work_plans[work_plan.id()] = {"Name": work_plan.Name}
data = {"Name": work_plan.Name}
data["IsDecomposedBy"] = []
for rel in work_plan.IsDecomposedBy:
data["IsDecomposedBy"].extend([o.id() for o in rel.RelatedObjects])
cls.data["work_plans"][work_plan.id()] = data
cls.data["number_of_work_plans_loaded"] = cls.number_of_work_plans_loaded()
@classmethod
def load_work_schedules(cls):
cls.data["work_schedules"] = {}
for work_schedule in tool.Ifc.get().by_type("IfcWorkSchedule"):
data = work_schedule.get_info()
del data["OwnerHistory"]
if data["Creators"]:
data["Creators"] = [p.id() for p in data["Creators"]]
data["CreationDate"] = (
ifcopenshell.util.date.ifc2datetime(data["CreationDate"]) if data["CreationDate"] else ""
)
data["StartTime"] = ifcopenshell.util.date.ifc2datetime(data["StartTime"]) if data["StartTime"] else ""
data["FinishTime"] = ifcopenshell.util.date.ifc2datetime(data["FinishTime"]) if data["FinishTime"] else ""
data["RelatedObjects"] = []
for rel in work_schedule.Controls:
for obj in rel.RelatedObjects:
if obj.is_a("IfcTask"):
data["RelatedObjects"].append(obj.id())
cls.data["work_schedules"][work_schedule.id()] = data
cls.data["number_of_work_schedules_loaded"] = cls.number_of_work_schedules_loaded()
@classmethod
def load_work_calendars(cls):
cls.data["work_calendars"] = {}
for work_calendar in tool.Ifc.get().by_type("IfcWorkCalendar"):
data = work_calendar.get_info()
del data["OwnerHistory"]
data["WorkingTimes"] = [t.id() for t in work_calendar.WorkingTimes or []]
data["ExceptionTimes"] = [t.id() for t in work_calendar.ExceptionTimes or []]
cls.data["work_calendars"][work_calendar.id()] = data
cls.data["number_of_work_calendars_loaded"] = len(cls.data["work_calendars"].keys())
@classmethod
def load_work_times(cls):
cls.data["work_times"] = {}
for work_time in tool.Ifc.get().by_type("IfcWorkTime"):
data = work_time.get_info()
data["Start"] = ifcopenshell.util.date.ifc2datetime(data["Start"]) if data["Start"] else None
data["Finish"] = ifcopenshell.util.date.ifc2datetime(data["Finish"]) if data["Finish"] else None
data["RecurrencePattern"] = work_time.RecurrencePattern.id() if work_time.RecurrencePattern else None
cls.data["work_times"][work_time.id()] = data
@classmethod
def load_recurrence_patterns(cls):
cls.data["recurrence_patterns"] = {}
for recurrence_pattern in tool.Ifc.get().by_type("IfcRecurrencePattern"):
data = recurrence_pattern.get_info()
data["TimePeriods"] = [t.id() for t in recurrence_pattern.TimePeriods or []]
cls.data["recurrence_patterns"][recurrence_pattern.id()] = data
@classmethod
def load_sequences(cls):
cls.data["sequences"] = {}
for sequence in tool.Ifc.get().by_type("IfcRelSequence"):
data = sequence.get_info()
data["RelatingProcess"] = sequence.RelatingProcess.id()
data["RelatedProcess"] = sequence.RelatedProcess.id()
data["TimeLag"] = sequence.TimeLag.id() if sequence.TimeLag else None
cls.data["sequences"][sequence.id()] = data
@classmethod
def load_time_periods(cls):
cls.data["time_periods"] = {}
for time_period in tool.Ifc.get().by_type("IfcTimePeriod"):
cls.data["time_periods"][time_period.id()] = {
"StartTime": ifcopenshell.util.date.ifc2datetime(time_period.StartTime),
"EndTime": ifcopenshell.util.date.ifc2datetime(time_period.EndTime),
}
@classmethod
def load_task_times(cls):
cls.data["task_times"] = {}
for task_time in tool.Ifc.get().by_type("IfcTaskTime"):
data = task_time.get_info()
for key, value in data.items():
if not value:
continue
if "Start" in key or "Finish" in key or key == "StatusTime":
data[key] = ifcopenshell.util.date.ifc2datetime(value)
elif key == "ScheduleDuration":
data[key] = ifcopenshell.util.date.ifc2datetime(value)
cls.data["task_times"][task_time.id()] = data
@classmethod
def load_lag_times(cls):
cls.data["lag_times"] = {}
for lag_time in tool.Ifc.get().by_type("IfcLagTime"):
data = lag_time.get_info()
if data["LagValue"]:
if data["LagValue"].is_a("IfcDuration"):
data["LagValue"] = ifcopenshell.util.date.ifc2datetime(data["LagValue"].wrappedValue)
else:
data["LagValue"] = float(data["LagValue"].wrappedValue)
cls.data["lag_times"][lag_time.id()] = data
@classmethod
def load_tasks(cls):
cls.data["tasks"] = {}
for task in tool.Ifc.get().by_type("IfcTask"):
data = task.get_info()
del data["OwnerHistory"]
data["HasAssignmentsWorkCalendar"] = []
data["RelatedObjects"] = []
data["Inputs"] = []
data["Controls"] = []
data["Outputs"] = []
data["Resources"] = []
data["IsPredecessorTo"] = []
data["IsSuccessorFrom"] = []
if task.TaskTime:
data["TaskTime"] = data["TaskTime"].id()
for rel in task.IsNestedBy:
[data["RelatedObjects"].append(o.id()) for o in rel.RelatedObjects if o.is_a("IfcTask")]
data["Nests"] = [r.RelatingObject.id() for r in task.Nests or []]
[
data["Outputs"].append(r.RelatingProduct.id())
for r in task.HasAssignments
if r.is_a("IfcRelAssignsToProduct")
]
[
data["Resources"].extend([o.id() for o in r.RelatedObjects if o.is_a("IfcResource")])
for r in task.OperatesOn
]
[
data["Controls"].extend([o.id() for o in r.RelatedObjects if o.is_a("IfcControl")])
for r in task.OperatesOn
]
[data["Inputs"].extend([o.id() for o in r.RelatedObjects if o.is_a("IfcProduct")]) for r in task.OperatesOn]
[data["IsPredecessorTo"].append(rel.id()) for rel in task.IsPredecessorTo or []]
[data["IsSuccessorFrom"].append(rel.id()) for rel in task.IsSuccessorFrom or []]
for rel in task.HasAssignments:
if rel.is_a("IfcRelAssignsToControl") and rel.RelatingControl:
if rel.RelatingControl.is_a("IfcWorkCalendar"):
data["HasAssignmentsWorkCalendar"].append(rel.RelatingControl.id())
cls.data["tasks"][task.id()] = data
@@ -16,38 +16,21 @@
# You should have received a copy of the GNU General Public License
# along with BlenderBIM Add-on. If not, see <http://www.gnu.org/licenses/>.
import bpy
import math
import isodate
import datetime
from dateutil import parser
from ifcopenshell.api.sequence.data import Data
import ifcopenshell.util.date as ifcdateutils
def derive_date(ifc_definition_id, attribute_name, date=None, is_earliest=False, is_latest=False):
task = Data.tasks[ifc_definition_id]
if task["TaskTime"]:
current_date = Data.task_times[task["TaskTime"]][attribute_name]
def derive_date(task, attribute_name, date=None, is_earliest=False, is_latest=False):
if task.TaskTime:
current_date = (
ifcdateutils.ifc2datetime(getattr(task.TaskTime, attribute_name))
if getattr(task.TaskTime, attribute_name)
else ""
)
if current_date:
return current_date
for subtask in task["RelatedObjects"]:
current_date = derive_date(subtask, attribute_name, date=date, is_earliest=is_earliest, is_latest=is_latest)
if is_earliest:
if current_date and (date is None or current_date < date):
date = current_date
if is_latest:
if current_date and (date is None or current_date > date):
date = current_date
return date
def derive_duration(ifc_definition_id, attribute_name):
task = Data.tasks[ifc_definition_id]
if task["TaskTime"]:
current_date = Data.task_times[task["TaskTime"]][attribute_name]
if current_date:
return current_date
for subtask in task["RelatedObjects"]:
for subtask in get_nested_tasks(task):
current_date = derive_date(subtask, attribute_name, date=date, is_earliest=is_earliest, is_latest=is_latest)
if is_earliest:
if current_date and (date is None or current_date < date):
@@ -79,3 +62,30 @@ def canonicalise_time(time):
if not time:
return "-"
return time.strftime("%d/%m/%y")
def get_nested_tasks(task):
tasks = []
for rel in task.IsNestedBy:
for object in rel.RelatedObjects:
if object.is_a("IfcTask"):
tasks.append(object)
return tasks
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:
get_task_work_schedule(parent_task)
else:
schedules = [
rel.RelatingControl
for rel in task.HasAssignments
if rel.is_a("IfcRelAssignsToControl") and rel.RelatingControl.is_a("IfcWorkSchedule")
]
print(f"Returning {schedules}")
return schedules
File diff suppressed because it is too large Load Diff
@@ -21,8 +21,9 @@ import isodate
import ifcopenshell.api
import ifcopenshell.util.attribute
from blenderbim.bim.ifc import IfcStore
from ifcopenshell.api.sequence.data import Data
from ifcopenshell.api.resource.data import Data as ResourceData
from blenderbim.bim.module.sequence.data import SequenceData
import blenderbim.bim.module.pset.data
from blenderbim.bim.prop import StrProperty, Attribute
from dateutil import parser
from bpy.types import PropertyGroup
@@ -78,17 +79,18 @@ def getTaskTimeColumns(self, context):
def getWorkSchedules(self, context):
return [(str(k), v["Name"], "") for k, v in Data.work_schedules.items()]
return [(str(k), v["Name"], "") for k, v in SequenceData.data["work_schedules"].items()]
def getWorkCalendars(self, context):
return [(str(k), v["Name"], "") for k, v in Data.work_calendars.items()]
return [(str(k), v["Name"], "") for k, v in SequenceData.data["work_calendars"].items()]
def update_active_task_index(self, context):
bpy.ops.bim.load_task_inputs()
bpy.ops.bim.load_task_resources()
bpy.ops.bim.load_task_outputs()
blenderbim.bim.module.pset.data.refresh()
def updateTaskName(self, context):
@@ -101,7 +103,7 @@ def updateTaskName(self, context):
self.file,
**{"task": self.file.by_id(self.ifc_definition_id), "attributes": {"Name": self.name}},
)
Data.load(IfcStore.get_file())
SequenceData.load()
if props.active_task_id == self.ifc_definition_id:
attribute = props.task_attributes.get("Name")
attribute.string_value = self.name
@@ -117,7 +119,7 @@ def updateTaskIdentification(self, context):
self.file,
**{"task": self.file.by_id(self.ifc_definition_id), "attributes": {"Identification": self.identification}},
)
Data.load(self.file)
SequenceData.load()
if props.active_task_id == self.ifc_definition_id:
attribute = props.task_attributes.get("Identification")
attribute.string_value = self.identification
@@ -163,10 +165,10 @@ def updateTaskTimeDateTime(self, context, startfinish):
task_time = task.TaskTime
else:
task_time = ifcopenshell.api.run("sequence.add_task_time", self.file, task=task)
Data.load(IfcStore.get_file())
SequenceData.load()
startfinish_key = "Schedule" + startfinish.capitalize()
if Data.task_times[task_time.id()][startfinish_key] == startfinish_datetime:
if SequenceData.data["task_times"][task_time.id()][startfinish_key] == startfinish_datetime:
canonical_startfinish_value = canonicalise_time(startfinish_datetime)
if startfinish_value != canonical_startfinish_value:
setattr(self, startfinish, canonical_startfinish_value)
@@ -177,7 +179,7 @@ def updateTaskTimeDateTime(self, context, startfinish):
self.file,
**{"task_time": task_time, "attributes": {startfinish_key: startfinish_datetime}},
)
Data.load(IfcStore.get_file())
SequenceData.load()
bpy.ops.bim.load_task_properties()
@@ -201,13 +203,13 @@ def updateTaskDuration(self, context):
task_time = task.TaskTime
else:
task_time = ifcopenshell.api.run("sequence.add_task_time", self.file, task=task)
Data.load(IfcStore.get_file())
SequenceData.load()
ifcopenshell.api.run(
"sequence.edit_task_time",
self.file,
**{"task_time": task_time, "attributes": {"ScheduleDuration": self.duration}},
)
Data.load(IfcStore.get_file())
SequenceData.load()
if props.active_task_id == self.ifc_definition_id:
attribute = props.task_time_attributes.get("Duration")
if attribute:
@@ -285,6 +287,7 @@ class BIMWorkPlanProperties(PropertyGroup):
active_work_plan_index: IntProperty(name="Active Work Plan Index")
active_work_plan_id: IntProperty(name="Active Work Plan Id")
work_schedules: EnumProperty(items=getWorkSchedules, name="Work Schedules")
show_work_plan_hints: BoolProperty(name="Show Hints", default=False)
class BIMWorkScheduleProperties(PropertyGroup):
@@ -326,7 +329,7 @@ class BIMWorkScheduleProperties(PropertyGroup):
editing_sequence_type: StringProperty(name="Editing Sequence Type")
active_sequence_id: IntProperty(name="Active Sequence Id")
sequence_attributes: CollectionProperty(name="Sequence Attributes", type=Attribute)
time_lag_attributes: CollectionProperty(name="Time Lag Attributes", type=Attribute)
lag_time_attributes: CollectionProperty(name="Time Lag Attributes", type=Attribute)
visualisation_start: StringProperty(name="Visualisation Start", update=update_visualisation_start)
visualisation_finish: StringProperty(name="Visualisation Finish", update=update_visualisation_finish)
speed_multiplier: FloatProperty(name="Speed Multiplier", default=10000)
@@ -349,6 +352,10 @@ class BIMWorkScheduleProperties(PropertyGroup):
task_outputs: CollectionProperty(name="Task Outputs", type=TaskProduct)
active_task_output_index: IntProperty(name="Active Task Output Index")
class BIMDuration(PropertyGroup):
duration_days: IntProperty(name="Days ")
duration_hours: IntProperty(name="Hours")
duration_minutes: IntProperty(name="Minutes")
class BIMTaskTreeProperties(PropertyGroup):
# This belongs by itself for performance reasons. https://developer.blender.org/T87737
@@ -21,11 +21,8 @@ import blenderbim.bim.helper
from bpy.types import Panel, UIList
from blenderbim.bim.ifc import IfcStore
from blenderbim.bim.helper import draw_attributes
from ifcopenshell.api.sequence.data import Data
from ifcopenshell.api.resource.data import Data as ResourceData
import blenderbim.bim.module.sequence.helper as helper
from blenderbim.bim.module.sequence.data import SequenceData
from datetime import datetime
from ifcopenshell.api.resource.data import Data as ResourceData
class BIM_PT_work_plans(Panel):
@@ -48,13 +45,15 @@ class BIM_PT_work_plans(Panel):
self.props = context.scene.BIMWorkPlanProperties
row = self.layout.row()
row.label(
text="{} Work Plans Found".format(SequenceData.number_of_work_plans_loaded),
icon="TEXT",
)
if SequenceData.data["has_work_plans"]:
row.label(
text="{} Work Plans Found".format(SequenceData.data["number_of_work_plans_loaded"]),
icon="TEXT",
)
else:
row.label(text="No Work Plans found.", icon="TEXT")
row.operator("bim.add_work_plan", icon="ADD", text="")
for work_plan_id, work_plan in SequenceData.work_plans.items():
for work_plan_id, work_plan in SequenceData.data["work_plans"].items():
self.draw_work_plan_ui(work_plan_id, work_plan)
def draw_work_plan_ui(self, work_plan_id, work_plan):
@@ -62,7 +61,8 @@ class BIM_PT_work_plans(Panel):
row.label(text=work_plan["Name"] or "Unnamed", icon="TEXT")
if self.props.active_work_plan_id == work_plan_id:
row.operator("bim.edit_work_plan", text="", icon="CHECKMARK")
if self.props.editing_type == "ATTRIBUTES":
row.operator("bim.edit_work_plan", text="", icon="CHECKMARK")
row.operator("bim.disable_editing_work_plan", text="", icon="CANCEL")
elif self.props.active_work_plan_id:
row.operator("bim.remove_work_plan", text="", icon="X").work_plan = work_plan_id
@@ -83,19 +83,25 @@ class BIM_PT_work_plans(Panel):
draw_attributes(self.props.work_plan_attributes, self.layout)
def draw_work_schedule_ui(self):
row = self.layout.row(align=True)
row.prop(self.props, "work_schedules", text="")
op = row.operator("bim.assign_work_schedule", text="", icon="ADD")
op.work_plan = self.props.active_work_plan_id
op.work_schedule = int(self.props.work_schedules)
if not SequenceData.is_loaded:
SequenceData.load()
for work_schedule_id in Data.work_plans[self.props.active_work_plan_id]["IsDecomposedBy"]:
work_schedule = Data.work_schedules[work_schedule_id]
if SequenceData.data["has_work_schedules"]:
row = self.layout.row(align=True)
row.label(text=work_schedule["Name"] or "Unnamed", icon="LINENUMBERS_ON")
op = row.operator("bim.unassign_work_schedule", text="", icon="X")
row.prop(self.props, "work_schedules", text="")
op = row.operator("bim.assign_work_schedule", text="", icon="ADD")
op.work_plan = self.props.active_work_plan_id
op.work_schedule = int(self.props.work_schedules)
for work_schedule_id in SequenceData.data["work_plans"][self.props.active_work_plan_id]["IsDecomposedBy"]:
work_schedule = SequenceData.data["work_schedules"][work_schedule_id]
row = self.layout.row(align=True)
row.label(text=work_schedule["Name"] or "Unnamed", icon="LINENUMBERS_ON")
op = row.operator("bim.unassign_work_schedule", text="", icon="X")
op.work_plan = self.props.active_work_plan_id
op.work_schedule = int(self.props.work_schedules)
else:
row = self.layout.row()
row.label(text="Must Create a WorkSchedule First. See Work Schedule Panel", icon="INFO")
class BIM_PT_work_schedules(Panel):
@@ -113,23 +119,29 @@ class BIM_PT_work_schedules(Panel):
return file and hasattr(file, "schema") and file.schema != "IFC2X3"
def draw(self, context):
if not SequenceData.is_loaded:
SequenceData.load()
self.props = context.scene.BIMWorkScheduleProperties
self.tprops = context.scene.BIMTaskTreeProperties
if not Data.is_loaded:
Data.load(IfcStore.get_file())
row = self.layout.row()
row.operator("bim.add_work_schedule", icon="ADD")
if SequenceData.data["has_work_schedules"]:
row.label(
text="{} Work Schedules Found".format(SequenceData.data["number_of_work_schedules_loaded"]),
icon="TEXT",
)
else:
row.label(text="No Work Schedules found.", icon="TEXT")
row.operator("bim.add_work_schedule", text="", icon="ADD")
for work_schedule_id, work_schedule in Data.work_schedules.items():
for work_schedule_id, work_schedule in SequenceData.data["work_schedules"].items():
self.draw_work_schedule_ui(work_schedule_id, work_schedule)
def draw_work_schedule_ui(self, work_schedule_id, work_schedule):
row = self.layout.row(align=True)
row.label(text=work_schedule["Name"] or "Unnamed", icon="LINENUMBERS_ON")
if self.props.active_work_schedule_id and self.props.active_work_schedule_id == work_schedule_id:
if self.props.active_work_schedule_id == work_schedule_id:
if self.props.editing_type == "WORK_SCHEDULE":
row.operator("bim.edit_work_schedule", text="", icon="CHECKMARK")
elif self.props.editing_type == "TASKS":
@@ -139,23 +151,23 @@ class BIM_PT_work_schedules(Panel):
row.operator("bim.recalculate_schedule", text="", icon="FILE_REFRESH").work_schedule = work_schedule_id
row.operator("bim.add_summary_task", text="", icon="ADD").work_schedule = work_schedule_id
row.operator("bim.disable_editing_work_schedule", text="", icon="CANCEL")
elif self.props.active_work_schedule_id:
row.operator("bim.remove_work_schedule", text="", icon="X").work_schedule = work_schedule_id
else:
row.operator("bim.enable_editing_tasks", text="", icon="ACTION").work_schedule = work_schedule_id
row.operator(
"bim.enable_editing_work_schedule_tasks", text="", icon="ACTION"
).work_schedule = work_schedule_id
row.operator(
"bim.enable_editing_work_schedule", text="", icon="GREASEPENCIL"
).work_schedule = work_schedule_id
row.operator("bim.remove_work_schedule", text="", icon="X").work_schedule = work_schedule_id
if self.props.active_work_schedule_id == work_schedule_id:
if self.props.should_show_column_ui:
self.draw_column_ui()
if self.props.should_show_visualisation_ui:
self.draw_visualisation_ui()
if self.props.editing_type == "WORK_SCHEDULE":
self.draw_editable_work_schedule_ui()
elif self.props.editing_type == "TASKS":
if self.props.should_show_column_ui:
self.draw_column_ui()
if self.props.should_show_visualisation_ui:
self.draw_visualisation_ui()
self.draw_editable_task_ui(work_schedule_id)
def draw_task_operators(self):
@@ -250,68 +262,70 @@ class BIM_PT_work_schedules(Panel):
self.draw_editable_task_time_attributes_ui()
def draw_editable_task_sequence_ui(self):
task = Data.tasks[self.props.active_task_id]
task = SequenceData.data["tasks"][self.props.active_task_id]
row = self.layout.row()
row.label(text="{} Predecessors".format(len(task["IsSuccessorFrom"])), icon="BACK")
for sequence_id in task["IsSuccessorFrom"]:
self.draw_editable_sequence_ui(Data.sequences[sequence_id], "RelatingProcess")
self.draw_editable_sequence_ui(SequenceData.data["sequences"][sequence_id], "RelatingProcess")
row = self.layout.row()
row.label(text="{} Successors".format(len(task["IsPredecessorTo"])), icon="FORWARD")
for sequence_id in task["IsPredecessorTo"]:
self.draw_editable_sequence_ui(Data.sequences[sequence_id], "RelatedProcess")
self.draw_editable_sequence_ui(SequenceData.data["sequences"][sequence_id], "RelatedProcess")
def draw_editable_sequence_ui(self, sequence, process_type):
task = Data.tasks[sequence[process_type]]
task = SequenceData.data["tasks"][sequence[process_type]]
row = self.layout.row(align=True)
row.label(text=task["Identification"] or "XXX")
row.label(text=task["Name"] or "Unnamed")
row.label(text=sequence["SequenceType"] or "N/A")
if sequence["TimeLag"]:
row.operator("bim.unassign_lag_time", text="", icon="X").sequence = sequence["id"]
row.label(text=isodate.duration_isoformat(Data.lag_times[sequence["TimeLag"]]["LagValue"]))
row.label(text=isodate.duration_isoformat(SequenceData.data["lag_times"][sequence["TimeLag"]]["LagValue"]))
else:
row.operator("bim.assign_lag_time", text="", icon="ADD").sequence = sequence["id"]
row.label(text="N/A")
row.operator("bim.assign_lag_time", text="Add Time Lag", icon="ADD").sequence = sequence["id"]
if self.props.active_sequence_id == sequence["id"]:
if self.props.editing_sequence_type == "ATTRIBUTES":
row.operator("bim.edit_sequence_attributes", text="", icon="CHECKMARK")
row.operator("bim.disable_editing_sequence", text="", icon="CANCEL")
self.draw_editable_sequence_attributes_ui()
elif self.props.editing_sequence_type == "TIME_LAG":
op = row.operator("bim.edit_sequence_time_lag", text="", icon="CHECKMARK")
elif self.props.editing_sequence_type == "LAG_TIME":
op = row.operator("bim.edit_sequence_lag_time", text="", icon="CHECKMARK")
op.lag_time = sequence["TimeLag"]
row.operator("bim.disable_editing_sequence", text="", icon="CANCEL")
self.draw_editable_sequence_time_lag_ui()
self.draw_editable_sequence_lag_time_ui()
else:
if sequence["TimeLag"]:
op = row.operator("bim.enable_editing_sequence_time_lag", text="", icon="CON_LOCKTRACK")
op = row.operator("bim.enable_editing_sequence_lag_time", text="Edit Time Lag", icon="CON_LOCKTRACK")
op.sequence = sequence["id"]
op.lag_time = sequence["TimeLag"]
op = row.operator("bim.enable_editing_sequence_attributes", text="", icon="GREASEPENCIL")
op = row.operator("bim.enable_editing_sequence_attributes", text="Edit Sequence", icon="GREASEPENCIL")
op.sequence = sequence["id"]
def draw_editable_sequence_attributes_ui(self):
blenderbim.bim.helper.draw_attributes(self.props.sequence_attributes, self.layout)
def draw_editable_sequence_time_lag_ui(self):
blenderbim.bim.helper.draw_attributes(self.props.time_lag_attributes, self.layout)
def draw_editable_sequence_lag_time_ui(self):
blenderbim.bim.helper.draw_attributes(self.props.lag_time_attributes, self.layout)
def draw_editable_task_calendar_ui(self):
task = Data.tasks[self.props.active_task_id]
task = SequenceData.data["tasks"][self.props.active_task_id]
if task["HasAssignmentsWorkCalendar"]:
row = self.layout.row(align=True)
calendar = Data.work_calendars[task["HasAssignmentsWorkCalendar"][0]]
calendar = SequenceData.data["work_calendars"][task["HasAssignmentsWorkCalendar"][0]]
row.label(text=calendar["Name"] or "Unnamed")
op = row.operator("bim.remove_task_calendar", text="", icon="X")
op.work_calendar = task["HasAssignmentsWorkCalendar"][0]
op.task = self.props.active_task_id
else:
elif SequenceData.data["has_work_calendars"]:
row = self.layout.row(align=True)
row.prop(self.props, "work_calendars", text="")
op = row.operator("bim.edit_task_calendar", text="", icon="ADD")
op.work_calendar = int(self.props.work_calendars)
op.task = self.props.active_task_id
else:
row = self.layout.row(align=True)
row.label(text="Must Create a Calendar First. See Work Calendar Panel", icon="INFO")
def draw_editable_task_attributes_ui(self):
blenderbim.bim.helper.draw_attributes(
@@ -353,16 +367,22 @@ class BIM_PT_task_icom(Panel):
row2 = col.row(align=True)
row2.label(text="Inputs")
total_task_inputs = len(self.props.task_inputs)
if context.selected_objects:
op = row2.operator("bim.assign_process", icon="ADD", text="")
op.task = task.ifc_definition_id
op.related_object_type = "PRODUCT"
op.related_object = ""
if total_task_inputs:
op = row2.operator("bim.unassign_process", icon="REMOVE", text="")
op.task = task.ifc_definition_id
op.related_object_type = "PRODUCT"
op.related_object = ""
if not context.selected_objects and self.props.active_task_input_index < total_task_inputs:
input_id = self.props.task_inputs[self.props.active_task_input_index].ifc_definition_id
op.related_object = input_id
op = row2.operator("bim.select_task_related_inputs", icon="RESTRICT_SELECT_OFF", text="")
op.task = task.ifc_definition_id
row2 = col.row()
row2.template_list("BIM_UL_task_inputs", "", self.props, "task_inputs", self.props, "active_task_input_index")
@@ -376,14 +396,17 @@ class BIM_PT_task_icom(Panel):
op = row2.operator("bim.calculate_task_duration", text="", icon="TEMP")
op.task = task.ifc_definition_id
total_resources = len(context.scene.BIMResourceTreeProperties.resources)
resource_props = context.scene.BIMResourceProperties
resource_tprops = context.scene.BIMResourceTreeProperties
total_resources = len(resource_tprops.resources)
if total_resources and context.scene.BIMResourceProperties.active_resource_index < total_resources:
op = row2.operator("bim.assign_process", icon="ADD", text="")
op.task = task.ifc_definition_id
op.related_object_type = "RESOURCE"
op.resource = context.scene.BIMResourceTreeProperties.resources[
context.scene.BIMResourceProperties.active_resource_index
].ifc_definition_id
resource_id = resource_tprops.resources[resource_props.active_resource_index].ifc_definition_id
ResourceData.load(IfcStore.get_file())
resource = ResourceData.resources[resource_id]
if resource["type"] != "IfcCrewResource":
op = row2.operator("bim.assign_process", icon="ADD", text="")
op.task = task.ifc_definition_id
op.related_object_type = "RESOURCE"
total_task_resources = len(self.props.task_resources)
if total_task_resources and self.props.active_task_resource_index < total_task_resources:
@@ -402,14 +425,17 @@ class BIM_PT_task_icom(Panel):
row2 = col.row(align=True)
row2.label(text="Outputs")
total_task_outputs = len(self.props.task_outputs)
if context.selected_objects:
op = row2.operator("bim.assign_product", icon="ADD", text="")
op.task = task.ifc_definition_id
op.relating_product = ""
if total_task_outputs:
op = row2.operator("bim.unassign_product", icon="REMOVE", text="")
op.task = task.ifc_definition_id
op.relating_product = ""
if not context.selected_objects and self.props.active_task_output_index < total_task_outputs:
output_id = self.props.task_outputs[self.props.active_task_output_index].ifc_definition_id
op.relating_product = output_id
op = row2.operator("bim.select_task_related_products", icon="RESTRICT_SELECT_OFF", text="")
op.task = task.ifc_definition_id
@@ -558,14 +584,20 @@ class BIM_PT_work_calendars(Panel):
return file and hasattr(file, "schema") and file.schema != "IFC2X3"
def draw(self, context):
if not Data.is_loaded:
Data.load(IfcStore.get_file())
if not SequenceData.is_loaded:
SequenceData.load()
self.props = context.scene.BIMWorkCalendarProperties
row = self.layout.row()
row.operator("bim.add_work_calendar", icon="ADD")
for work_calendar_id, work_calendar in Data.work_calendars.items():
if SequenceData.data["has_work_calendars"]:
row.label(
text="{} Work Calendars Found".format(SequenceData.data["number_of_work_calendars_loaded"]),
icon="TEXT",
)
else:
row.label(text="No Work Calendars found.", icon="TEXT")
row.operator("bim.add_work_calendar", icon="ADD", text="")
for work_calendar_id, work_calendar in SequenceData.data["work_calendars"].items():
self.draw_work_calendar_ui(work_calendar_id, work_calendar)
def draw_work_calendar_ui(self, work_calendar_id, work_calendar):
@@ -600,10 +632,10 @@ class BIM_PT_work_calendars(Panel):
op.time_type = "ExceptionTimes"
for work_time_id in work_calendar["WorkingTimes"]:
self.draw_work_time_ui(Data.work_times[work_time_id], time_type="WorkingTimes")
self.draw_work_time_ui(SequenceData.data["work_times"][work_time_id], time_type="WorkingTimes")
for work_time_id in work_calendar["ExceptionTimes"]:
self.draw_work_time_ui(Data.work_times[work_time_id], time_type="ExceptionTimes")
self.draw_work_time_ui(SequenceData.data["work_times"][work_time_id], time_type="ExceptionTimes")
def draw_work_time_ui(self, work_time, time_type):
row = self.layout.row(align=True)
@@ -628,7 +660,9 @@ class BIM_PT_work_calendars(Panel):
def draw_editable_work_time_ui(self, work_time):
draw_attributes(self.props.work_time_attributes, self.layout)
if work_time["RecurrencePattern"]:
self.draw_editable_recurrence_pattern_ui(Data.recurrence_patterns[work_time["RecurrencePattern"]])
self.draw_editable_recurrence_pattern_ui(
SequenceData.data["recurrence_patterns"][work_time["RecurrencePattern"]]
)
else:
row = self.layout.row(align=True)
row.prop(self.props, "recurrence_types", icon="RECOVER_LAST", text="")
@@ -650,7 +684,7 @@ class BIM_PT_work_calendars(Panel):
op.recurrence_pattern = recurrence_pattern["id"]
for time_period_id in recurrence_pattern["TimePeriods"]:
time_period = Data.time_periods[time_period_id]
time_period = SequenceData.data["time_periods"][time_period_id]
row = box.row(align=True)
row.label(text="{} - {}".format(time_period["StartTime"], time_period["EndTime"]), icon="TIME")
op = row.operator("bim.remove_time_period", text="", icon="X")
+416 -8
View File
@@ -17,14 +17,12 @@
# along with BlenderBIM Add-on. If not, see <http://www.gnu.org/licenses/>.
def add_work_plan(ifc, sequence):
ifc.run("sequence.add_work_plan")
sequence.load_work_plans()
def add_work_plan(ifc):
return ifc.run("sequence.add_work_plan")
def remove_work_plan(ifc, sequence, work_plan=None):
def remove_work_plan(ifc, work_plan=None):
ifc.run("sequence.remove_work_plan", work_plan=work_plan)
sequence.load_work_plans()
def enable_editing_work_plan(sequence, work_plan=None):
@@ -36,9 +34,419 @@ def disable_editing_work_plan(sequence):
sequence.disable_editing_work_plan()
def edit_work_plan(ifc, sequence):
work_plan = sequence.get_current_ifc_work_plan()
def edit_work_plan(ifc, sequence, work_plan=None):
attributes = sequence.get_work_plan_attributes()
ifc.run("sequence.edit_work_plan", work_plan=work_plan, attributes=attributes)
sequence.disable_editing_work_plan()
sequence.load_work_plans()
def edit_work_schedule(ifc, sequence, work_schedule=None):
attributes = sequence.get_work_schedule_attributes()
ifc.run("sequence.edit_work_schedule", **{"work_schedule": work_schedule, "attributes": attributes})
sequence.disable_editing_work_schedule()
def enable_editing_work_plan_schedules(sequence, work_plan=None):
sequence.enable_editing_work_plan_schedules(work_plan)
def add_work_schedule(ifc):
return ifc.run("sequence.add_work_schedule")
def remove_work_schedule(ifc, work_schedule=None):
ifc.run("sequence.remove_work_schedule", **{"work_schedule": work_schedule})
def assign_work_schedule(ifc, sequence, work_plan=None, work_schedule=None):
if work_schedule:
sequence.hide_work_plan_hints()
return ifc.run("aggregate.assign_object", **{"relating_object": work_plan, "product": work_schedule})
else:
sequence.show_work_plan_hints()
def unassign_work_schedule(ifc, work_plan=None, work_schedule=None):
ifc.run("aggregate.unassign_object", **{"relating_object": work_plan, "product": work_schedule})
def enable_editing_work_schedule(sequence, work_schedule=None):
sequence.load_work_schedule_attributes(work_schedule)
sequence.enable_editing_work_schedule(work_schedule)
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_properties()
def create_task_tree(sequence, work_schedule):
sequence.create_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_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_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_properties()
sequence.disable_selecting_deleted_task()
def load_task_properties(sequence):
sequence.load_task_properties()
def disable_editing_work_schedule(sequence):
sequence.disable_editing_work_schedule()
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_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_properties()
def enable_editing_task(sequence, task=None):
sequence.load_task_attributes(task)
sequence.enable_editing_task(task)
def edit_task(ifc, sequence, task=None):
attributes = sequence.get_task_attributes()
ifc.run("sequence.edit_task", **{"task": task, "attributes": attributes})
sequence.load_task_properties(task=task)
sequence.disable_editing_task()
def copy_task_attribute(ifc, sequence, attribute_name=None):
for task in sequence.get_checked_tasks():
ifc.run(
"sequence.edit_task",
**{"task": task, "attributes": {attribute_name: sequence.get_task_attribute_value(attribute_name)}}
)
sequence.load_task_properties(task)
def disable_editing_task(sequence):
sequence.disable_editing_task()
def enable_editing_task_time(ifc, sequence, task=None):
task_time = sequence.get_task_time(task)
if task_time is None:
task_time = ifc.run("sequence.add_task_time", **{"task": task})
sequence.load_task_time_attributes(task_time)
sequence.enable_editing_task_time(task)
def edit_task_time(ifc, sequence, task_time=None):
attributes = sequence.get_task_time_attributes()
print(task_time)
ifc.run("sequence.edit_task_time", **{"task_time": task_time, "attributes": attributes}) # nasty loop goes on when calendar props are messed up
task = sequence.get_active_task()
sequence.load_task_properties(task=task)
sequence.disable_editing_task_time()
def assign_predecessor(ifc, sequence, task=None):
predecessor_task = sequence.get_active_task()
ifc.run("sequence.assign_sequence", **{"relating_process": task, "related_process": predecessor_task})
sequence.load_task_properties()
def unassign_predecessor(ifc, sequence, task=None):
predecessor_task = sequence.get_active_task()
ifc.run("sequence.unassign_sequence", **{"relating_process": task, "related_process": predecessor_task})
sequence.load_task_properties()
def assign_successor(ifc, sequence, task=None):
successor_task = sequence.get_active_task()
ifc.run("sequence.assign_sequence", **{"relating_process": successor_task, "related_process": task})
sequence.load_task_properties()
def unassign_successor(ifc, sequence, task=None):
successor_task = sequence.get_active_task()
ifc.run("sequence.unassign_sequence", **{"relating_process": successor_task, "related_process": task})
sequence.load_task_properties()
def assign_products(ifc, sequence, task=None, products=None):
if not products:
products = sequence.get_selected_products()
for product in products:
ifc.run("sequence.assign_product", **{"relating_product": product, "related_object": task})
outputs = sequence.get_task_outputs(task)
sequence.load_task_outputs(outputs)
def unassign_products(ifc, sequence, task=None, products=None):
if not products:
products = sequence.get_selected_products()
for product in products:
ifc.run("sequence.unassign_product", **{"relating_product": product, "related_object": task})
outputs = sequence.get_task_outputs(task)
sequence.load_task_outputs(outputs)
def assign_input_products(ifc, sequence, task=None, products=None):
if not products:
products = sequence.get_selected_products()
for product in products:
ifc.run("sequence.assign_process", **{"relating_process": task, "related_object": product})
inputs = sequence.get_task_inputs(task)
sequence.load_task_inputs(inputs)
def unassign_input_products(ifc, sequence, task=None, products=None):
if not products:
products = sequence.get_selected_products()
for product in products:
ifc.run("sequence.unassign_process", **{"relating_process": task, "related_object": product})
inputs = sequence.get_task_inputs(task)
sequence.load_task_inputs(inputs)
def assign_resource(ifc, sequence, task=None):
resource = sequence.get_selected_resource()
sub_resource = ifc.run(
"resource.add_resource", **{"parent_resource": resource, "ifc_class": resource.is_a(), "name": resource.Name}
)
ifc.run("sequence.assign_process", **{"relating_process": task, "related_object": sub_resource})
resources = sequence.get_task_resources(task)
sequence.load_task_resources(resources)
sequence.load_resources()
def unassign_resource(ifc, sequence, task=None, resource=None):
ifc.run("sequence.unassign_process", **{"relating_process": task, "related_object": resource})
ifc.run("resource.remove_resource", **{"resource": resource})
resources = sequence.get_task_resources(task)
sequence.load_task_resources(resources)
sequence.load_resources()
def load_task_outputs(sequence):
task = sequence.get_highlighted_task()
outputs = sequence.get_task_outputs(task)
sequence.load_task_outputs(outputs)
def load_task_inputs(sequence):
task = sequence.get_highlighted_task()
inputs = sequence.get_task_inputs(task)
sequence.load_task_inputs(inputs)
def load_task_resources(sequence):
task = sequence.get_highlighted_task()
resources = sequence.get_task_resources(task)
sequence.load_task_resources(resources)
def remove_work_calendar(ifc, work_calendar=None):
ifc.run("sequence.remove_work_calendar", **{"work_calendar": work_calendar})
def add_work_calendar(ifc):
return ifc.run("sequence.add_work_calendar")
def edit_work_calendar(ifc, sequence, work_calendar=None):
attributes = sequence.get_work_calendar_attributes()
ifc.run("sequence.edit_work_calendar", **{"work_calendar": work_calendar, "attributes": attributes})
sequence.disable_editing_work_calendar()
sequence.load_task_properties()
def enable_editing_work_calendar(sequence, work_calendar=None):
sequence.load_work_calendar_attributes(work_calendar)
sequence.enable_editing_work_calendar(work_calendar)
def disable_editing_work_calendar(sequence):
sequence.disable_editing_work_calendar()
def enable_editing_work_calendar_times(sequence, work_calendar=None):
sequence.enable_editing_work_calendar_times(work_calendar)
def add_work_time(ifc, work_calendar=None, time_type=None):
return ifc.run("sequence.add_work_time", **{"work_calendar": work_calendar, "time_type": time_type})
def enable_editing_work_time(sequence, work_time=None):
sequence.load_work_time_attributes(work_time)
sequence.enable_editing_work_time(work_time)
def disable_editing_work_time(sequence):
sequence.disable_editing_work_time()
def remove_work_time(ifc, work_time=None):
ifc.run("sequence.remove_work_time", **{"work_time": work_time})
def edit_work_time(ifc, sequence):
work_time = sequence.get_active_work_time()
ifc.run("sequence.edit_work_time", **{"work_time": work_time, "attributes": sequence.get_work_time_attributes()})
recurrence_pattern = work_time.RecurrencePattern
if recurrence_pattern:
ifc.run(
"sequence.edit_recurrence_pattern",
**{
"recurrence_pattern": recurrence_pattern,
"attributes": sequence.get_recurrence_pattern_attributes(recurrence_pattern),
}
)
sequence.disable_editing_work_time()
def assign_recurrence_pattern(ifc, work_time=None, recurrence_type=None):
return ifc.run("sequence.assign_recurrence_pattern", **{"parent": work_time, "recurrence_type": recurrence_type})
def unassign_recurrence_pattern(ifc, recurrence_pattern=None):
ifc.run("sequence.unassign_recurrence_pattern", **{"recurrence_pattern": recurrence_pattern})
def add_time_period(ifc, sequence, recurrence_pattern=None):
start_time, end_time = sequence.get_recurrence_pattern_times()
ifc.run(
"sequence.add_time_period",
**{"recurrence_pattern": recurrence_pattern, "start_time": start_time, "end_time": end_time}
)
sequence.reset_time_period()
def remove_time_period(ifc, time_period=None):
ifc.run("sequence.remove_time_period", **{"time_period": time_period})
def enable_editing_task_calendar(sequence, task=None):
sequence.enable_editing_task_calendar(task)
def edit_task_calendar(ifc, sequence, task=None, work_calendar=None):
ifc.run("control.assign_control", **{"relating_control": work_calendar, "related_object": task})
ifc.run("sequence.cascade_schedule", **{"task": task})
sequence.load_task_properties()
def remove_task_calendar(ifc, sequence, task=None, work_calendar=None):
ifc.run("control.unassign_control", **{"relating_control": work_calendar, "related_object": task})
ifc.run("sequence.cascade_schedule", **{"task": task})
sequence.load_task_properties()
def enable_editing_task_sequence(sequence, task=None):
sequence.enable_editing_task_sequence(task)
sequence.load_task_properties()
def disable_editing_task_sequence(sequence, task=None):
sequence.enable_editing_task_sequence(task)
sequence.load_task_properties()
def disable_editing_task_time(sequence):
sequence.disable_editing_task_time()
def enable_editing_sequence_attributes(sequence, rel_sequence=None):
sequence.enable_editing_rel_sequence_attributes(rel_sequence)
sequence.load_rel_sequence_attributes(rel_sequence)
def enable_editing_sequence_lag_time(sequence, rel_sequence=None, lag_time=None):
sequence.load_lag_time_attributes(lag_time)
sequence.enable_editing_sequence_lag_time(rel_sequence)
def unassign_lag_time(ifc, sequence, rel_sequence=None):
ifc.run("sequence.unassign_lag_time", **{"rel_sequence": rel_sequence})
sequence.load_task_properties()
def assign_lag_time(ifc, rel_sequence=None):
ifc.run("sequence.assign_lag_time", **{"rel_sequence": rel_sequence, "lag_value": "P1D"})
def edit_sequence_attributes(ifc, sequence, rel_sequence=None):
attributes = sequence.get_rel_sequence_attributes()
ifc.run("sequence.edit_sequence", **{"rel_sequence": rel_sequence, "attributes": attributes})
sequence.disable_editing_rel_sequence()
sequence.load_task_properties()
def edit_sequence_lag_time(ifc, sequence, lag_time=None):
attributes = sequence.get_lag_time_attributes()
ifc.run("sequence.edit_lag_time", **{"lag_time": lag_time, "attributes": attributes})
sequence.disable_editing_rel_sequence()
sequence.load_task_properties()
def disable_editing_rel_sequence(sequence):
sequence.disable_editing_rel_sequence()
def select_task_outputs(ifc, sequence, task=None):
outputs = sequence.get_task_outputs(task) ## should this be from the api instead ?
sequence.select_task_products(outputs)
def select_task_inputs(ifc, sequence, task=None):
inputs = sequence.get_task_inputs(task) ## should this be from the api instead ?
print(inputs)
sequence.select_task_products(inputs)
def recalculate_schedule(ifc, work_schedule=None):
ifc.run("sequence.recalculate_schedule", **{"work_schedule": work_schedule})
def add_task_column(sequence, column_type=None, name=None, data_type=None):
sequence.add_task_column(column_type, name, data_type)
def remove_task_column(sequence, name=None):
sequence.remove_task_column(name)
def set_task_sort_column(sequence, column=None):
sequence.set_task_sort_column(column)
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_properties()
+72 -6
View File
@@ -423,13 +423,79 @@ class Selector:
@interface
class Sequence:
def disable_editing_work_plan(cls): pass
def get_work_plan_attributes(cls): pass
def load_work_plan_attributes(cls, work_plan): pass
def get_nested_tasks(cls, task):pass
def enable_editing_work_plan(cls, work_plan): pass
def export_attributes(cls): pass
def get_current_ifc_work_plan(cls): pass
def get_ifc_work_plan_attributes(cls): pass
def load_work_plan_attributes(cls): pass
def load_work_plans(cls): pass
def disable_editing_work_plan(cls): pass
def enable_editing_work_plan_schedules(cls, work_plan): pass
def get_work_schedule_attributes(cls): pass
def load_work_schedule_attributes(cls, work_schedule): pass
def enable_editing_work_schedule(cls,work_schedule): pass
def disable_editing_work_schedule(cls): pass
def enable_editing_work_schedule_tasks(cls, work_schedule): pass
def create_task_tree(cls, work_schedule): pass
def load_task_properties(cls, task): pass
def hide_work_plan_hints(cls): pass
def show_work_plan_hints(cls): pass
def get_active_work_schedule_id(cls): pass
def get_selected_resource(cls): pass
def expand_task(cls, task): pass
def contract_task(cls, task): pass
def disable_work_schedule(cls): pass
def disable_selecting_deleted_task(cls): pass
def get_checked_tasks(cls): pass
def get_task_attribute_value(cls, attribute_name): pass
def get_active_task(cls): pass
def get_task_time(cls, task): pass
def load_task_attributes(cls, task): pass
def get_selected_products(cls): pass
def enable_editing_task(cls, task): pass
def get_task_attributes(cls): pass
def load_task_time_attributes(cls, task_time): pass
def enable_editing_task_time(cls, task): pass
def disable_editing_task(cls): pass
def get_task_time_attributes(cls): pass
def load_task_resources(cls,resources): pass
def load_resources(cls): pass
def get_task_inputs(cls, task): pass
def load_task_inputs(cls, inputs): pass
def load_task_outputs(cls, outputs): pass
def get_highlighted_task(cls): pass
def get_task_outputs(cls, task): pass
def get_task_resources(cls, task):pass
def enable_editing_work_calendar_times(cls, work_calendar): pass
def load_work_calendar_attributes(cls, work_calendar): pass
def enable_editing_work_calendar(cls, work_calendar): pass
def disable_editing_work_calendar(cls): pass
def get_work_calendar_attributes(cls): pass
def load_work_time_attributes(cls, work_time): pass
def enable_editing_work_time(cls, work_time): pass
def get_work_time_attributes(cls): pass
def get_recurrence_pattern_attributes(cls, recurrence_pattern): pass
def disable_editing_work_time(cls): pass
def get_recurrence_pattern_times(cls): pass
def reset_time_period(cls): pass
def enable_editing_task_calendar(cls, task): pass
def enable_editing_task_sequence(cls, task): pass
def disable_editing_task_time(cls): pass
def load_rel_sequence_attributes(cls, rel_sequence): pass
def enable_editing_rel_sequence_attributes(cls, rel_sequence): pass
def load_lag_time_attributes(cls, lag_time): pass
def enable_editing_sequence_lag_time(cls, rel_sequence): pass
def get_rel_sequence_attributes(cls): pass
def disable_editing_rel_sequence(cls): pass
def get_lag_time_attributes(cls): pass
def select_task_products(cls, products): pass
def add_task_column(cls, column_type, name, data_type): pass
def remove_task_column(cls, name): pass
def set_task_sort_column(cls, column): pass
def find_related_output_tasks(cls, column): pass
def get_root_task(cls, task): pass
def get_task_work_schedule(cls, task): pass
def is_work_schedule_active(cls, work_schedule): pass
def highlight_task(cls, task): pass
@interface
+1 -1
View File
@@ -40,9 +40,9 @@ from blenderbim.tool.project import Project
from blenderbim.tool.pset import Pset
from blenderbim.tool.qto import Qto
from blenderbim.tool.root import Root
from blenderbim.tool.sequence import Sequence
from blenderbim.tool.spatial import Spatial
from blenderbim.tool.structural import Structural
from blenderbim.tool.sequence import Sequence
from blenderbim.tool.style import Style
from blenderbim.tool.surveyor import Surveyor
from blenderbim.tool.system import System
+709 -35
View File
@@ -15,8 +15,11 @@
#
# You should have received a copy of the GNU General Public License
# along with BlenderBIM Add-on. If not, see <http://www.gnu.org/licenses/>.
from dateutil import parser
import bpy
import re
import isodate
from datetime import datetime
import ifcopenshell
import json
import blenderbim.core.tool
@@ -26,40 +29,6 @@ import blenderbim.bim.module.sequence.helper as helper
class Sequence(blenderbim.core.tool.Sequence):
@classmethod
def load_work_plans(cls):
props = bpy.context.scene.BIMWorkPlanProperties
props.work_plans.clear()
for work_plan in tool.Ifc.get().by_type("IfcWorkPlan"):
new = props.work_plans.add()
new.ifc_definition_id = work_plan.id()
new.name = work_plan.Name or "Unnamed"
@classmethod
def enable_editing_work_plan(cls, work_plan):
if work_plan:
bpy.context.scene.BIMWorkPlanProperties.active_work_plan_id = work_plan.id()
bpy.context.scene.BIMWorkPlanProperties.editing_type = "ATTRIBUTES"
@classmethod
def disable_editing_work_plan(cls):
bpy.context.scene.BIMWorkPlanProperties.active_work_plan_id = 0
@classmethod
def get_current_ifc_work_plan(cls):
return tool.Ifc.get().by_id(bpy.context.scene.BIMWorkPlanProperties.active_work_plan_id)
@classmethod
def load_work_plan_attributes(cls, work_plan):
def callback(name, prop, data):
if name in ["CreationDate", "StartTime", "FinishTime"]:
prop.string_value = "" if prop.is_null else data[name]
return True
props = bpy.context.scene.BIMWorkPlanProperties
props.work_plan_attributes.clear()
blenderbim.bim.helper.import_attributes2(work_plan, props.work_plan_attributes, callback)
@classmethod
def get_work_plan_attributes(cls):
def callback(attributes, prop):
@@ -78,3 +47,708 @@ class Sequence(blenderbim.core.tool.Sequence):
props = bpy.context.scene.BIMWorkPlanProperties
return blenderbim.bim.helper.export_attributes(props.work_plan_attributes, callback)
@classmethod
def load_work_plan_attributes(cls, work_plan):
def callback(name, prop, data):
if name in ["CreationDate", "StartTime", "FinishTime"]:
prop.string_value = "" if prop.is_null else data[name]
return True
props = bpy.context.scene.BIMWorkPlanProperties
props.work_plan_attributes.clear()
blenderbim.bim.helper.import_attributes2(work_plan, props.work_plan_attributes, callback)
@classmethod
def enable_editing_work_plan(cls, work_plan):
if work_plan:
bpy.context.scene.BIMWorkPlanProperties.active_work_plan_id = work_plan.id()
bpy.context.scene.BIMWorkPlanProperties.editing_type = "ATTRIBUTES"
@classmethod
def disable_editing_work_plan(cls):
bpy.context.scene.BIMWorkPlanProperties.active_work_plan_id = 0
@classmethod
def enable_editing_work_plan_schedules(cls, work_plan):
if work_plan:
bpy.context.scene.BIMWorkPlanProperties.active_work_plan_id = work_plan.id()
bpy.context.scene.BIMWorkPlanProperties.editing_type = "SCHEDULES"
@classmethod
def get_work_schedule_attributes(cls):
def callback(attributes, prop):
if "Date" in prop.name or "Time" in prop.name:
if prop.is_null:
attributes[prop.name] = None
return True
attributes[prop.name] = helper.parse_datetime(prop.string_value)
return True
elif prop.name == "Duration" or prop.name == "TotalFloat":
if prop.is_null:
attributes[prop.name] = None
return True
attributes[prop.name] = helper.parse_duration(prop.string_value)
return True
props = bpy.context.scene.BIMWorkScheduleProperties
return blenderbim.bim.helper.export_attributes(props.work_schedule_attributes, callback)
@classmethod
def load_work_schedule_attributes(cls, work_schedule):
def callback(name, prop, data):
if name in ["CreationDate", "StartTime", "FinishTime"]:
prop.string_value = "" if prop.is_null else data[name]
return True
props = bpy.context.scene.BIMWorkScheduleProperties
props.work_schedule_attributes.clear()
blenderbim.bim.helper.import_attributes2(work_schedule, props.work_schedule_attributes, callback)
@classmethod
def enable_editing_work_schedule(cls, work_schedule):
bpy.context.scene.BIMWorkScheduleProperties.active_work_schedule_id = work_schedule.id()
bpy.context.scene.BIMWorkScheduleProperties.editing_type = "WORK_SCHEDULE"
@classmethod
def disable_editing_work_schedule(cls):
bpy.context.scene.BIMWorkScheduleProperties.active_work_schedule_id = 0
@classmethod
def enable_editing_work_schedule_tasks(cls, work_schedule):
if work_schedule:
props = bpy.context.scene.BIMWorkScheduleProperties
props.active_work_schedule_id = work_schedule.id()
props.editing_type = "TASKS"
@classmethod
def create_task_tree(cls, work_schedule):
def get_work_schedule_root_tasks(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_work_schedule_root_tasks(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}
related_objects_ids = sorted(cls.sort_keys, key=cls.natural_sort_key)
if props.is_sort_reversed:
related_objects_ids.reverse()
for related_object_id in related_objects_ids:
cls.create_new_task_li(related_object_id, 0)
@classmethod
def create_new_task_li(cls, related_object_id, level_index):
task = tool.Ifc.get().by_id(related_object_id)
new = bpy.context.scene.BIMTaskTreeProperties.tasks.add()
new.ifc_definition_id = related_object_id
new.is_expanded = related_object_id not in cls.contracted_tasks
new.level_index = level_index
if task.IsNestedBy:
new.has_children = True
if new.is_expanded:
cls.sort_keys = {subtask.id(): cls.get_sort_key(subtask) for subtask in helper.get_nested_tasks(task)}
related_object_ids = sorted(cls.sort_keys, key=cls.natural_sort_key)
if bpy.context.scene.BIMWorkScheduleProperties.is_sort_reversed:
related_object_ids.reverse()
for related_object_id in related_object_ids:
cls.create_new_task_li(related_object_id, level_index + 1)
@classmethod
def natural_sort_key(cls, i, _nsre=re.compile("([0-9]+)")):
s = cls.sort_keys[i]
return [int(text) if text.isdigit() else text.lower() for text in _nsre.split(s)]
@classmethod
def get_sort_key(cls, 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 ""
column_type, name = bpy.context.scene.BIMWorkScheduleProperties.sort_column.split(".")
if column_type == "IfcTask":
return task.Name or ""
elif column_type == "IfcTaskTime" and task.TaskTime:
return task.TaskTime.Name or ""
return task.Identification or ""
@classmethod
def load_task_properties(cls, task=None):
def canonicalise_time(time):
if not time:
return "-"
return time.strftime("%d/%m/%y")
props = bpy.context.scene.BIMWorkScheduleProperties
task_props = bpy.context.scene.BIMTaskTreeProperties
props.is_task_update_enabled = False
for item in task_props.tasks:
# if task and item.ifc_definition_id != task.id():
# continue
task = tool.Ifc.get().by_id(item.ifc_definition_id)
item.name = task.Name or "Unnamed"
item.identification = task.Identification or "XXX"
if props.active_task_id:
item.is_predecessor = props.active_task_id in [rel.RelatedProcess.id() for rel in task.IsPredecessorTo]
item.is_successor = props.active_task_id in [rel.RelatingProcess.id() for rel in task.IsSuccessorFrom]
calendar = ifcopenshell.util.sequence.derive_calendar(task)
if task.HasAssignments:
for rel in task.HasAssignments:
if rel.is_a("IfcRelAssignsToControl") and rel.RelatingControl.is_a("IfcWorkCalendar"):
item.calendar = calendar.Name if calendar else ""
else:
item.calendar = ""
item.derived_calendar = calendar.Name if calendar else ""
if task.TaskTime:
task_time = task.TaskTime
item.start = (
canonicalise_time(ifcopenshell.util.date.ifc2datetime(task_time.ScheduleStart))
if task_time.ScheduleStart
else "-"
)
item.finish = (
canonicalise_time(ifcopenshell.util.date.ifc2datetime(task_time.ScheduleFinish))
if task_time.ScheduleFinish
else "-"
)
item.duration = (
isodate.duration_isoformat(ifcopenshell.util.date.ifc2datetime(task_time.ScheduleDuration))
if task_time.ScheduleDuration
else "-"
)
else:
derived_start = helper.derive_date(task, "ScheduleStart", is_earliest=True)
derived_finish = helper.derive_date(task, "ScheduleFinish", is_latest=True)
item.derived_start = canonicalise_time(derived_start) if derived_start else ""
item.derived_finish = canonicalise_time(derived_finish) if derived_finish else ""
if derived_start and derived_finish and calendar:
derived_duration = ifcopenshell.util.sequence.count_working_days(
derived_start, derived_finish, calendar
)
item.derived_duration = f"P{derived_duration}D"
item.start = "-"
item.finish = "-"
item.duration = "-"
bpy.context.scene.BIMWorkScheduleProperties.is_task_update_enabled = True
@classmethod
def hide_work_plan_hints(cls):
bpy.context.scene.BIMWorkPlanProperties.show_hints = False
@classmethod
def show_work_plan_hints(cls):
bpy.context.scene.BIMWorkPlanProperties.show_hints = True
@classmethod
def get_active_work_schedule(cls):
if not bpy.context.scene.BIMWorkScheduleProperties.active_work_schedule_id:
return None
return tool.Ifc.get().by_id(bpy.context.scene.BIMWorkScheduleProperties.active_work_schedule_id)
@classmethod
def get_selected_resource(cls):
if bpy.context.scene.BIMResourceTreeProperties.resources:
selected_resource_id = bpy.context.scene.BIMResourceTreeProperties.resources[
bpy.context.scene.BIMResourceProperties.active_resource_index
].ifc_definition_id
return tool.Ifc.get().by_id(selected_resource_id)
@classmethod
def expand_task(cls, task):
props = bpy.context.scene.BIMWorkScheduleProperties
contracted_tasks = json.loads(props.contracted_tasks)
contracted_tasks.remove(task.id())
props.contracted_tasks = json.dumps(contracted_tasks)
@classmethod
def contract_task(cls, task):
props = bpy.context.scene.BIMWorkScheduleProperties
contracted_tasks = json.loads(props.contracted_tasks)
contracted_tasks.append(task.id())
props.contracted_tasks = json.dumps(contracted_tasks)
@classmethod
def disable_work_schedule(cls):
bpy.context.scene.BIMWorkScheduleProperties.active_work_schedule_id = 0
@classmethod
def disable_selecting_deleted_task(cls):
props = bpy.context.scene.BIMWorkScheduleProperties
if props.active_task_id not in [
task.ifc_definition_id for task in bpy.context.scene.BIMTaskTreeProperties.tasks
]: # Task was deleted
bpy.context.scene.BIMWorkScheduleProperties.active_task_id = 0
bpy.context.scene.BIMWorkScheduleProperties.active_task_time_id = 0
@classmethod
def get_checked_tasks(cls):
return [
tool.Ifc.get().by_id(task.ifc_definition_id)
for task in bpy.context.scene.BIMTaskTreeProperties.tasks
if task.is_selected
]
@classmethod
def get_task_attribute_value(cls, attribute_name):
return bpy.context.scene.BIMWorkScheduleProperties.task_attributes.get(attribute_name).get_value()
@classmethod
def get_active_task(cls):
return tool.Ifc.get().by_id(bpy.context.scene.BIMWorkScheduleProperties.active_task_id)
@classmethod
def get_active_work_time(cls):
return tool.Ifc.get().by_id(bpy.context.scene.BIMWorkCalendarProperties.active_work_time_id)
@classmethod
def get_task_time(cls, task):
return task.TaskTime if task.TaskTime else None
@classmethod
def load_task_attributes(cls, task):
props = bpy.context.scene.BIMWorkScheduleProperties
props.task_attributes.clear()
blenderbim.bim.helper.import_attributes2(task, props.task_attributes)
@classmethod
def get_selected_products(cls):
return [
tool.Ifc.get_entity(obj)
for obj in bpy.context.selected_objects
if obj.BIMObjectProperties.ifc_definition_id
] or []
@classmethod
def enable_editing_task(cls, task):
props = bpy.context.scene.BIMWorkScheduleProperties
props.active_task_id = task.id()
props.editing_task_type = "ATTRIBUTES"
@classmethod
def get_task_attributes(cls):
return blenderbim.bim.helper.export_attributes(bpy.context.scene.BIMWorkScheduleProperties.task_attributes)
@classmethod
def load_task_time_attributes(cls, task_time):
def callback(name, prop, data):
if prop.data_type == "string":
if name == "ScheduleDuration" and data[name] and isinstance(data[name], str):
time_object = ifcopenshell.util.date.ifc2datetime(data[name])
minutes = int(round(time_object.seconds/60 % 60))
hours = (time_object.seconds - minutes*60)/60/60
bpy.context.scene.BIMDuration.duration_days = int(time_object.days)
bpy.context.scene.BIMDuration.duration_hours = round(hours)
bpy.context.scene.BIMDuration.duration_minutes = minutes # should consider years, months and seconds.
if isinstance(data[name], datetime):
prop.string_value = "" if prop.is_null else data[name].isoformat()
if name == "ScheduleDuration":
bpy.context.scene.BIMDuration.duration_days = data[name].days
bpy.context.scene.BIMDuration.duration_hours = round(data[name].seconds / 60 / 60)
bpy.context.scene.BIMDuration.duration_minutes = data[name].seconds/60 % 60
return True
elif isinstance(data[name], isodate.Duration):
prop.string_value = (
"" if prop.is_null else ifcopenshell.util.date.datetime2ifc(data[name], "IfcDuration")
)
return True
props = bpy.context.scene.BIMWorkScheduleProperties
props.task_time_attributes.clear()
blenderbim.bim.helper.import_attributes2(task_time, props.task_time_attributes, callback)
@classmethod
def enable_editing_task_time(cls, task):
props = bpy.context.scene.BIMWorkScheduleProperties
props.active_task_id = task.id()
props.active_task_time_id = task.TaskTime.id()
props.editing_task_type = "TASKTIME"
@classmethod
def disable_editing_task(cls):
bpy.context.scene.BIMWorkScheduleProperties.active_task_id = 0
bpy.context.scene.BIMWorkScheduleProperties.active_task_time_id = 0
@classmethod
def get_task_time_attributes(cls):
def callback(attributes, prop):
if "Start" in prop.name or "Finish" in prop.name or prop.name == "StatusTime":
if prop.is_null:
attributes[prop.name] = None
return True
attributes[prop.name] = helper.parse_datetime(prop.string_value)
return True
elif prop.name == "ScheduleDuration":
if prop.is_null:
return True
# TODO make this parse PT32 as P4D
attributes[prop.name] = helper.parse_duration(prop.string_value)
dprops= bpy.context.scene.BIMDuration
duration_days = dprops.duration_days if dprops.duration_days else 0
duration_hours = dprops.duration_hours if dprops.duration_hours else 0
duration_minutes = dprops.duration_minutes if dprops.duration_minutes else 0
dprops.duration_days = 0
dprops.duration_hours = 0
dprops.duration_minutes = 0
attributes[prop.name] = helper.parse_duration(f"P{duration_days}DT{duration_hours}H{duration_minutes}M")
return True
props = bpy.context.scene.BIMWorkScheduleProperties
return blenderbim.bim.helper.export_attributes(props.task_time_attributes, callback)
@classmethod
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"
@classmethod
def load_resources(cls):
bpy.ops.bim.load_resources() # remove and refactor
@classmethod
def get_task_inputs(cls, task):
inputs = []
for rel in task.OperatesOn:
for object in rel.RelatedObjects:
if object.is_a("IfcProduct"):
inputs.append(object)
return inputs
@classmethod
def load_task_inputs(cls, inputs):
props = bpy.context.scene.BIMWorkScheduleProperties
props.task_inputs.clear()
for input in inputs:
new = props.task_inputs.add()
new.ifc_definition_id = input.id()
new.name = input.Name or "Unnamed"
@classmethod
def load_task_outputs(cls, outputs):
props = bpy.context.scene.BIMWorkScheduleProperties
props.task_outputs.clear()
if outputs:
for output in outputs:
new = props.task_outputs.add()
new.ifc_definition_id = output.id()
new.name = output.Name or "Unnamed"
@classmethod
def get_highlighted_task(cls):
props = bpy.context.scene.BIMWorkScheduleProperties
task_props = bpy.context.scene.BIMTaskTreeProperties
return tool.Ifc.get().by_id(task_props.tasks[props.active_task_index].ifc_definition_id)
@classmethod
def get_task_outputs(cls, task):
return [rel.RelatingProduct for rel in task.HasAssignments if rel.is_a("IfcRelAssignsToProduct")]
@classmethod
def get_task_resources(cls, task):
resources = []
for rel in task.OperatesOn:
for object in rel.RelatedObjects:
if object.is_a("IfcResource"):
resources.append(object)
return resources
@classmethod
def enable_editing_work_calendar_times(cls, work_calendar):
props = bpy.context.scene.BIMWorkCalendarProperties
props.active_work_calendar_id = work_calendar.id()
props.editing_type = "WORKTIMES"
@classmethod
def load_work_calendar_attributes(cls, work_calendar):
props = bpy.context.scene.BIMWorkCalendarProperties
props.work_calendar_attributes.clear()
return blenderbim.bim.helper.import_attributes2(work_calendar, props.work_calendar_attributes)
@classmethod
def enable_editing_work_calendar(cls, work_calendar):
bpy.context.scene.BIMWorkCalendarProperties.active_work_calendar_id = work_calendar.id()
bpy.context.scene.BIMWorkCalendarProperties.editing_type = "ATTRIBUTES"
@classmethod
def disable_editing_work_calendar(cls):
bpy.context.scene.BIMWorkCalendarProperties.active_work_calendar_id = 0
@classmethod
def get_work_calendar_attributes(cls):
return blenderbim.bim.helper.export_attributes(
bpy.context.scene.BIMWorkCalendarProperties.work_calendar_attributes
)
@classmethod
def load_work_time_attributes(cls, work_time):
def callback(name, prop, data):
if name in ["Start", "Finish"]:
prop.string_value = "" if prop.is_null else data[name]
return True
props = bpy.context.scene.BIMWorkCalendarProperties
props.work_time_attributes.clear()
blenderbim.bim.helper.import_attributes2(work_time, props.work_time_attributes, callback)
@classmethod
def enable_editing_work_time(cls, work_time):
def initialise_recurrence_components(props):
if len(props.day_components) == 0:
for i in range(0, 31):
new = props.day_components.add()
new.name = str(i + 1)
if len(props.weekday_components) == 0:
for d in ["M", "T", "W", "T", "F", "S", "S"]:
new = props.weekday_components.add()
new.name = d
if len(props.month_components) == 0:
for m in ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"]:
new = props.month_components.add()
new.name = m
def load_recurrence_pattern_data(work_time, props):
props.position = 0
props.interval = 0
props.occurrences = 0
props.start_time = ""
props.end_time = ""
for component in props.day_components:
component.is_specified = False
for component in props.weekday_components:
component.is_specified = False
for component in props.month_components:
component.is_specified = False
if not work_time.RecurrencePattern:
return
recurrence_pattern = work_time.RecurrencePattern
for attribute in ["Position", "Interval", "Occurrences"]:
if getattr(recurrence_pattern, attribute):
setattr(props, attribute.lower(), getattr(recurrence_pattern, attribute))
for component in recurrence_pattern.DayComponent or []:
props.day_components[component - 1].is_specified = True
for component in recurrence_pattern.WeekdayComponent or []:
props.weekday_components[component - 1].is_specified = True
for component in recurrence_pattern.MonthComponent or []:
props.month_components[component - 1].is_specified = True
props = bpy.context.scene.BIMWorkCalendarProperties
initialise_recurrence_components(props)
load_recurrence_pattern_data(work_time, props)
props.active_work_time_id = work_time.id()
props.editing_type = "WORKTIMES"
@classmethod
def get_work_time_attributes(cls):
def callback(attributes, prop):
if "Start" in prop.name or "Finish" in prop.name:
if prop.is_null:
attributes[prop.name] = None
return True
attributes[prop.name] = helper.parse_datetime(prop.string_value)
return True
props = bpy.context.scene.BIMWorkCalendarProperties
return blenderbim.bim.helper.export_attributes(props.work_time_attributes, callback)
@classmethod
def get_recurrence_pattern_attributes(cls, recurrence_pattern):
props = bpy.context.scene.BIMWorkCalendarProperties
attributes = {
"Interval": props.interval if props.interval > 0 else None,
"Occurrences": props.occurrences if props.occurrences > 0 else None,
}
applicable_data = {
"DAILY": ["Interval", "Occurrences"],
"WEEKLY": ["WeekdayComponent", "Interval", "Occurrences"],
"MONTHLY_BY_DAY_OF_MONTH": ["DayComponent", "Interval", "Occurrences"],
"MONTHLY_BY_POSITION": ["WeekdayComponent", "Position", "Interval", "Occurrences"],
"BY_DAY_COUNT": ["Interval", "Occurrences"],
"BY_WEEKDAY_COUNT": ["WeekdayComponent", "Interval", "Occurrences"],
"YEARLY_BY_DAY_OF_MONTH": ["DayComponent", "MonthComponent", "Interval", "Occurrences"],
"YEARLY_BY_POSITION": ["WeekdayComponent", "MonthComponent", "Position", "Interval", "Occurrences"],
}
if "Position" in applicable_data[recurrence_pattern.RecurrenceType]:
attributes["Position"] = props.position if props.position != 0 else None
if "DayComponent" in applicable_data[recurrence_pattern.RecurrenceType]:
attributes["DayComponent"] = [i + 1 for i, c in enumerate(props.day_components) if c.is_specified]
if "WeekdayComponent" in applicable_data[recurrence_pattern.RecurrenceType]:
attributes["WeekdayComponent"] = [i + 1 for i, c in enumerate(props.weekday_components) if c.is_specified]
if "MonthComponent" in applicable_data[recurrence_pattern.RecurrenceType]:
attributes["MonthComponent"] = [i + 1 for i, c in enumerate(props.month_components) if c.is_specified]
return attributes
@classmethod
def disable_editing_work_time(cls):
bpy.context.scene.BIMWorkCalendarProperties.active_work_time_id = 0
@classmethod
def get_recurrence_pattern_times(cls):
props = bpy.context.scene.BIMWorkCalendarProperties
try:
start_time = parser.parse(props.start_time)
end_time = parser.parse(props.end_time)
return start_time, end_time
except:
return # improve UI / refactor to add user hints
@classmethod
def reset_time_period(cls):
bpy.context.scene.BIMWorkCalendarProperties.start_time = ""
bpy.context.scene.BIMWorkCalendarProperties.end_time = ""
@classmethod
def enable_editing_task_calendar(cls, task):
props = bpy.context.scene.BIMWorkScheduleProperties
props.active_task_id = task.id()
props.editing_task_type = "CALENDAR"
@classmethod
def enable_editing_task_sequence(cls, task):
props = bpy.context.scene.BIMWorkScheduleProperties
props.active_task_id = task.id()
props.editing_task_type = "SEQUENCE"
@classmethod
def disable_editing_task_time(cls):
bpy.context.scene.BIMWorkScheduleProperties.active_task_id = 0
bpy.context.scene.BIMWorkScheduleProperties.active_task_time_id = 0
@classmethod
def load_rel_sequence_attributes(cls, rel_sequence):
props = bpy.context.scene.BIMWorkScheduleProperties
props.sequence_attributes.clear()
blenderbim.bim.helper.import_attributes2(rel_sequence, props.sequence_attributes)
@classmethod
def enable_editing_rel_sequence_attributes(cls, rel_sequence):
props = bpy.context.scene.BIMWorkScheduleProperties
props.active_sequence_id = rel_sequence.id()
props.editing_sequence_type = "ATTRIBUTES"
@classmethod
def load_lag_time_attributes(cls, lag_time):
def callback(name, prop, data):
if name == "LagValue":
prop = bpy.context.scene.BIMWorkScheduleProperties.lag_time_attributes.add()
prop.name = name
prop.is_null = data[name] is None
prop.is_optional = False
prop.data_type = "string"
prop.string_value = (
"" if prop.is_null else ifcopenshell.util.date.datetime2ifc(data[name].wrappedValue, "IfcDuration")
)
return True
props = bpy.context.scene.BIMWorkScheduleProperties
props.lag_time_attributes.clear()
blenderbim.bim.helper.import_attributes2(lag_time, props.lag_time_attributes, callback)
@classmethod
def enable_editing_sequence_lag_time(cls, rel_sequence):
props = bpy.context.scene.BIMWorkScheduleProperties
props.active_sequence_id = rel_sequence.id()
props.editing_sequence_type = "LAG_TIME"
@classmethod
def get_rel_sequence_attributes(cls):
return blenderbim.bim.helper.export_attributes(bpy.context.scene.BIMWorkScheduleProperties.sequence_attributes)
@classmethod
def disable_editing_rel_sequence(cls):
bpy.context.scene.BIMWorkScheduleProperties.active_sequence_id = 0
@classmethod
def get_lag_time_attributes(cls):
return blenderbim.bim.helper.export_attributes(bpy.context.scene.BIMWorkScheduleProperties.lag_time_attributes)
@classmethod
def select_task_products(cls, products):
for obj in bpy.context.visible_objects:
obj.select_set(False)
if obj.BIMObjectProperties.ifc_definition_id in [product.id() for product in products]:
obj.select_set(True)
@classmethod
def add_task_column(cls, column_type, name, data_type):
props = bpy.context.scene.BIMWorkScheduleProperties
new = props.columns.add()
new.name = f"{column_type}.{name}"
new.data_type = data_type
@classmethod
def remove_task_column(cls, name):
props = bpy.context.scene.BIMWorkScheduleProperties
props.columns.remove(props.columns.find(name))
@classmethod
def set_task_sort_column(cls, column):
props = bpy.context.scene.BIMWorkScheduleProperties
props.sort_column = column
@classmethod
def find_related_input_tasks(cls, object):
related_tasks = []
for assignment in object.HasAssignments:
if assignment.is_a("IfcRelAssignsToProcess") and assignment.RelatingProcess.is_a("IfcTask"):
related_tasks.append(assignment.RelatingProcess)
return related_tasks
@classmethod
def find_related_output_tasks(cls, object):
related_tasks = []
for reference in object.ReferencedBy:
if reference.is_a("IfcRelAssignsToProduct") and reference.RelatedObjects[0].is_a("IfcTask"):
related_tasks.append(reference.RelatedObjects[0])
return related_tasks
@classmethod
def get_root_task(cls, task):
return (
task
if not task.Nests or not task.Nests[0].RelatingObject.is_a("IfcTask")
else cls.get_root_task(task.Nests[0].RelatingObject)
)
@classmethod
def get_task_work_schedule(cls, task):
if task.HasAssignments:
for rel in task.HasAssignments:
if rel.is_a("IfcRelAssignsToControl") and rel.RelatingControl.is_a("IfcWorkSchedule"):
return rel.RelatingControl
@classmethod
def is_work_schedule_active(cls, work_schedule):
return (
True if work_schedule.id() == bpy.context.scene.BIMWorkScheduleProperties.active_work_schedule_id else False
)
@classmethod
def highlight_task(cls, task):
props = bpy.context.scene.BIMWorkScheduleProperties
task_props = bpy.context.scene.BIMTaskTreeProperties
task_id = task.id()
task_index = [task.ifc_definition_id for task in task_props.tasks].index(task_id)
if task_index:
props.active_task_index = task_index
+2 -2
View File
@@ -57,7 +57,7 @@ Scenario: Enable pset editing - work schedule
Given an empty IFC project
And I press "bim.add_work_schedule"
And the variable "work_schedule" is "{ifc}.by_type('IfcWorkSchedule')[0].id()"
And I press "bim.enable_editing_tasks(work_schedule={work_schedule})"
And I press "bim.enable_editing_work_schedule_tasks(work_schedule={work_schedule})"
And I set "scene.WorkSchedulePsetProperties.pset_name" to "Pset_WorkControlCommon"
And I press "bim.add_pset(obj_type='WorkSchedule')"
And the variable "pset" is "{ifc}.by_type('IfcPropertySet')[-1].id()"
@@ -90,7 +90,7 @@ Scenario: Enable pset editing - task
Given an empty IFC project
And I press "bim.add_work_schedule"
And the variable "work_schedule" is "IfcStore.get_file().by_type('IfcWorkSchedule')[0].id()"
And I press "bim.enable_editing_tasks(work_schedule={work_schedule})"
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 I set "scene.TaskPsetProperties.qto_name" to "Qto_TaskBaseQuantities"
And I press "bim.add_qto(obj_type='Task')"
+433 -14
View File
@@ -4,13 +4,225 @@ Feature: Sequence
Scenario: Add work plan
Given an empty IFC project
When I press "bim.add_work_plan"
And the variable "work_plan" is "IfcStore.get_file().by_type('IfcWorkPlan')[0].id()"
Then nothing happens
Scenario: Add Work schedule
Given an empty IFC project
When I press "bim.add_work_schedule"
And the variable "work_schedule" is "IfcStore.get_file().by_type('IfcWorkSchedule')[0].id()"
Then nothing happens
Scenario: Remove work plan
Given an empty IFC project
When I press "bim.add_work_plan"
And the variable "work_plan" is "IfcStore.get_file().by_type('IfcWorkPlan')[0].id()"
When I press "bim.remove_work_plan(work_plan={work_plan})"
Then nothing happens
Scenario: Remove work schedule
Given an empty IFC project
When I press "bim.add_work_schedule"
And the variable "work_schedule" is "IfcStore.get_file().by_type('IfcWorkSchedule')[0].id()"
When I press "bim.remove_work_schedule(work_schedule={work_schedule})"
Then nothing happens
Scenario: Enable Editing Work Plan
Given an empty IFC project
When I press "bim.add_work_plan"
And the variable "work_plan" is "IfcStore.get_file().by_type('IfcWorkPlan')[0].id()"
When I press "bim.enable_editing_work_plan(work_plan={work_plan})"
Then nothing happens
Scenario: Edit Work Plan
Given an empty IFC project
When I press "bim.add_work_plan"
And the variable "work_plan" is "IfcStore.get_file().by_type('IfcWorkPlan')[0].id()"
And I press "bim.enable_editing_work_plan(work_plan={work_plan})"
And I set "scene.BIMWorkPlanProperties.work_plan_attributes.get('Name').string_value" to "FooPlan"
When I press "bim.edit_work_plan()"
Then nothing happens
Scenario: Edit Work Schedule
Given an empty IFC project
When I press "bim.add_work_schedule"
And the variable "work_schedule" is "IfcStore.get_file().by_type('IfcWorkSchedule')[0].id()"
And I press "bim.enable_editing_work_schedule(work_schedule={work_schedule})"
And I set "scene.BIMWorkScheduleProperties.work_schedule_attributes.get('Name').string_value" to "FooSchedule"
When I press "bim.edit_work_schedule()"
Then nothing happens
Scenario: Disable Editing Work Plan
Given an empty IFC project
When I press "bim.add_work_plan"
And the variable "work_plan" is "IfcStore.get_file().by_type('IfcWorkPlan')[0].id()"
And I press "bim.enable_editing_work_plan_schedules(work_plan={work_plan})"
When I press "bim.disable_editing_work_plan"
Then nothing happens
Scenario: Assign work schedule
Given an empty IFC project
When I press "bim.add_work_schedule"
And the variable "work_schedule" is "IfcStore.get_file().by_type('IfcWorkSchedule')[0].id()"
When I press "bim.add_work_plan"
And the variable "work_plan" is "IfcStore.get_file().by_type('IfcWorkPlan')[0].id()"
And I press "bim.enable_editing_work_plan_schedules(work_plan={work_plan})"
And I press "bim.assign_work_schedule(work_plan={work_plan}, work_schedule={work_schedule})"
Then nothing happens
Scenario: Unassign work schedule
Given an empty IFC project
When I press "bim.add_work_schedule"
And the variable "work_schedule" is "IfcStore.get_file().by_type('IfcWorkSchedule')[0].id()"
When I press "bim.add_work_plan"
And the variable "work_plan" is "IfcStore.get_file().by_type('IfcWorkPlan')[0].id()"
And I press "bim.enable_editing_work_plan_schedules(work_plan={work_plan})"
And I press "bim.assign_work_schedule(work_plan={work_plan}, work_schedule={work_schedule})"
And I press "bim.unassign_work_schedule(work_plan={work_plan}, work_schedule={work_schedule})"
Then nothing happens
Scenario: Delete assigned work schedule
Given an empty IFC project
When I press "bim.add_work_schedule"
And the variable "work_schedule" is "IfcStore.get_file().by_type('IfcWorkSchedule')[0].id()"
When I press "bim.add_work_plan"
And the variable "work_plan" is "IfcStore.get_file().by_type('IfcWorkPlan')[0].id()"
And I press "bim.enable_editing_work_plan_schedules(work_plan={work_plan})"
And I press "bim.assign_work_schedule(work_plan={work_plan}, work_schedule={work_schedule})"
When I press "bim.remove_work_schedule(work_schedule={work_schedule})"
Then nothing happens
Scenario: Remove Assigned work schedule
Given an empty IFC project
When I press "bim.add_work_schedule"
And the variable "work_schedule" is "IfcStore.get_file().by_type('IfcWorkSchedule')[0].id()"
When I press "bim.add_work_plan"
And the variable "work_plan" is "IfcStore.get_file().by_type('IfcWorkPlan')[0].id()"
And I press "bim.enable_editing_work_plan_schedules(work_plan={work_plan})"
When I press "bim.assign_work_schedule(work_plan={work_plan}, work_schedule={work_schedule})"
Then nothing happens
Scenario: Add work calendar
Given an empty IFC project
When I press "bim.add_work_calendar"
And the variable "work_calendar" is "IfcStore.get_file().by_type('IfcWorkCalendar')[0].id()"
Then nothing happens
Scenario: Remove work calendar
Given an empty IFC project
When I press "bim.add_work_calendar"
And the variable "work_calendar" is "IfcStore.get_file().by_type('IfcWorkCalendar')[0].id()"
When I press "bim.remove_work_calendar(work_calendar={work_calendar})"
Then nothing happens
Scenario: Edit work calendar attributes
Given an empty IFC project
When I press "bim.add_work_calendar"
And the variable "work_calendar" is "IfcStore.get_file().by_type('IfcWorkCalendar')[0].id()"
When I press "bim.enable_editing_work_calendar(work_calendar={work_calendar})"
And I set "scene.BIMWorkCalendarProperties.work_calendar_attributes.get('Name').string_value" to "FooCalendar"
When I press "bim.edit_work_calendar()"
Then nothing happens
Scenario: Enable editing calendar times
Given an empty IFC project
When I press "bim.add_work_calendar"
And the variable "work_calendar" is "IfcStore.get_file().by_type('IfcWorkCalendar')[0].id()"
When I press "bim.enable_editing_work_calendar_times(work_calendar={work_calendar})"
Then nothing happens
Scenario: Add calendar Working Time
Given an empty IFC project
When I press "bim.add_work_calendar"
And the variable "work_calendar" is "IfcStore.get_file().by_type('IfcWorkCalendar')[0].id()"
When I press "bim.enable_editing_work_calendar_times(work_calendar={work_calendar})"
When I press "bim.add_work_time(work_calendar={work_calendar}, time_type="WorkingTimes")"
Then nothing happens
Scenario: Add calendar Exception Time
Given an empty IFC project
When I press "bim.add_work_calendar"
And the variable "work_calendar" is "IfcStore.get_file().by_type('IfcWorkCalendar')[0].id()"
And I press "bim.enable_editing_work_calendar_times(work_calendar={work_calendar})"
When I press "bim.add_work_time(work_calendar={work_calendar}, time_type="ExceptionTimes")"
Then nothing happens
Scenario: Enable editing Working Time Attributes
Given an empty IFC project
When I press "bim.add_work_calendar"
And the variable "work_calendar" is "IfcStore.get_file().by_type('IfcWorkCalendar')[0].id()"
When I press "bim.enable_editing_work_calendar_times(work_calendar={work_calendar})"
When I press "bim.add_work_time(work_calendar={work_calendar}, time_type="WorkingTimes")"
And the variable "work_time" is "IfcStore.get_file().by_type('IfcWorkTime')[0].id()"
When I press "bim.enable_editing_work_time(work_time={work_time})"
Scenario: Edit Working Time Start and End Period
Given an empty IFC project
When I press "bim.add_work_calendar"
And the variable "work_calendar" is "IfcStore.get_file().by_type('IfcWorkCalendar')[0].id()"
When I press "bim.enable_editing_work_calendar_times(work_calendar={work_calendar})"
When I press "bim.add_work_time(work_calendar={work_calendar}, time_type='WorkingTimes')"
And the variable "work_time" is "IfcStore.get_file().by_type('IfcWorkTime')[0].id()"
When I press "bim.enable_editing_work_time(work_time={work_time})"
And I set "scene.BIMWorkCalendarProperties.work_time_attributes.get('Start').string_value" to "2021-01-01"
And I set "scene.BIMWorkCalendarProperties.work_time_attributes.get('Finish').string_value" to "2022-01-01"
When I press "bim.edit_work_time()"
Then nothing happens
Scenario: Add Working Time Period
Given an empty IFC project
When I press "bim.add_work_calendar"
And the variable "work_calendar" is "IfcStore.get_file().by_type('IfcWorkCalendar')[0].id()"
When I press "bim.enable_editing_work_calendar_times(work_calendar={work_calendar})"
When I press "bim.add_work_time(work_calendar={work_calendar}, time_type='WorkingTimes')"
And the variable "work_time" is "IfcStore.get_file().by_type('IfcWorkTime')[0].id()"
When I press "bim.enable_editing_work_time(work_time={work_time})"
When I press "bim.assign_recurrence_pattern(work_time={work_time}, recurrence_type='DAILY')"
And the variable "recurrence_pattern" is "IfcStore.get_file().by_type('IfcRecurrencePattern')[0].id()"
And I set "scene.BIMWorkCalendarProperties.start_time" to "9AM"
And I set "scene.BIMWorkCalendarProperties.end_time" to "1PM"
When I press "bim.add_time_period(recurrence_pattern={recurrence_pattern})"
When I press "bim.edit_work_time()"
Then nothing happens
Scenario: Edit Working Time start finish and time period
Given an empty IFC project
When I press "bim.add_work_calendar"
And the variable "work_calendar" is "IfcStore.get_file().by_type('IfcWorkCalendar')[0].id()"
When I press "bim.enable_editing_work_calendar_times(work_calendar={work_calendar})"
When I press "bim.add_work_time(work_calendar={work_calendar}, time_type='WorkingTimes')"
And the variable "work_time" is "IfcStore.get_file().by_type('IfcWorkTime')[0].id()"
When I press "bim.enable_editing_work_time(work_time={work_time})"
And I set "scene.BIMWorkCalendarProperties.work_time_attributes.get('Start').string_value" to "2021-01-01"
And I set "scene.BIMWorkCalendarProperties.work_time_attributes.get('Finish').string_value" to "2022-01-01"
When I press "bim.assign_recurrence_pattern(work_time={work_time}, recurrence_type='DAILY')"
And the variable "recurrence_pattern" is "IfcStore.get_file().by_type('IfcRecurrencePattern')[0].id()"
And I set "scene.BIMWorkCalendarProperties.start_time" to "9AM"
And I set "scene.BIMWorkCalendarProperties.end_time" to "1PM"
When I press "bim.add_time_period(recurrence_pattern={recurrence_pattern})"
When I press "bim.edit_work_time()"
Then nothing happens
Scenario: Unassign Calendar to task
Given an empty IFC project
When I press "bim.add_work_calendar"
And the variable "work_calendar" is "IfcStore.get_file().by_type('IfcWorkCalendar')[0].id()"
When I press "bim.add_work_schedule"
And the variable "work_schedule" is "IfcStore.get_file().by_type('IfcWorkSchedule')[0].id()"
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_calendar(task={task})"
And I press "bim.edit_task_calendar(work_calendar={work_calendar}, task={task})"
When I press "bim.remove_task_calendar(work_calendar={work_calendar}, task={task})"
Then nothing happens
Scenario: Enable editing task
Given an empty IFC project
And I press "bim.add_work_schedule"
And the variable "work_schedule" is "IfcStore.get_file().by_type('IfcWorkSchedule')[0].id()"
And I press "bim.enable_editing_tasks(work_schedule={work_schedule})"
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})"
@@ -20,7 +232,7 @@ Scenario: Copy task attribute
Given an empty IFC project
And I press "bim.add_work_schedule"
And the variable "work_schedule" is "IfcStore.get_file().by_type('IfcWorkSchedule')[0].id()"
And I press "bim.enable_editing_tasks(work_schedule={work_schedule})"
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 I press "bim.add_summary_task(work_schedule={work_schedule})"
And the variable "task" is "IfcStore.get_file().by_type('IfcTask')[0].id()"
@@ -30,11 +242,86 @@ Scenario: Copy task attribute
And I press "bim.copy_task_attribute(name='Description')"
Then nothing happens
Scenario: Unassign task Successor
Given an empty IFC project
When I press "bim.add_work_schedule"
And the variable "work_schedule" is "IfcStore.get_file().by_type('IfcWorkSchedule')[0].id()"
And I press "bim.enable_editing_work_schedule_tasks(work_schedule={work_schedule})"
When 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.add_task(task={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.assign_successor(task={nested_task_two})"
When I press "bim.unassign_successor(task={nested_task_two})"
Then nothing happens
Scenario: Edit time Lag
Given an empty IFC project
When I press "bim.add_work_schedule"
And the variable "work_schedule" is "IfcStore.get_file().by_type('IfcWorkSchedule')[0].id()"
And I press "bim.enable_editing_work_schedule_tasks(work_schedule={work_schedule})"
When 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.add_task(task={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})"
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})"
And the variable "lag_time" is "IfcStore.get_file().by_type('IfcLagTime')[0].id()"
And I press "bim.enable_editing_sequence_lag_time(sequence={rel_sequence}, lag_time={lag_time})"
And I set "scene.BIMWorkScheduleProperties.lag_time_attributes.get('LagValue').string_value" to "P5D"
When I press "bim.edit_sequence_lag_time(lag_time={lag_time})"
Then nothing happens
Scenario: Unassign time Lag
Given an empty IFC project
When I press "bim.add_work_schedule"
And the variable "work_schedule" is "IfcStore.get_file().by_type('IfcWorkSchedule')[0].id()"
And I press "bim.enable_editing_work_schedule_tasks(work_schedule={work_schedule})"
When 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.add_task(task={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})"
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})"
And the variable "lag_time" is "IfcStore.get_file().by_type('IfcLagTime')[0].id()"
When I press "bim.unassign_lag_time(sequence={rel_sequence})"
Then nothing happens
Scenario: Edit Sequence Relationship
Given an empty IFC project
When I press "bim.add_work_schedule"
And the variable "work_schedule" is "IfcStore.get_file().by_type('IfcWorkSchedule')[0].id()"
And I press "bim.enable_editing_work_schedule_tasks(work_schedule={work_schedule})"
When 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.add_task(task={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})"
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})"
And I set "scene.BIMWorkScheduleProperties.sequence_attributes.get('SequenceType').enum_value" to "START_START"
When I press "bim.edit_sequence_attributes()"
Then nothing happens
Scenario: See the current frame date as text
Given an empty IFC project
And I press "bim.add_work_schedule"
And the variable "work_schedule" is "IfcStore.get_file().by_type('IfcWorkSchedule')[0].id()"
And I press "bim.enable_editing_tasks(work_schedule={work_schedule})"
And I press "bim.enable_editing_work_schedule_tasks(work_schedule={work_schedule})"
And I set "scene.BIMWorkScheduleProperties.visualisation_start" to "01/01/21"
And I set "scene.BIMWorkScheduleProperties.visualisation_finish" to "01/02/21"
And I set "scene.BIMWorkScheduleProperties.speed_types" to "FRAME_SPEED"
@@ -50,7 +337,7 @@ Scenario: Animate the construction of a wall
Given an empty IFC project
And I press "bim.add_work_schedule"
And the variable "work_schedule" is "IfcStore.get_file().by_type('IfcWorkSchedule')[0].id()"
And I press "bim.enable_editing_tasks(work_schedule={work_schedule})"
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})"
@@ -65,7 +352,7 @@ Scenario: Animate the construction of a wall
And I set "scene.BIMRootProperties.ifc_class" to "IfcWall"
And I press "bim.assign_class"
And the object "IfcWall/Cube" is selected
And I press "bim.assign_product(task={task}, relating_product='')"
And I press "bim.assign_product(task={task})"
And I set "scene.BIMWorkScheduleProperties.visualisation_start" to "01/01/21"
And I set "scene.BIMWorkScheduleProperties.visualisation_finish" to "01/02/21"
And I set "scene.BIMWorkScheduleProperties.speed_types" to "FRAME_SPEED"
@@ -86,7 +373,7 @@ Scenario: Animate the demolition of a wall
Given an empty IFC project
And I press "bim.add_work_schedule"
And the variable "work_schedule" is "IfcStore.get_file().by_type('IfcWorkSchedule')[0].id()"
And I press "bim.enable_editing_tasks(work_schedule={work_schedule})"
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})"
@@ -101,7 +388,7 @@ Scenario: Animate the demolition of a wall
And I set "scene.BIMRootProperties.ifc_class" to "IfcWall"
And I press "bim.assign_class"
And the object "IfcWall/Cube" is selected
And I press "bim.assign_product(task={task}, relating_product='')"
And I press "bim.assign_product(task={task}, relating_product=0)"
And I set "scene.BIMWorkScheduleProperties.visualisation_start" to "01/01/21"
And I set "scene.BIMWorkScheduleProperties.visualisation_finish" to "01/02/21"
And I set "scene.BIMWorkScheduleProperties.speed_types" to "FRAME_SPEED"
@@ -125,7 +412,7 @@ Scenario: Animate the operation of a wall
Given an empty IFC project
And I press "bim.add_work_schedule"
And the variable "work_schedule" is "IfcStore.get_file().by_type('IfcWorkSchedule')[0].id()"
And I press "bim.enable_editing_tasks(work_schedule={work_schedule})"
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})"
@@ -140,7 +427,7 @@ Scenario: Animate the operation of a wall
And I set "scene.BIMRootProperties.ifc_class" to "IfcWall"
And I press "bim.assign_class"
And the object "IfcWall/Cube" is selected
And I press "bim.assign_product(task={task}, relating_product='')"
And I press "bim.assign_product(task={task}, relating_product=0)"
And I set "scene.BIMWorkScheduleProperties.visualisation_start" to "01/01/21"
And I set "scene.BIMWorkScheduleProperties.visualisation_finish" to "01/02/21"
And I set "scene.BIMWorkScheduleProperties.speed_types" to "FRAME_SPEED"
@@ -158,7 +445,7 @@ Scenario: Animate the movement of a wall
Given an empty IFC project
And I press "bim.add_work_schedule"
And the variable "work_schedule" is "IfcStore.get_file().by_type('IfcWorkSchedule')[0].id()"
And I press "bim.enable_editing_tasks(work_schedule={work_schedule})"
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})"
@@ -174,13 +461,13 @@ Scenario: Animate the movement of a wall
And I set "scene.BIMRootProperties.ifc_class" to "IfcWall"
And I press "bim.assign_class"
And the object "IfcWall/ToObject" is selected
And I press "bim.assign_product(task={task}, relating_product='')"
And I press "bim.assign_product(task={task}, relating_product=0)"
When I add a cube
And I rename the object "Cube" to "FromObject"
And the object "FromObject" is selected
And I press "bim.assign_class"
And the object "IfcWall/FromObject" is selected
And I press "bim.assign_process(task={task}, related_object_type='PRODUCT', related_object='')"
And I press "bim.assign_process(task={task}, related_object_type='PRODUCT', related_object=0)"
And I set "scene.BIMWorkScheduleProperties.visualisation_start" to "01/01/21"
And I set "scene.BIMWorkScheduleProperties.visualisation_finish" to "01/02/21"
And I set "scene.BIMWorkScheduleProperties.speed_types" to "FRAME_SPEED"
@@ -212,7 +499,7 @@ Scenario: Animate the consumption of a wall
Given an empty IFC project
And I press "bim.add_work_schedule"
And the variable "work_schedule" is "IfcStore.get_file().by_type('IfcWorkSchedule')[0].id()"
And I press "bim.enable_editing_tasks(work_schedule={work_schedule})"
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_time(task={task})"
@@ -224,7 +511,7 @@ Scenario: Animate the consumption of a wall
And I set "scene.BIMRootProperties.ifc_class" to "IfcWall"
And I press "bim.assign_class"
And the object "IfcWall/Cube" is selected
And I press "bim.assign_process(task={task}, related_object_type='PRODUCT', related_object='')"
And I press "bim.assign_process(task={task}, related_object_type='PRODUCT', related_object=0)"
And I set "scene.BIMWorkScheduleProperties.visualisation_start" to "01/01/21"
And I set "scene.BIMWorkScheduleProperties.visualisation_finish" to "01/02/21"
And I set "scene.BIMWorkScheduleProperties.speed_types" to "FRAME_SPEED"
@@ -243,3 +530,135 @@ Scenario: Animate the consumption of a wall
Then "scene.objects.get('IfcWall/Cube').color" is "[0.0, 0.0, 0.0, 1]"
Then "scene.objects.get('IfcWall/Cube').hide_viewport" is "True"
Then "scene.objects.get('IfcWall/Cube').hide_render" is "True"
Scenario: Generate Gantt Chart
Given an empty IFC project
And I press "bim.add_work_schedule"
And the variable "work_schedule" is "IfcStore.get_file().by_type('IfcWorkSchedule')[0].id()"
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 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})"
And I set "scene.BIMWorkScheduleProperties.task_time_attributes.get('ScheduleStart').string_value" to "2021-01-02"
And I set "scene.BIMWorkScheduleProperties.task_time_attributes.get('ScheduleFinish').string_value" to "2021-01-06"
And I press "bim.edit_task_time"
And I press "bim.generate_gantt_chart(work_schedule={work_schedule})"
Then nothing happens
Scenario: Edit task with calendar
Given an empty IFC project
When I press "bim.add_work_calendar"
And the variable "work_calendar" is "IfcStore.get_file().by_type('IfcWorkCalendar')[0].id()"
When I press "bim.add_work_schedule"
And the variable "work_schedule" is "IfcStore.get_file().by_type('IfcWorkSchedule')[0].id()"
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.add_task(task={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()"
When I press "bim.add_task(task={task})"
And the variable "nested_task_three" is "IfcStore.get_file().by_type('IfcTask')[3].id()"
When I press "bim.enable_editing_work_calendar_times(work_calendar={work_calendar})"
When I press "bim.add_work_time(work_calendar={work_calendar}, time_type="WorkingTimes")"
When I press "bim.add_work_time(work_calendar={work_calendar}, time_type="ExceptionTimes")"
And I press "bim.disable_editing_work_calendar"
And I press "bim.enable_editing_task_sequence(task={nested_task_one})"
And I press "bim.assign_successor(task={nested_task_two})"
And I press "bim.disable_editing_task"
And I press "bim.enable_editing_task_sequence(task={nested_task_three})"
And I press "bim.assign_predecessor(task={nested_task_two})"
And I press "bim.disable_editing_task"
And I press "bim.enable_editing_task_time(task={nested_task_three})"
And I set "scene.BIMWorkScheduleProperties.task_time_attributes.get('ScheduleStart').string_value" to "2021-01-02"
And I set "scene.BIMWorkScheduleProperties.task_time_attributes.get('ScheduleFinish').string_value" to "2021-01-06"
And I press "bim.edit_task_time"
And I press "bim.enable_editing_task_calendar(task={task})"
And I press "bim.edit_task_calendar(work_calendar={work_calendar}, task={task})"
And I press "bim.enable_editing_task_sequence(task={nested_task_one})"
And I press "bim.disable_editing_task()"
Then nothing happens
Scenario: Assign task calendar with Working Time
Given an empty IFC project
When I press "bim.add_work_calendar"
And the variable "work_calendar" is "IfcStore.get_file().by_type('IfcWorkCalendar')[0].id()"
When I press "bim.add_work_schedule"
And the variable "work_schedule" is "IfcStore.get_file().by_type('IfcWorkSchedule')[0].id()"
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.add_task(task={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()"
When I press "bim.add_task(task={task})"
And the variable "nested_task_three" is "IfcStore.get_file().by_type('IfcTask')[3].id()"
When I press "bim.enable_editing_work_calendar_times(work_calendar={work_calendar})"
When I press "bim.add_work_time(work_calendar={work_calendar}, time_type="WorkingTimes")"
When I press "bim.add_work_time(work_calendar={work_calendar}, time_type="ExceptionTimes")"
And I press "bim.disable_editing_work_calendar"
And I press "bim.enable_editing_task_sequence(task={nested_task_one})"
And I press "bim.assign_successor(task={nested_task_two})"
And I press "bim.disable_editing_task"
And I press "bim.enable_editing_task_sequence(task={nested_task_three})"
And I press "bim.assign_predecessor(task={nested_task_two})"
And I press "bim.disable_editing_task"
And I press "bim.enable_editing_task_calendar(task={task})"
And I press "bim.edit_task_calendar(work_calendar={work_calendar}, task={nested_task_three})"
And I press "bim.disable_editing_task()"
And I press "bim.enable_editing_task_time(task={nested_task_three})"
And I set "scene.BIMWorkScheduleProperties.task_time_attributes.get('ScheduleStart').string_value" to "2021-01-02"
And I set "scene.BIMWorkScheduleProperties.task_time_attributes.get('ScheduleFinish').string_value" to "2021-01-06"
# And I press "bim.edit_task_time"
Then nothing happens
Scenario: Assign task calendar with no working time
Given an empty IFC project
When I press "bim.add_work_calendar"
And the variable "work_calendar" is "IfcStore.get_file().by_type('IfcWorkCalendar')[0].id()"
When I press "bim.add_work_schedule"
And the variable "work_schedule" is "IfcStore.get_file().by_type('IfcWorkSchedule')[0].id()"
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.add_task(task={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()"
When I press "bim.add_task(task={task})"
And the variable "nested_task_three" is "IfcStore.get_file().by_type('IfcTask')[3].id()"
And I press "bim.enable_editing_task_sequence(task={nested_task_one})"
And I press "bim.assign_successor(task={nested_task_two})"
And I press "bim.disable_editing_task"
And I press "bim.enable_editing_task_sequence(task={nested_task_three})"
And I press "bim.assign_predecessor(task={nested_task_two})"
And I press "bim.disable_editing_task"
And I press "bim.enable_editing_task_calendar(task={task})"
And I press "bim.edit_task_calendar(work_calendar={work_calendar}, task={nested_task_three})"
And I press "bim.disable_editing_task()"
When I press "bim.enable_editing_work_calendar_times(work_calendar={work_calendar})"
When I press "bim.add_work_time(work_calendar={work_calendar}, time_type="WorkingTimes")"
And the variable "work_time" is "IfcStore.get_file().by_type('IfcWorkTime')[0].id()"
When I press "bim.enable_editing_work_time(work_time={work_time})"
And I set "scene.BIMWorkCalendarProperties.work_time_attributes.get('Start').string_value" to "01-08-2021"
And I set "scene.BIMWorkCalendarProperties.work_time_attributes.get('Finish').string_value" to "01-08-2022"
When I press "bim.assign_recurrence_pattern(work_time={work_time}, recurrence_type='DAILY')"
And the variable "recurrence_pattern" is "IfcStore.get_file().by_type('IfcRecurrencePattern')[0].id()"
And I set "scene.BIMWorkCalendarProperties.start_time" to "9AM"
And I set "scene.BIMWorkCalendarProperties.end_time" to "1PM"
When I press "bim.add_time_period(recurrence_pattern={recurrence_pattern})"
And I press "bim.edit_work_time"
# When I press "bim.add_work_time(work_calendar={work_calendar}, time_type="ExceptionTimes")"
And I press "bim.disable_editing_work_calendar"
And I press "bim.enable_editing_task_time(task={nested_task_three})"
And I set "scene.BIMWorkScheduleProperties.task_time_attributes.get('ScheduleStart').string_value" to "2021-01-02"
And I set "scene.BIMWorkScheduleProperties.task_time_attributes.get('ScheduleFinish').string_value" to "2021-01-06"
And I press "bim.edit_task_time"
Then nothing happens
@@ -62,7 +62,7 @@ class Usecase:
predecessor = rel.RelatingProcess
predecessor_duration = (
ifcopenshell.util.date.ifc2datetime(predecessor.TaskTime.ScheduleDuration)
if predecessor.TaskTime.ScheduleDuration
if predecessor.TaskTime and predecessor.TaskTime.ScheduleDuration
else datetime.timedelta()
)
if rel.SequenceType == "FINISH_START":
@@ -21,7 +21,6 @@ import ifcopenshell.util.date
class Data:
is_loaded = False
work_plans = {}
work_schedules = {}
work_calendars = {}
work_times = {}
@@ -35,7 +34,6 @@ class Data:
@classmethod
def purge(cls):
cls.is_loaded = False
cls.work_plans = {}
cls.work_schedules = {}
cls.work_calendars = {}
cls.work_times = {}
@@ -51,7 +49,6 @@ class Data:
cls._file = file
if not cls._file:
return
cls.load_work_plans()
cls.load_work_schedules()
cls.load_work_calendars()
cls.load_work_times()
@@ -63,23 +60,6 @@ class Data:
cls.load_sequences()
cls.is_loaded = True
@classmethod
def load_work_plans(cls):
cls.work_plans = {}
for work_plan in cls._file.by_type("IfcWorkPlan"):
data = work_plan.get_info()
del data["OwnerHistory"]
if data["Creators"]:
data["Creators"] = [p.id() for p in data["Creators"]]
data["CreationDate"] = ifcopenshell.util.date.ifc2datetime(data["CreationDate"])
data["StartTime"] = ifcopenshell.util.date.ifc2datetime(data["StartTime"])
if data["FinishTime"]:
data["FinishTime"] = ifcopenshell.util.date.ifc2datetime(data["FinishTime"])
data["IsDecomposedBy"] = []
for rel in work_plan.IsDecomposedBy:
data["IsDecomposedBy"].extend([o.id() for o in rel.RelatedObjects])
cls.work_plans[work_plan.id()] = data
@classmethod
def load_work_schedules(cls):
cls.work_schedules = {}
@@ -34,4 +34,11 @@ class Usecase:
definition=self.settings["work_calendar"],
relating_context=self.file.by_type("IfcContext")[0],
)
if self.settings["work_calendar"].Controls:
for rel in self.settings["work_calendar"].Controls:
for object in rel.RelatedObjects:
ifcopenshell.api.run(
"control.unassign_control",
self.file,
**{"relating_control": self.settings["work_calendar"], "related_object": object})
self.file.remove(self.settings["work_calendar"])