mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-09-26 18:21:59 +00:00
Support importing P6 sequence types and new view sequences UI
This commit is contained in:
@@ -38,6 +38,7 @@ classes = (
|
|||||||
operator.RemoveTask,
|
operator.RemoveTask,
|
||||||
operator.EnableEditingTask,
|
operator.EnableEditingTask,
|
||||||
operator.DisableEditingTask,
|
operator.DisableEditingTask,
|
||||||
|
operator.DisableEditingTaskTime,
|
||||||
operator.EditTask,
|
operator.EditTask,
|
||||||
operator.AssignPredecessor,
|
operator.AssignPredecessor,
|
||||||
operator.AssignSuccessor,
|
operator.AssignSuccessor,
|
||||||
@@ -45,6 +46,7 @@ classes = (
|
|||||||
operator.UnassignSuccessor,
|
operator.UnassignSuccessor,
|
||||||
operator.EnableEditingTaskTime,
|
operator.EnableEditingTaskTime,
|
||||||
operator.EnableEditingTaskCalendar,
|
operator.EnableEditingTaskCalendar,
|
||||||
|
operator.EnableEditingTaskSequence,
|
||||||
operator.EditTaskTime,
|
operator.EditTaskTime,
|
||||||
operator.EditTaskCalendar,
|
operator.EditTaskCalendar,
|
||||||
operator.RemoveTaskCalendar,
|
operator.RemoveTaskCalendar,
|
||||||
|
|||||||
@@ -291,8 +291,12 @@ class LoadTaskProperties(bpy.types.Operator):
|
|||||||
item.name = task["Name"] or "Unnamed"
|
item.name = task["Name"] or "Unnamed"
|
||||||
item.identification = task["Identification"] or "XXX"
|
item.identification = task["Identification"] or "XXX"
|
||||||
if self.props.active_task_id:
|
if self.props.active_task_id:
|
||||||
item.is_predecessor = self.props.active_task_id in task["IsPredecessorTo"]
|
item.is_predecessor = self.props.active_task_id in [
|
||||||
item.is_successor = self.props.active_task_id in task["IsSuccessorFrom"]
|
Data.sequences[r]["RelatedProcess"] for r in task["IsPredecessorTo"]
|
||||||
|
]
|
||||||
|
item.is_successor = self.props.active_task_id in [
|
||||||
|
Data.sequences[r]["RelatingProcess"] for r in task["IsSuccessorFrom"]
|
||||||
|
]
|
||||||
if task["TaskTime"]:
|
if task["TaskTime"]:
|
||||||
task_time = Data.task_times[task["TaskTime"]]
|
task_time = Data.task_times[task["TaskTime"]]
|
||||||
item.start = self.canonicalise_time(task_time["ScheduleStart"])
|
item.start = self.canonicalise_time(task_time["ScheduleStart"])
|
||||||
@@ -440,7 +444,6 @@ class EnableEditingTaskTime(bpy.types.Operator):
|
|||||||
props.active_task_time_id = task_time_id
|
props.active_task_time_id = task_time_id
|
||||||
props.active_task_id = self.task
|
props.active_task_id = self.task
|
||||||
props.editing_task_type = "TASKTIME"
|
props.editing_task_type = "TASKTIME"
|
||||||
bpy.ops.bim.load_task_properties()
|
|
||||||
return {"FINISHED"}
|
return {"FINISHED"}
|
||||||
|
|
||||||
def add_task_time(self):
|
def add_task_time(self):
|
||||||
@@ -530,7 +533,6 @@ class EnableEditingTask(bpy.types.Operator):
|
|||||||
new.enum_value = data[attribute.name()]
|
new.enum_value = data[attribute.name()]
|
||||||
props.active_task_id = self.task
|
props.active_task_id = self.task
|
||||||
props.editing_task_type = "ATTRIBUTES"
|
props.editing_task_type = "ATTRIBUTES"
|
||||||
bpy.ops.bim.load_task_properties()
|
|
||||||
return {"FINISHED"}
|
return {"FINISHED"}
|
||||||
|
|
||||||
|
|
||||||
@@ -1159,3 +1161,26 @@ class RemoveTaskCalendar(bpy.types.Operator):
|
|||||||
)
|
)
|
||||||
Data.load(IfcStore.get_file())
|
Data.load(IfcStore.get_file())
|
||||||
return {"FINISHED"}
|
return {"FINISHED"}
|
||||||
|
|
||||||
|
|
||||||
|
class EnableEditingTaskSequence(bpy.types.Operator):
|
||||||
|
bl_idname = "bim.enable_editing_task_sequence"
|
||||||
|
bl_label = "Enable Editing Task Sequence"
|
||||||
|
task: bpy.props.IntProperty()
|
||||||
|
|
||||||
|
def execute(self, context):
|
||||||
|
props = context.scene.BIMWorkScheduleProperties
|
||||||
|
props.active_task_id = self.task
|
||||||
|
props.editing_task_type = "SEQUENCE"
|
||||||
|
bpy.ops.bim.load_task_properties()
|
||||||
|
return {"FINISHED"}
|
||||||
|
|
||||||
|
|
||||||
|
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"}
|
||||||
|
|||||||
@@ -156,7 +156,7 @@ class BIMWorkScheduleProperties(PropertyGroup):
|
|||||||
active_task_index: IntProperty(name="Active Task Index")
|
active_task_index: IntProperty(name="Active Task Index")
|
||||||
active_task_id: IntProperty(name="Active Task Id")
|
active_task_id: IntProperty(name="Active Task Id")
|
||||||
task_attributes: CollectionProperty(name="Task Attributes", type=Attribute)
|
task_attributes: CollectionProperty(name="Task Attributes", type=Attribute)
|
||||||
should_show_times: BoolProperty(name="Should Show Times", default=True)
|
should_show_times: BoolProperty(name="Should Show Times", default=False)
|
||||||
active_task_time_id: IntProperty(name="Active Task Id")
|
active_task_time_id: IntProperty(name="Active Task Id")
|
||||||
task_time_attributes: CollectionProperty(name="Task Time Attributes", type=Attribute)
|
task_time_attributes: CollectionProperty(name="Task Time Attributes", type=Attribute)
|
||||||
contracted_tasks: StringProperty(name="Contracted Task Items", default="[]")
|
contracted_tasks: StringProperty(name="Contracted Task Items", default="[]")
|
||||||
|
|||||||
@@ -149,9 +149,30 @@ class BIM_PT_work_schedules(Panel):
|
|||||||
self.draw_editable_task_attributes_ui()
|
self.draw_editable_task_attributes_ui()
|
||||||
elif self.props.active_task_id and self.props.editing_task_type == "CALENDAR":
|
elif self.props.active_task_id and self.props.editing_task_type == "CALENDAR":
|
||||||
self.draw_editable_task_calendar_ui()
|
self.draw_editable_task_calendar_ui()
|
||||||
|
elif self.props.active_task_id and self.props.editing_task_type == "SEQUENCE":
|
||||||
|
self.draw_editable_task_sequence_ui()
|
||||||
elif self.props.active_task_time_id and self.props.editing_task_type == "TASKTIME":
|
elif self.props.active_task_time_id and self.props.editing_task_type == "TASKTIME":
|
||||||
self.draw_editable_task_time_attributes_ui()
|
self.draw_editable_task_time_attributes_ui()
|
||||||
|
|
||||||
|
def draw_editable_task_sequence_ui(self):
|
||||||
|
task = 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")
|
||||||
|
|
||||||
|
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")
|
||||||
|
|
||||||
|
def draw_editable_sequence_ui(self, sequence, process_type):
|
||||||
|
task = 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")
|
||||||
|
|
||||||
def draw_editable_task_calendar_ui(self):
|
def draw_editable_task_calendar_ui(self):
|
||||||
task = Data.tasks[self.props.active_task_id]
|
task = Data.tasks[self.props.active_task_id]
|
||||||
if task["HasAssignmentsWorkCalendar"]:
|
if task["HasAssignmentsWorkCalendar"]:
|
||||||
@@ -240,31 +261,35 @@ class BIM_UL_tasks(UIList):
|
|||||||
row.operator("bim.edit_task_time", text="", icon="CHECKMARK")
|
row.operator("bim.edit_task_time", text="", icon="CHECKMARK")
|
||||||
elif props.editing_task_type == "CALENDAR":
|
elif props.editing_task_type == "CALENDAR":
|
||||||
row.operator("bim.disable_editing_task", text="", icon="CHECKMARK")
|
row.operator("bim.disable_editing_task", text="", icon="CHECKMARK")
|
||||||
|
elif props.editing_task_type == "SEQUENCE":
|
||||||
|
row.operator("bim.disable_editing_task", text="", icon="CHECKMARK")
|
||||||
elif props.editing_task_type == "ATTRIBUTES":
|
elif props.editing_task_type == "ATTRIBUTES":
|
||||||
row.operator("bim.edit_task", text="", icon="CHECKMARK")
|
row.operator("bim.edit_task", text="", icon="CHECKMARK")
|
||||||
row.operator("bim.disable_editing_task", text="", icon="CANCEL")
|
row.operator("bim.disable_editing_task", text="", icon="CANCEL")
|
||||||
elif props.active_task_id:
|
elif props.active_task_id:
|
||||||
if item.is_predecessor:
|
if props.editing_task_type == "SEQUENCE":
|
||||||
row.operator(
|
if item.is_predecessor:
|
||||||
"bim.unassign_predecessor", text="", icon="BACK", emboss=False
|
row.operator(
|
||||||
).task = item.ifc_definition_id
|
"bim.unassign_predecessor", text="", icon="BACK", emboss=False
|
||||||
else:
|
).task = item.ifc_definition_id
|
||||||
row.operator(
|
else:
|
||||||
"bim.assign_predecessor", text="", icon="TRACKING_BACKWARDS", emboss=False
|
row.operator(
|
||||||
).task = item.ifc_definition_id
|
"bim.assign_predecessor", text="", icon="TRACKING_BACKWARDS", emboss=False
|
||||||
|
).task = item.ifc_definition_id
|
||||||
|
|
||||||
if item.is_successor:
|
if item.is_successor:
|
||||||
row.operator(
|
row.operator(
|
||||||
"bim.unassign_successor", text="", icon="FORWARD", emboss=False
|
"bim.unassign_successor", text="", icon="FORWARD", emboss=False
|
||||||
).task = item.ifc_definition_id
|
).task = item.ifc_definition_id
|
||||||
else:
|
else:
|
||||||
row.operator(
|
row.operator(
|
||||||
"bim.assign_successor", text="", icon="TRACKING_FORWARDS", emboss=False
|
"bim.assign_successor", text="", icon="TRACKING_FORWARDS", emboss=False
|
||||||
).task = item.ifc_definition_id
|
).task = item.ifc_definition_id
|
||||||
|
|
||||||
row.operator("bim.add_task", text="", icon="ADD").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
|
row.operator("bim.remove_task", text="", icon="X").task = item.ifc_definition_id
|
||||||
else:
|
else:
|
||||||
|
row.operator("bim.enable_editing_task_sequence", text="", icon="TRACKING").task = item.ifc_definition_id
|
||||||
row.operator("bim.enable_editing_task_time", text="", icon="TIME").task = item.ifc_definition_id
|
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_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.enable_editing_task", text="", icon="GREASEPENCIL").task = item.ifc_definition_id
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ class Data:
|
|||||||
time_periods = {}
|
time_periods = {}
|
||||||
tasks = {}
|
tasks = {}
|
||||||
task_times = {}
|
task_times = {}
|
||||||
|
sequences = {}
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def purge(cls):
|
def purge(cls):
|
||||||
@@ -23,6 +24,7 @@ class Data:
|
|||||||
cls.time_periods = {}
|
cls.time_periods = {}
|
||||||
cls.tasks = {}
|
cls.tasks = {}
|
||||||
cls.task_times = {}
|
cls.task_times = {}
|
||||||
|
cls.sequences = {}
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def load(cls, file):
|
def load(cls, file):
|
||||||
@@ -37,6 +39,7 @@ class Data:
|
|||||||
cls.load_time_periods()
|
cls.load_time_periods()
|
||||||
cls.load_tasks()
|
cls.load_tasks()
|
||||||
cls.load_task_times()
|
cls.load_task_times()
|
||||||
|
cls.load_sequences()
|
||||||
cls.is_loaded = True
|
cls.is_loaded = True
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
@@ -132,8 +135,8 @@ class Data:
|
|||||||
for r in task.HasAssignments
|
for r in task.HasAssignments
|
||||||
if r.is_a("IfcRelAssignsToProduct")
|
if r.is_a("IfcRelAssignsToProduct")
|
||||||
]
|
]
|
||||||
[data["IsPredecessorTo"].append(rel.RelatedProcess.id()) for rel in task.IsPredecessorTo or []]
|
[data["IsPredecessorTo"].append(rel.id()) for rel in task.IsPredecessorTo or []]
|
||||||
[data["IsSuccessorFrom"].append(rel.RelatingProcess.id()) for rel in task.IsSuccessorFrom or []]
|
[data["IsSuccessorFrom"].append(rel.id()) for rel in task.IsSuccessorFrom or []]
|
||||||
[
|
[
|
||||||
data["HasAssignmentsWorkCalendar"].append(rel.RelatingControl.id())
|
data["HasAssignmentsWorkCalendar"].append(rel.RelatingControl.id())
|
||||||
for rel in task.HasAssignments or []
|
for rel in task.HasAssignments or []
|
||||||
@@ -153,3 +156,13 @@ class Data:
|
|||||||
data[key] = ifcopenshell.util.date.ifc2datetime(value)
|
data[key] = ifcopenshell.util.date.ifc2datetime(value)
|
||||||
# TODO parse duration
|
# TODO parse duration
|
||||||
cls.task_times[task_time.id()] = data
|
cls.task_times[task_time.id()] = data
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def load_sequences(cls):
|
||||||
|
cls.sequences = {}
|
||||||
|
for sequence in cls._file.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.sequences[sequence.id()] = data
|
||||||
|
|||||||
@@ -130,6 +130,7 @@ class P62Ifc:
|
|||||||
self.relationships[relationship.find("pr:ObjectId", self.ns).text] = {
|
self.relationships[relationship.find("pr:ObjectId", self.ns).text] = {
|
||||||
"PredecessorActivity": relationship.find("pr:PredecessorActivityObjectId", self.ns).text,
|
"PredecessorActivity": relationship.find("pr:PredecessorActivityObjectId", self.ns).text,
|
||||||
"SuccessorActivity": relationship.find("pr:SuccessorActivityObjectId", self.ns).text,
|
"SuccessorActivity": relationship.find("pr:SuccessorActivityObjectId", self.ns).text,
|
||||||
|
"Type": relationship.find("pr:Type", self.ns).text,
|
||||||
}
|
}
|
||||||
|
|
||||||
def get_wbs(self, wbs):
|
def get_wbs(self, wbs):
|
||||||
@@ -338,13 +339,25 @@ class P62Ifc:
|
|||||||
)
|
)
|
||||||
|
|
||||||
def create_rel_sequences(self):
|
def create_rel_sequences(self):
|
||||||
|
self.sequence_type_map = {
|
||||||
|
"Start to Start": "START_START",
|
||||||
|
"Start to Finish": "START_FINISH",
|
||||||
|
"Finish to Start": "FINISH_START",
|
||||||
|
"Finish to Finish": "FINISH_FINISH",
|
||||||
|
}
|
||||||
for relationship in self.relationships.values():
|
for relationship in self.relationships.values():
|
||||||
ifcopenshell.api.run(
|
rel_sequence = ifcopenshell.api.run(
|
||||||
"sequence.assign_sequence",
|
"sequence.assign_sequence",
|
||||||
self.file,
|
self.file,
|
||||||
relating_process=self.activities[relationship["PredecessorActivity"]]["ifc"],
|
relating_process=self.activities[relationship["PredecessorActivity"]]["ifc"],
|
||||||
related_process=self.activities[relationship["SuccessorActivity"]]["ifc"],
|
related_process=self.activities[relationship["SuccessorActivity"]]["ifc"],
|
||||||
)
|
)
|
||||||
|
ifcopenshell.api.run(
|
||||||
|
"sequence.edit_sequence",
|
||||||
|
self.file,
|
||||||
|
rel_sequence=rel_sequence,
|
||||||
|
attributes={"SequenceType": self.sequence_type_map[relationship["Type"]]},
|
||||||
|
)
|
||||||
|
|
||||||
def create_boilerplate_ifc(self):
|
def create_boilerplate_ifc(self):
|
||||||
self.file = ifcopenshell.file(schema="IFC4")
|
self.file = ifcopenshell.file(schema="IFC4")
|
||||||
|
|||||||
Reference in New Issue
Block a user