diff --git a/src/blenderbim/blenderbim/bim/module/sequence/__init__.py b/src/blenderbim/blenderbim/bim/module/sequence/__init__.py index 477f6239a3..56b035c8f5 100644 --- a/src/blenderbim/blenderbim/bim/module/sequence/__init__.py +++ b/src/blenderbim/blenderbim/bim/module/sequence/__init__.py @@ -16,7 +16,6 @@ classes = ( operator.EnableEditingWorkSchedule, operator.EnableEditingTasks, operator.DisableEditingWorkSchedule, - operator.DisableTaskEditingUI, operator.AddWorkCalendar, operator.EditWorkCalendar, operator.EditWorkTime, @@ -45,8 +44,10 @@ classes = ( operator.UnassignPredecessor, operator.UnassignSuccessor, operator.EnableEditingTaskTime, - operator.DisableEditingTaskTime, + operator.EnableEditingTaskCalendar, operator.EditTaskTime, + operator.EditTaskCalendar, + operator.RemoveTaskCalendar, operator.AssignProduct, operator.UnassignProduct, operator.GenerateGanttChart, diff --git a/src/blenderbim/blenderbim/bim/module/sequence/operator.py b/src/blenderbim/blenderbim/bim/module/sequence/operator.py index 30ddabd08f..d0a8d32bbd 100644 --- a/src/blenderbim/blenderbim/bim/module/sequence/operator.py +++ b/src/blenderbim/blenderbim/bim/module/sequence/operator.py @@ -91,7 +91,7 @@ class EnableEditingWorkPlan(bpy.types.Operator): if data[attribute.name()]: new.enum_value = data[attribute.name()] props.active_work_plan_id = self.work_plan - props.is_editing = "ATTRIBUTES" + props.editing_type = "ATTRIBUTES" return {"FINISHED"} @@ -112,7 +112,7 @@ class EnableEditingWorkPlanSchedules(bpy.types.Operator): def execute(self, context): props = context.scene.BIMWorkPlanProperties props.active_work_plan_id = self.work_plan - props.is_editing = "SCHEDULES" + props.editing_type = "SCHEDULES" return {"FINISHED"} @@ -217,7 +217,7 @@ class EnableEditingWorkSchedule(bpy.types.Operator): while len(self.props.work_schedule_attributes) > 0: self.props.work_schedule_attributes.remove(0) self.enable_editing_work_schedule() - self.props.is_editing = "WORK_SCHEDULE" + self.props.editing_type = "WORK_SCHEDULE" return {"FINISHED"} def enable_editing_work_schedule(self): @@ -258,7 +258,7 @@ class EnableEditingTasks(bpy.types.Operator): for related_object_id in Data.work_schedules[self.work_schedule]["RelatedObjects"]: self.create_new_task_li(related_object_id, 0) bpy.ops.bim.load_task_properties() - self.props.is_editing = "TASKS" + self.props.editing_type = "TASKS" return {"FINISHED"} def create_new_task_li(self, related_object_id, level_index): @@ -321,15 +321,6 @@ class DisableEditingWorkSchedule(bpy.types.Operator): return {"FINISHED"} -class DisableTaskEditingUI(bpy.types.Operator): - bl_idname = "bim.disable_task_editing_ui" - bl_label = "Disable Task Editing UI" - - def execute(self, context): - context.scene.BIMTaskProperties.is_editing = False - return {"FINISHED"} - - class AddTask(bpy.types.Operator): bl_idname = "bim.add_task" bl_label = "Add Task" @@ -448,6 +439,7 @@ class EnableEditingTaskTime(bpy.types.Operator): new.enum_value = data[attribute.name()] props.active_task_time_id = task_time_id props.active_task_id = self.task + props.editing_task_type = "TASKTIME" bpy.ops.bim.load_task_properties() return {"FINISHED"} @@ -457,16 +449,6 @@ class EnableEditingTaskTime(bpy.types.Operator): return task_time -class DisableEditingTaskTime(bpy.types.Operator): - bl_idname = "bim.disable_editing_task_time" - bl_label = "Disable Editing Task Time" - - def execute(self, context): - context.scene.BIMWorkScheduleProperties.active_task_time_id = 0 - bpy.ops.bim.disable_editing_task() - return {"FINISHED"} - - class EditTaskTime(bpy.types.Operator): bl_idname = "bim.edit_task_time" bl_label = "Edit Task Time" @@ -547,6 +529,7 @@ class EnableEditingTask(bpy.types.Operator): if data[attribute.name()]: new.enum_value = data[attribute.name()] props.active_task_id = self.task + props.editing_task_type = "ATTRIBUTES" bpy.ops.bim.load_task_properties() return {"FINISHED"} @@ -557,6 +540,7 @@ class DisableEditingTask(bpy.types.Operator): def execute(self, context): context.scene.BIMWorkScheduleProperties.active_task_id = 0 + context.scene.BIMWorkScheduleProperties.active_task_time_id = 0 return {"FINISHED"} @@ -826,7 +810,7 @@ class EnableEditingWorkCalendar(bpy.types.Operator): if data[attribute.name()]: new.enum_value = data[attribute.name()] self.props.active_work_calendar_id = self.work_calendar - self.props.is_editing = "ATTRIBUTES" + self.props.editing_type = "ATTRIBUTES" return {"FINISHED"} @@ -868,7 +852,7 @@ class EnableEditingWorkCalendarTimes(bpy.types.Operator): def execute(self, context): props = context.scene.BIMWorkCalendarProperties props.active_work_calendar_id = self.work_calendar - props.is_editing = "WORKTIMES" + props.editing_type = "WORKTIMES" return {"FINISHED"} @@ -1123,3 +1107,55 @@ class RemoveTimePeriod(bpy.types.Operator): ) Data.load(self.file) return {"FINISHED"} + + +class EnableEditingTaskCalendar(bpy.types.Operator): + bl_idname = "bim.enable_editing_task_calendar" + bl_label = "Enable Editing Task Calendar" + task: bpy.props.IntProperty() + + def execute(self, context): + props = context.scene.BIMWorkScheduleProperties + props.active_task_id = self.task + props.editing_task_type = "CALENDAR" + return {"FINISHED"} + + +class EditTaskCalendar(bpy.types.Operator): + bl_idname = "bim.edit_task_calendar" + bl_label = "Edit Task Calendar" + work_calendar: bpy.props.IntProperty() + task: bpy.props.IntProperty() + + def execute(self, context): + self.file = IfcStore.get_file() + ifcopenshell.api.run( + "control.assign_control", + self.file, + **{ + "relating_control": self.file.by_id(self.work_calendar), + "related_object": self.file.by_id(self.task), + }, + ) + Data.load(IfcStore.get_file()) + return {"FINISHED"} + + +class RemoveTaskCalendar(bpy.types.Operator): + bl_idname = "bim.remove_task_calendar" + bl_label = "Remove Task Calendar" + work_calendar: bpy.props.IntProperty() + task: bpy.props.IntProperty() + + def execute(self, context): + self.file = IfcStore.get_file() + ifcopenshell.api.run( + "control.unassign_control", + self.file, + **{ + "relating_control": self.file.by_id(self.work_calendar), + "related_object": self.file.by_id(self.task), + }, + ) + Data.load(IfcStore.get_file()) + return {"FINISHED"} diff --git a/src/blenderbim/blenderbim/bim/module/sequence/prop.py b/src/blenderbim/blenderbim/bim/module/sequence/prop.py index 2d02e2236d..f5c2f8f383 100644 --- a/src/blenderbim/blenderbim/bim/module/sequence/prop.py +++ b/src/blenderbim/blenderbim/bim/module/sequence/prop.py @@ -114,6 +114,10 @@ def getWorkSchedules(self, context): return [(str(k), v["Name"], "") for k, v in Data.work_schedules.items()] +def getWorkCalendars(self, context): + return [(str(k), v["Name"], "") for k, v in Data.work_calendars.items()] + + class Task(PropertyGroup): name: StringProperty(name="Name", update=updateTaskName) identification: StringProperty(name="Identification", update=updateTaskIdentification) @@ -135,7 +139,7 @@ class WorkPlan(PropertyGroup): class BIMWorkPlanProperties(PropertyGroup): work_plan_attributes: CollectionProperty(name="Work Plan Attributes", type=Attribute) - is_editing: StringProperty(name="Is Editing") + editing_type: StringProperty(name="Editing Type") work_plans: CollectionProperty(name="Work Plans", type=WorkPlan) active_work_plan_index: IntProperty(name="Active Work Plan Index") active_work_plan_id: IntProperty(name="Active Work Plan Id") @@ -143,8 +147,10 @@ class BIMWorkPlanProperties(PropertyGroup): class BIMWorkScheduleProperties(PropertyGroup): + work_calendars: EnumProperty(items=getWorkCalendars, name="Work Calendars") work_schedule_attributes: CollectionProperty(name="Work Schedule Attributes", type=Attribute) - is_editing: StringProperty(name="Is Editing") + editing_type: StringProperty(name="Editing Type") + editing_task_type: StringProperty(name="Editing Task Type") active_work_schedule_index: IntProperty(name="Active Work Schedules Index") active_work_schedule_id: IntProperty(name="Active Work Schedules Id") active_task_index: IntProperty(name="Active Task Index") @@ -176,8 +182,7 @@ class RecurrenceComponent(PropertyGroup): class BIMWorkCalendarProperties(PropertyGroup): work_calendar_attributes: CollectionProperty(name="Work Calendar Attributes", type=Attribute) work_time_attributes: CollectionProperty(name="Work Time Attributes", type=Attribute) - is_editing: StringProperty(name="Is Editing") - work_calendars: CollectionProperty(name="Work Calendar", type=WorkCalendar) + editing_type: StringProperty(name="Editing Type") active_work_calendar_id: IntProperty(name="Active Work Calendar Id") active_work_time_id: IntProperty(name="Active Work Time Id") day_components: CollectionProperty(name="Day Components", type=RecurrenceComponent) diff --git a/src/blenderbim/blenderbim/bim/module/sequence/ui.py b/src/blenderbim/blenderbim/bim/module/sequence/ui.py index 8e35fa30fc..8b37eb61a8 100644 --- a/src/blenderbim/blenderbim/bim/module/sequence/ui.py +++ b/src/blenderbim/blenderbim/bim/module/sequence/ui.py @@ -43,9 +43,9 @@ class BIM_PT_work_plans(Panel): row.operator("bim.remove_work_plan", text="", icon="X").work_plan = work_plan_id if self.props.active_work_plan_id == work_plan_id: - if self.props.is_editing == "ATTRIBUTES": + if self.props.editing_type == "ATTRIBUTES": self.draw_editable_ui() - elif self.props.is_editing == "SCHEDULES": + elif self.props.editing_type == "SCHEDULES": self.draw_work_schedule_ui() def draw_editable_ui(self): @@ -104,9 +104,9 @@ class BIM_PT_work_schedules(Panel): 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.is_editing == "WORK_SCHEDULE": + if self.props.editing_type == "WORK_SCHEDULE": row.operator("bim.edit_work_schedule", text="", icon="CHECKMARK") - elif self.props.is_editing == "TASKS": + elif self.props.editing_type == "TASKS": row.prop(self.props, "should_show_times", text="", icon="TIME") row.operator("bim.generate_gantt_chart", text="", icon="NLA").work_schedule = work_schedule_id row.operator("bim.add_summary_task", text="", icon="ADD").work_schedule = work_schedule_id @@ -121,9 +121,9 @@ class BIM_PT_work_schedules(Panel): 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.is_editing == "WORK_SCHEDULE": + if self.props.editing_type == "WORK_SCHEDULE": self.draw_editable_work_schedule_ui() - elif self.props.is_editing == "TASKS": + elif self.props.editing_type == "TASKS": self.draw_editable_task_ui(work_schedule_id) def draw_editable_work_schedule_ui(self): @@ -145,11 +145,29 @@ class BIM_PT_work_schedules(Panel): self.props, "active_task_index", ) - if self.props.active_task_id: + if self.props.active_task_id and self.props.editing_task_type == "ATTRIBUTES": self.draw_editable_task_attributes_ui() - if self.props.active_task_time_id: + elif self.props.active_task_id and self.props.editing_task_type == "CALENDAR": + self.draw_editable_task_calendar_ui() + elif self.props.active_task_time_id and self.props.editing_task_type == "TASKTIME": self.draw_editable_task_time_attributes_ui() + def draw_editable_task_calendar_ui(self): + task = Data.tasks[self.props.active_task_id] + if task["HasAssignmentsWorkCalendar"]: + row = self.layout.row(align=True) + calendar = 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: + 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 + def draw_editable_task_attributes_ui(self): for attribute in self.props.task_attributes: row = self.layout.row(align=True) @@ -218,9 +236,11 @@ class BIM_UL_tasks(UIList): op.task = item.ifc_definition_id if props.active_task_id == item.ifc_definition_id: - if props.active_task_time_id: + if props.editing_task_type == "TASKTIME": row.operator("bim.edit_task_time", text="", icon="CHECKMARK") - else: + elif props.editing_task_type == "CALENDAR": + row.operator("bim.disable_editing_task", text="", icon="CHECKMARK") + elif props.editing_task_type == "ATTRIBUTES": row.operator("bim.edit_task", text="", icon="CHECKMARK") row.operator("bim.disable_editing_task", text="", icon="CANCEL") elif props.active_task_id: @@ -246,6 +266,7 @@ class BIM_UL_tasks(UIList): row.operator("bim.remove_task", text="", icon="X").task = item.ifc_definition_id else: row.operator("bim.enable_editing_task_time", text="", icon="TIME").task = item.ifc_definition_id + row.operator("bim.enable_editing_task_calendar", text="", icon="VIEW_ORTHO").task = item.ifc_definition_id row.operator("bim.enable_editing_task", text="", icon="GREASEPENCIL").task = item.ifc_definition_id row.operator("bim.add_task", text="", icon="ADD").task = item.ifc_definition_id row.operator("bim.remove_task", text="", icon="X").task = item.ifc_definition_id @@ -278,7 +299,7 @@ class BIM_PT_work_calendars(Panel): row = self.layout.row(align=True) row.label(text=work_calendar["Name"] or "Unnamed", icon="VIEW_ORTHO") if self.props.active_work_calendar_id == work_calendar_id: - if self.props.is_editing == "ATTRIBUTES": + if self.props.editing_type == "ATTRIBUTES": row.operator("bim.edit_work_calendar", text="", icon="CHECKMARK") row.operator("bim.disable_editing_work_calendar", text="", icon="CANCEL") elif self.props.active_work_calendar_id: @@ -291,9 +312,9 @@ class BIM_PT_work_calendars(Panel): row.operator("bim.remove_work_calendar", text="", icon="X").work_calendar = work_calendar_id if self.props.active_work_calendar_id == work_calendar_id: - if self.props.is_editing == "ATTRIBUTES": + if self.props.editing_type == "ATTRIBUTES": self.draw_editable_ui() - elif self.props.is_editing == "WORKTIMES": + elif self.props.editing_type == "WORKTIMES": self.draw_work_times_ui(work_calendar_id, work_calendar) def draw_work_times_ui(self, work_calendar_id, work_calendar): diff --git a/src/ifcopenshell-python/ifcopenshell/api/sequence/data.py b/src/ifcopenshell-python/ifcopenshell/api/sequence/data.py index 5f7ad96676..b1714dc27a 100644 --- a/src/ifcopenshell-python/ifcopenshell/api/sequence/data.py +++ b/src/ifcopenshell-python/ifcopenshell/api/sequence/data.py @@ -118,6 +118,7 @@ class Data: for task in cls._file.by_type("IfcTask"): data = task.get_info() del data["OwnerHistory"] + data["HasAssignmentsWorkCalendar"] = [] data["RelatedObjects"] = [] data["RelatingProducts"] = [] data["IsPredecessorTo"] = [] @@ -133,6 +134,11 @@ class Data: ] [data["IsPredecessorTo"].append(rel.RelatedProcess.id()) for rel in task.IsPredecessorTo or []] [data["IsSuccessorFrom"].append(rel.RelatingProcess.id()) for rel in task.IsSuccessorFrom or []] + [ + data["HasAssignmentsWorkCalendar"].append(rel.RelatingControl.id()) + for rel in task.HasAssignments or [] + if rel.is_a("IfcRelAssignsToControl") and rel.RelatingControl.is_a("IfcWorkCalendar") + ] cls.tasks[task.id()] = data @classmethod