mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-09-20 15:08:51 +00:00
feature to clear previous 4D Animation (object keyframes & colors)
This commit is contained in:
@@ -20,12 +20,10 @@ import bpy
|
|||||||
from . import ui, prop, operator
|
from . import ui, prop, operator
|
||||||
|
|
||||||
classes = (
|
classes = (
|
||||||
operator.ExpandAllTasks,
|
|
||||||
operator.ContractAllTasks,
|
|
||||||
operator.AddSummaryTask,
|
operator.AddSummaryTask,
|
||||||
operator.AddTask,
|
operator.AddTask,
|
||||||
operator.AddTaskColumn,
|
|
||||||
operator.AddTaskBars,
|
operator.AddTaskBars,
|
||||||
|
operator.AddTaskColumn,
|
||||||
operator.AddTimePeriod,
|
operator.AddTimePeriod,
|
||||||
operator.AddWorkCalendar,
|
operator.AddWorkCalendar,
|
||||||
operator.AddWorkPlan,
|
operator.AddWorkPlan,
|
||||||
@@ -42,11 +40,15 @@ classes = (
|
|||||||
operator.BlenderBIM_DatePickerSetDate,
|
operator.BlenderBIM_DatePickerSetDate,
|
||||||
operator.BlenderBIM_RedrawDatePicker,
|
operator.BlenderBIM_RedrawDatePicker,
|
||||||
operator.CalculateTaskDuration,
|
operator.CalculateTaskDuration,
|
||||||
|
operator.ClearPreviousAnimation,
|
||||||
|
operator.ContractAllTasks,
|
||||||
operator.ContractTask,
|
operator.ContractTask,
|
||||||
operator.CopyTaskAttribute,
|
|
||||||
operator.CopyTask,
|
operator.CopyTask,
|
||||||
|
operator.CopyTaskAttribute,
|
||||||
|
operator.CreateBaseline,
|
||||||
operator.DisableEditingSequence,
|
operator.DisableEditingSequence,
|
||||||
operator.DisableEditingTask,
|
operator.DisableEditingTask,
|
||||||
|
operator.DisableEditingTaskAnimationColors,
|
||||||
operator.DisableEditingTaskTime,
|
operator.DisableEditingTaskTime,
|
||||||
operator.DisableEditingWorkCalendar,
|
operator.DisableEditingWorkCalendar,
|
||||||
operator.DisableEditingWorkPlan,
|
operator.DisableEditingWorkPlan,
|
||||||
@@ -67,23 +69,27 @@ classes = (
|
|||||||
operator.EnableEditingTaskCalendar,
|
operator.EnableEditingTaskCalendar,
|
||||||
operator.EnableEditingTaskSequence,
|
operator.EnableEditingTaskSequence,
|
||||||
operator.EnableEditingTaskTime,
|
operator.EnableEditingTaskTime,
|
||||||
operator.EnableEditingWorkScheduleTasks,
|
|
||||||
operator.EnableEditingWorkCalendar,
|
operator.EnableEditingWorkCalendar,
|
||||||
operator.EnableEditingWorkCalendarTimes,
|
operator.EnableEditingWorkCalendarTimes,
|
||||||
operator.EnableEditingWorkPlan,
|
operator.EnableEditingWorkPlan,
|
||||||
operator.EnableEditingWorkPlanSchedules,
|
operator.EnableEditingWorkPlanSchedules,
|
||||||
operator.EnableEditingWorkSchedule,
|
operator.EnableEditingWorkSchedule,
|
||||||
|
operator.EnableEditingWorkScheduleTasks,
|
||||||
operator.EnableEditingWorkTime,
|
operator.EnableEditingWorkTime,
|
||||||
|
operator.ExpandAllTasks,
|
||||||
operator.ExpandTask,
|
operator.ExpandTask,
|
||||||
operator.ExportMSP,
|
operator.ExportMSP,
|
||||||
operator.ExportP6,
|
operator.ExportP6,
|
||||||
operator.GenerateGanttChart,
|
operator.GenerateGanttChart,
|
||||||
operator.GuessDateRange,
|
operator.GuessDateRange,
|
||||||
operator.ImportMSP,
|
operator.HighlightTask,
|
||||||
operator.ImportCSV,
|
operator.ImportCSV,
|
||||||
|
operator.ImportMSP,
|
||||||
operator.ImportP6,
|
operator.ImportP6,
|
||||||
operator.ImportP6XER,
|
operator.ImportP6XER,
|
||||||
operator.ImportPP,
|
operator.ImportPP,
|
||||||
|
operator.LoadProductTasks,
|
||||||
|
operator.LoadTaskAnimationColors,
|
||||||
operator.LoadTaskInputs,
|
operator.LoadTaskInputs,
|
||||||
operator.LoadTaskOutputs,
|
operator.LoadTaskOutputs,
|
||||||
operator.LoadTaskProperties,
|
operator.LoadTaskProperties,
|
||||||
@@ -98,10 +104,10 @@ classes = (
|
|||||||
operator.RemoveWorkSchedule,
|
operator.RemoveWorkSchedule,
|
||||||
operator.RemoveWorkTime,
|
operator.RemoveWorkTime,
|
||||||
operator.ReorderTask,
|
operator.ReorderTask,
|
||||||
operator.SelectTaskRelatedProducts,
|
|
||||||
operator.SelectTaskRelatedInputs,
|
operator.SelectTaskRelatedInputs,
|
||||||
operator.SelectWorkScheduleProducts,
|
operator.SelectTaskRelatedProducts,
|
||||||
operator.SelectUnassignedWorkScheduleProducts,
|
operator.SelectUnassignedWorkScheduleProducts,
|
||||||
|
operator.SelectWorkScheduleProducts,
|
||||||
operator.SetTaskSortColumn,
|
operator.SetTaskSortColumn,
|
||||||
operator.SetupDefaultTaskColumns,
|
operator.SetupDefaultTaskColumns,
|
||||||
operator.UnassignLagTime,
|
operator.UnassignLagTime,
|
||||||
@@ -113,11 +119,6 @@ classes = (
|
|||||||
operator.UnassignWorkSchedule,
|
operator.UnassignWorkSchedule,
|
||||||
operator.VisualiseWorkScheduleDate,
|
operator.VisualiseWorkScheduleDate,
|
||||||
operator.VisualiseWorkScheduleDateRange,
|
operator.VisualiseWorkScheduleDateRange,
|
||||||
operator.LoadTaskAnimationColors,
|
|
||||||
operator.DisableEditingTaskAnimationColors,
|
|
||||||
operator.LoadProductTasks,
|
|
||||||
operator.HighlightTask,
|
|
||||||
operator.CreateBaseline,
|
|
||||||
prop.WorkPlan,
|
prop.WorkPlan,
|
||||||
prop.BIMWorkPlanProperties,
|
prop.BIMWorkPlanProperties,
|
||||||
prop.Task,
|
prop.Task,
|
||||||
|
|||||||
@@ -1401,3 +1401,12 @@ class CreateBaseline(bpy.types.Operator, tool.Ifc.Operator):
|
|||||||
|
|
||||||
def invoke(self, context, event):
|
def invoke(self, context, event):
|
||||||
return context.window_manager.invoke_props_dialog(self)
|
return context.window_manager.invoke_props_dialog(self)
|
||||||
|
|
||||||
|
|
||||||
|
class ClearPreviousAnimation(bpy.types.Operator, tool.Ifc.Operator):
|
||||||
|
bl_idname = "bim.clear_previous_animation"
|
||||||
|
bl_label = "Clear Previous Animation"
|
||||||
|
bl_options = {"REGISTER", "UNDO"}
|
||||||
|
|
||||||
|
def _execute(self, context):
|
||||||
|
core.clear_previous_animation(tool.Sequence)
|
||||||
|
|||||||
@@ -444,6 +444,16 @@ class BIM_PT_animation_tools(Panel):
|
|||||||
self.draw_visualisation_ui()
|
self.draw_visualisation_ui()
|
||||||
if self.props.should_show_snapshot_ui:
|
if self.props.should_show_snapshot_ui:
|
||||||
self.draw_snapshot_ui()
|
self.draw_snapshot_ui()
|
||||||
|
self.draw_processing_options()
|
||||||
|
|
||||||
|
|
||||||
|
def draw_processing_options(self):
|
||||||
|
row = self.layout.row(align=True)
|
||||||
|
row.alignment = "LEFT"
|
||||||
|
row.label(text="Processing Tools")
|
||||||
|
row = self.layout.row()
|
||||||
|
row.alignment = "RIGHT"
|
||||||
|
row.operator("bim.clear_previous_animation", text="Clear Previous Animation", icon="TRACKING_CLEAR_FORWARDS")
|
||||||
|
|
||||||
def draw_visualisation_ui(self):
|
def draw_visualisation_ui(self):
|
||||||
row = self.layout.row(align=True)
|
row = self.layout.row(align=True)
|
||||||
@@ -467,12 +477,13 @@ class BIM_PT_animation_tools(Panel):
|
|||||||
row.prop(self.props, "speed_real_duration", text="")
|
row.prop(self.props, "speed_real_duration", text="")
|
||||||
elif self.props.speed_types == "DURATION_SPEED":
|
elif self.props.speed_types == "DURATION_SPEED":
|
||||||
row.prop(self.props, "speed_animation_duration", text="")
|
row.prop(self.props, "speed_animation_duration", text="")
|
||||||
|
row.label(text="->")
|
||||||
row.prop(self.props, "speed_real_duration", text="")
|
row.prop(self.props, "speed_real_duration", text="")
|
||||||
elif self.props.speed_types == "MULTIPLIER_SPEED":
|
elif self.props.speed_types == "MULTIPLIER_SPEED":
|
||||||
row.prop(self.props, "speed_multiplier", text="")
|
row.prop(self.props, "speed_multiplier", text="")
|
||||||
row = self.layout.row(align=True)
|
row = self.layout.row(align=True)
|
||||||
row.label(text="Display Settings")
|
row.label(text="Display Settings")
|
||||||
row = self.layout.row(align=True)
|
row = self.layout.row()
|
||||||
row.alignment = "RIGHT"
|
row.alignment = "RIGHT"
|
||||||
if not self.animation_props.is_editing:
|
if not self.animation_props.is_editing:
|
||||||
op = row.operator(
|
op = row.operator(
|
||||||
@@ -506,7 +517,6 @@ class BIM_PT_animation_tools(Panel):
|
|||||||
self.draw_visualisation_settings_ui()
|
self.draw_visualisation_settings_ui()
|
||||||
|
|
||||||
row = self.layout.row(align=True)
|
row = self.layout.row(align=True)
|
||||||
row.alignment = "RIGHT"
|
|
||||||
op = row.operator("bim.visualise_work_schedule_date_range", text="Create Animation", icon="OUTLINER_OB_CAMERA")
|
op = row.operator("bim.visualise_work_schedule_date_range", text="Create Animation", icon="OUTLINER_OB_CAMERA")
|
||||||
op.work_schedule = self.props.active_work_schedule_id
|
op.work_schedule = self.props.active_work_schedule_id
|
||||||
|
|
||||||
|
|||||||
@@ -530,6 +530,7 @@ def disable_editing_task_animation_colors(sequence):
|
|||||||
|
|
||||||
|
|
||||||
def visualise_work_schedule_date_range(sequence, work_schedule=None):
|
def visualise_work_schedule_date_range(sequence, work_schedule=None):
|
||||||
|
sequence.clear_objects_animation(include_blender_objects=False)
|
||||||
settings = sequence.get_animation_settings()
|
settings = sequence.get_animation_settings()
|
||||||
if settings:
|
if settings:
|
||||||
product_frames = sequence.get_animation_product_frames(work_schedule, settings)
|
product_frames = sequence.get_animation_product_frames(work_schedule, settings)
|
||||||
@@ -580,3 +581,6 @@ def reorder_task_nesting(ifc, sequence, task, new_index):
|
|||||||
|
|
||||||
def create_baseline(ifc, sequence, work_schedule, name):
|
def create_baseline(ifc, sequence, work_schedule, name):
|
||||||
ifc.run("sequence.create_baseline", work_schedule=work_schedule, name=name)
|
ifc.run("sequence.create_baseline", work_schedule=work_schedule, name=name)
|
||||||
|
|
||||||
|
def clear_previous_animation(sequence):
|
||||||
|
sequence.clear_objects_animation(include_blender_objects=False)
|
||||||
|
|||||||
@@ -19,7 +19,6 @@
|
|||||||
import bpy
|
import bpy
|
||||||
import re
|
import re
|
||||||
import os
|
import os
|
||||||
import isodate
|
|
||||||
import ifcopenshell
|
import ifcopenshell
|
||||||
import ifcopenshell.util.sequence
|
import ifcopenshell.util.sequence
|
||||||
import ifcopenshell.util.date
|
import ifcopenshell.util.date
|
||||||
@@ -36,7 +35,6 @@ from datetime import datetime
|
|||||||
import mathutils
|
import mathutils
|
||||||
import pystache
|
import pystache
|
||||||
import webbrowser
|
import webbrowser
|
||||||
from datetime import timedelta
|
|
||||||
|
|
||||||
|
|
||||||
class Sequence(blenderbim.core.tool.Sequence):
|
class Sequence(blenderbim.core.tool.Sequence):
|
||||||
@@ -212,7 +210,9 @@ class Sequence(blenderbim.core.tool.Sequence):
|
|||||||
item.calendar = ""
|
item.calendar = ""
|
||||||
item.derived_calendar = calendar.Name or "Unnamed" if calendar else ""
|
item.derived_calendar = calendar.Name or "Unnamed" if calendar else ""
|
||||||
|
|
||||||
if task.TaskTime and (task.TaskTime.ScheduleStart or task.TaskTime.ScheduleFinish or task.TaskTime.ScheduleDuration):
|
if task.TaskTime and (
|
||||||
|
task.TaskTime.ScheduleStart or task.TaskTime.ScheduleFinish or task.TaskTime.ScheduleDuration
|
||||||
|
):
|
||||||
task_time = task.TaskTime
|
task_time = task.TaskTime
|
||||||
item.start = (
|
item.start = (
|
||||||
canonicalise_time(ifcopenshell.util.date.ifc2datetime(task_time.ScheduleStart))
|
canonicalise_time(ifcopenshell.util.date.ifc2datetime(task_time.ScheduleStart))
|
||||||
@@ -721,7 +721,7 @@ class Sequence(blenderbim.core.tool.Sequence):
|
|||||||
def setup_default_task_columns(cls):
|
def setup_default_task_columns(cls):
|
||||||
props = bpy.context.scene.BIMWorkScheduleProperties
|
props = bpy.context.scene.BIMWorkScheduleProperties
|
||||||
props.columns.clear()
|
props.columns.clear()
|
||||||
default_columns = ["ScheduleStart","ScheduleFinish","ScheduleDuration"]
|
default_columns = ["ScheduleStart", "ScheduleFinish", "ScheduleDuration"]
|
||||||
for item in default_columns:
|
for item in default_columns:
|
||||||
new = props.columns.add()
|
new = props.columns.add()
|
||||||
new.name = f"IfcTaskTime.{item}"
|
new.name = f"IfcTaskTime.{item}"
|
||||||
@@ -798,6 +798,7 @@ class Sequence(blenderbim.core.tool.Sequence):
|
|||||||
def update_visualisation_date(cls, start_date, finish_date):
|
def update_visualisation_date(cls, start_date, finish_date):
|
||||||
def canonicalise_time(time):
|
def canonicalise_time(time):
|
||||||
return time.strftime("%d/%m/%y")
|
return time.strftime("%d/%m/%y")
|
||||||
|
|
||||||
if not (start_date and finish_date):
|
if not (start_date and finish_date):
|
||||||
return
|
return
|
||||||
props = bpy.context.scene.BIMWorkScheduleProperties
|
props = bpy.context.scene.BIMWorkScheduleProperties
|
||||||
@@ -1212,7 +1213,7 @@ class Sequence(blenderbim.core.tool.Sequence):
|
|||||||
start,
|
start,
|
||||||
finish,
|
finish,
|
||||||
props.speed_animation_frames,
|
props.speed_animation_frames,
|
||||||
ifcopenshell.util.date.parse_duration(props.speed_real_duration)
|
ifcopenshell.util.date.parse_duration(props.speed_real_duration),
|
||||||
)
|
)
|
||||||
elif props.speed_types == "DURATION_SPEED":
|
elif props.speed_types == "DURATION_SPEED":
|
||||||
animation_duration = ifcopenshell.util.date.parse_duration(props.speed_animation_duration)
|
animation_duration = ifcopenshell.util.date.parse_duration(props.speed_animation_duration)
|
||||||
@@ -1299,15 +1300,24 @@ class Sequence(blenderbim.core.tool.Sequence):
|
|||||||
if obj.animation_data:
|
if obj.animation_data:
|
||||||
obj.animation_data_clear()
|
obj.animation_data_clear()
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def clear_object_color(cls, obj):
|
||||||
|
obj.color = (1.0, 1.0, 1.0, 1.0)
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def display_object(cls, obj):
|
||||||
|
if not obj.visible_get():
|
||||||
|
obj.hide_viewport = False
|
||||||
|
obj.hide_render = False
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def clear_objects_animation(cls, include_blender_objects=True):
|
def clear_objects_animation(cls, include_blender_objects=True):
|
||||||
for obj in bpy.data.objects:
|
for obj in bpy.data.objects:
|
||||||
if not include_blender_objects and not obj.BIMObjectProperties.ifc_definition_id:
|
if not include_blender_objects and not obj.BIMObjectProperties.ifc_definition_id:
|
||||||
continue
|
continue
|
||||||
cls.clear_object_animation(obj)
|
cls.clear_object_animation(obj)
|
||||||
if not obj.visible_get():
|
cls.clear_object_color(obj)
|
||||||
obj.hide_viewport = False
|
cls.display_object(obj)
|
||||||
obj.hide_render = False
|
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def animate_objects(cls, settings, frames, clear_previous=True, animation_type=""):
|
def animate_objects(cls, settings, frames, clear_previous=True, animation_type=""):
|
||||||
@@ -1502,13 +1512,13 @@ class Sequence(blenderbim.core.tool.Sequence):
|
|||||||
compare_start = schedule_start
|
compare_start = schedule_start
|
||||||
compare_finish = schedule_finish
|
compare_finish = schedule_finish
|
||||||
task_name = task.Name or "Unnamed"
|
task_name = task.Name or "Unnamed"
|
||||||
task_name = task_name.replace('\n', "")
|
task_name = task_name.replace("\n", "")
|
||||||
data = {
|
data = {
|
||||||
"pID": task.id(),
|
"pID": task.id(),
|
||||||
"pName": task_name,
|
"pName": task_name,
|
||||||
"pCaption": task_name,
|
"pCaption": task_name,
|
||||||
"pStart": schedule_start,
|
"pStart": schedule_start,
|
||||||
"pEnd": schedule_finish ,
|
"pEnd": schedule_finish,
|
||||||
"pPlanStart": compare_start,
|
"pPlanStart": compare_start,
|
||||||
"pPlanEnd": compare_finish,
|
"pPlanEnd": compare_finish,
|
||||||
"pMile": 1 if task.IsMilestone else 0,
|
"pMile": 1 if task.IsMilestone else 0,
|
||||||
@@ -1602,4 +1612,5 @@ class Sequence(blenderbim.core.tool.Sequence):
|
|||||||
object_type = None
|
object_type = None
|
||||||
if predefined_type == "USERDEFINED":
|
if predefined_type == "USERDEFINED":
|
||||||
object_type = bpy.context.scene.BIMWorkScheduleProperties.object_type
|
object_type = bpy.context.scene.BIMWorkScheduleProperties.object_type
|
||||||
return predefined_type, object_type
|
return predefined_type, object_type
|
||||||
|
|
||||||
|
|||||||
@@ -532,6 +532,39 @@ Scenario: Animate the consumption of a wall
|
|||||||
Then "scene.objects.get('IfcWall/Cube').hide_render" is "True"
|
Then "scene.objects.get('IfcWall/Cube').hide_render" is "True"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Scenario: Clear Previous Animation
|
||||||
|
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_attributes(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 add a cube
|
||||||
|
And the object "Cube" is selected
|
||||||
|
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})"
|
||||||
|
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"
|
||||||
|
And I set "scene.BIMWorkScheduleProperties.speed_animation_frames" to "7"
|
||||||
|
And I set "scene.BIMWorkScheduleProperties.speed_real_duration" to "1 w"
|
||||||
|
And I press "bim.visualise_work_schedule_date_range(work_schedule={work_schedule})"
|
||||||
|
And I press "bim.clear_previous_animation"
|
||||||
|
When I am on frame "3"
|
||||||
|
Then "scene.objects.get('IfcWall/Cube').hide_viewport" is "False"
|
||||||
|
And "scene.objects.get('IfcWall/Cube').hide_render" is "False"
|
||||||
|
And "scene.objects.get('IfcWall/Cube').color[:]" is "[1.0, 1.0, 1.0, 1]"
|
||||||
|
|
||||||
Scenario: Generate Gantt Chart
|
Scenario: Generate Gantt Chart
|
||||||
Given an empty IFC project
|
Given an empty IFC project
|
||||||
And I press "bim.add_work_schedule"
|
And I press "bim.add_work_schedule"
|
||||||
@@ -808,4 +841,5 @@ Scenario: Duplicate Task and edit sequence Relationship
|
|||||||
And I press "bim.assign_successor(task={nested_task_two})"
|
And I press "bim.assign_successor(task={nested_task_two})"
|
||||||
And I press "bim.duplicate_task(task={task})"
|
And I press "bim.duplicate_task(task={task})"
|
||||||
When I press "bim.enable_editing_task_sequence(task={nested_task_one})"
|
When I press "bim.enable_editing_task_sequence(task={nested_task_one})"
|
||||||
Then nothing happens
|
Then nothing happens
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user