New feature to see the current frame's real life date as text during a generated animation

This commit is contained in:
Dion Moult
2021-09-20 17:06:02 +10:00
parent 8cde074fd8
commit 132ec473ec
16 changed files with 219 additions and 17 deletions
+3 -1
View File
@@ -1312,7 +1312,9 @@ class IfcImporter:
if "TargetView" in pset:
camera.BIMCameraProperties.target_view = pset["TargetView"]
if "Scale" in pset:
valid_scales = [i[0] for i in get_diagram_scales(None, bpy.context) if pset["Scale"] == i[0].split("|")[-1]]
valid_scales = [
i[0] for i in get_diagram_scales(None, bpy.context) if pset["Scale"] == i[0].split("|")[-1]
]
if valid_scales:
camera.BIMCameraProperties.diagram_scale = valid_scales[0]
else:
@@ -116,7 +116,13 @@ class CreateAllShapes(bpy.types.Operator):
start = time.time()
try:
shape = ifcopenshell.geom.create_shape(settings, element)
print("Success", time.time()-start, len(shape.geometry.verts), len(shape.geometry.edges), len(shape.geometry.faces))
print(
"Success",
time.time() - start,
len(shape.geometry.verts),
len(shape.geometry.edges),
len(shape.geometry.faces),
)
except:
failures.append(element)
print("***** FAILURE *****")
@@ -102,7 +102,7 @@ class BIMProjectProperties(PropertyGroup):
("BLACKLIST", "Blacklist", "Filter objects using a custom blacklist query"),
],
name="Filter Mode",
update=update_filter_mode
update=update_filter_mode,
)
filter_categories: CollectionProperty(name="Filter Categories", type=FilterCategory)
active_filter_category_index: IntProperty(name="Active Filter Category Index")
@@ -119,6 +119,5 @@ class BIMProjectProperties(PropertyGroup):
links: CollectionProperty(name="Links", type=Link)
active_link_index: IntProperty(name="Active Link Index")
def get_library_element_index(self, lib_element):
return next((i for i in range(len(self.library_elements)) if self.library_elements[i] == lib_element))
@@ -271,9 +271,9 @@ class BIM_UL_links(UIList):
row.label(text=item.name)
if item.is_loaded:
op = row.operator("bim.unload_link", text="", icon="UNLINKED")
op.filepath=item.name
op.filepath = item.name
else:
op = row.operator("bim.load_link", text="", icon="LINKED")
op.filepath=item.name
op.filepath = item.name
op = row.operator("bim.unlink_ifc", text="", icon="X")
op.filepath=item.name
op.filepath = item.name
@@ -109,6 +109,7 @@ classes = (
prop.RecurrenceComponent,
prop.BIMWorkCalendarProperties,
prop.DatePickerProperties,
prop.BIMDateTextProperties,
ui.BIM_PT_work_plans,
ui.BIM_PT_work_schedules,
ui.BIM_PT_work_calendars,
@@ -132,6 +133,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.TextCurve.BIMDateTextProperties = bpy.props.PointerProperty(type=prop.BIMDateTextProperties)
bpy.types.TOPBAR_MT_file_import.append(menu_func_import)
@@ -141,4 +143,5 @@ def unregister():
del bpy.types.Scene.BIMTaskTreeProperties
del bpy.types.Scene.BIMWorkCalendarProperties
del bpy.types.Scene.DatePickerProperties
del bpy.types.TextCurve.BIMDateTextProperties
bpy.types.TOPBAR_MT_file_import.remove(menu_func_import)
@@ -1742,11 +1742,12 @@ class VisualiseWorkScheduleDateRange(bpy.types.Operator):
self.animate_input(obj, product_frame)
elif product_frame["relationship"] == "output":
self.animate_output(obj, product_frame)
self.add_text_animation_handler()
area = next(area for area in context.screen.areas if area.type == "VIEW_3D")
area.spaces[0].shading.color_type = "OBJECT"
context.scene.frame_start = self.start_frame
context.scene.frame_end = self.start_frame + self.total_frames
context.scene.frame_end = int(self.start_frame + self.total_frames)
# with open("/home/dion/animation.json", "w") as json_file:
# guid_frames = {}
# for k, v in self.product_frames.items():
@@ -1754,6 +1755,35 @@ class VisualiseWorkScheduleDateRange(bpy.types.Operator):
# json.dump(guid_frames, json_file)
return {"FINISHED"}
def add_text_animation_handler(self):
data = bpy.data.curves.get("Timeline")
if not data:
data = bpy.data.curves.new(type="FONT", name="Timeline")
obj = bpy.data.objects.get("Timeline")
if not obj:
obj = bpy.data.objects.new(name="Timeline", object_data=data)
bpy.context.scene.collection.objects.link(obj)
obj.data.BIMDateTextProperties.start_frame = self.start_frame
obj.data.BIMDateTextProperties.total_frames = int(self.total_frames)
obj.data.BIMDateTextProperties.start = self.props.visualisation_start
obj.data.BIMDateTextProperties.finish = self.props.visualisation_finish
bpy.app.handlers.frame_change_post.append(self.animate_text)
def remove_text_animation_handler(self):
bpy.app.handlers.frame_change_post.remove(self.animate_text)
def animate_text(self, scene, context):
data = bpy.data.curves.get("Timeline")
if not data or not bpy.data.objects.get("Timeline"):
self.remove_text_animation_handler()
scene.frame_current
props = data.BIMDateTextProperties
start = parser.parse(props.start, dayfirst=True, fuzzy=True)
finish = parser.parse(props.finish, dayfirst=True, fuzzy=True)
duration = finish - start
frame_date = (((scene.frame_current - props.start_frame) / props.total_frames) * duration) + start
data.body = frame_date.date().isoformat()
def animate_input(self, obj, product_frame):
if product_frame["type"] in ["LOGISTIC", "MOVE", "DISPOSAL"]:
self.animate_movement_from(obj, product_frame)
@@ -204,15 +204,15 @@ def updateTaskDuration(self, context):
bpy.ops.bim.load_task_properties()
def updateVisualisationStart(self, context):
updateVisualisationStartFinish(self, context, "visualisation_start")
def update_visualisation_start(self, context):
update_visualisation_start_finish(self, context, "visualisation_start")
def updateVisualisationFinish(self, context):
updateVisualisationStartFinish(self, context, "visualisation_finish")
def update_visualisation_finish(self, context):
update_visualisation_start_finish(self, context, "visualisation_finish")
def updateVisualisationStartFinish(self, context, startfinish):
def update_visualisation_start_finish(self, context, startfinish):
def canonicalise_time(time):
if not time:
return "-"
@@ -316,8 +316,8 @@ class BIMWorkScheduleProperties(PropertyGroup):
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)
visualisation_start: StringProperty(name="Visualisation Start", update=updateVisualisationStart)
visualisation_finish: StringProperty(name="Visualisation Finish", update=updateVisualisationFinish)
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)
speed_animation_duration: StringProperty(name="Speed Animation Duration", default="PT1S")
speed_animation_frames: IntProperty(name="Speed Animation Frames", default=24)
@@ -388,3 +388,10 @@ class BIMWorkCalendarProperties(PropertyGroup):
class DatePickerProperties(PropertyGroup):
display_date: StringProperty()
selected_date: StringProperty()
class BIMDateTextProperties(PropertyGroup):
start_frame: IntProperty(name="Start Frame")
total_frames: IntProperty(name="Total Frames")
start: StringProperty(name="Start")
finish: StringProperty(name="Finish")
+1 -1
View File
@@ -104,7 +104,7 @@ class ImportIFC(bpy.types.Operator):
bl_options = {"REGISTER", "UNDO"}
def execute(self, context):
bpy.ops.bim.load_project('INVOKE_DEFAULT')
bpy.ops.bim.load_project("INVOKE_DEFAULT")
return {"FINISHED"}
+13 -1
View File
@@ -78,6 +78,10 @@ def additionally_the_object_name_is_selected(name):
obj.select_set(True)
def i_am_on_frame_number(number):
bpy.context.scene.frame_set(int(number))
def i_set_prop_to_value(prop, value):
try:
eval(f"bpy.context.{prop}")
@@ -159,6 +163,10 @@ def the_object_name_is_not_in_the_collection_collection(name, collection):
assert collection not in [c.name for c in the_object_name_exists(name).users_collection]
def the_object_name_has_a_body_of_value(name, value):
assert the_object_name_exists(name).data.body == value
def the_collection_name1_is_in_the_collection_name2(name1, name2):
assert bpy.data.collections.get(name2).children.get(name1)
@@ -256,7 +264,9 @@ def the_object_name_has_number_vertices(name, number):
def the_object_name_is_at_location(name, location):
obj_location = the_object_name_exists(name).location
assert (obj_location - Vector([float(co) for co in location.split(",")])).length < 0.1, f"Object is at {obj_location}"
assert (
obj_location - Vector([float(co) for co in location.split(",")])
).length < 0.1, f"Object is at {obj_location}"
definitions = {
@@ -265,6 +275,7 @@ definitions = {
'I add a cube of size "([0-9]+)" at "(.*)"': i_add_a_cube_of_size_size_at_location,
'the object "(.*)" is selected': the_object_name_is_selected,
'additionally the object "(.*)" is selected': additionally_the_object_name_is_selected,
'I am on frame "([0-9]+)"': i_am_on_frame_number,
'I set "(.*)" to "(.*)"': i_set_prop_to_value,
'"(.*)" is "(.*)"': prop_is_value,
'I enable "(.*)"': i_enable_prop,
@@ -275,6 +286,7 @@ definitions = {
'the object "(.*)" is not an IFC element': the_object_name_is_not_an_ifc_element,
'the object "(.*)" is in the collection "(.*)"': the_object_name_is_in_the_collection_collection,
'the object "(.*)" is not in the collection "(.*)"': the_object_name_is_not_in_the_collection_collection,
'the object "(.*)" has a body of "(.*)"': the_object_name_has_a_body_of_value,
'the collection "(.*)" is in the collection "(.*)"': the_collection_name1_is_in_the_collection_name2,
'the collection "(.*)" is not in the collection "(.*)"': the_collection_name1_is_not_in_the_collection_name2,
"an IFC file exists": an_ifc_file_exists,
@@ -0,0 +1,17 @@
# BlenderBIM Add-on - OpenBIM Blender Add-on
# Copyright (C) 2021 Dion Moult <dion@thinkmoult.com>
#
# This file is part of BlenderBIM Add-on.
#
# BlenderBIM Add-on is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# BlenderBIM Add-on is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# 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/>.
@@ -0,0 +1,17 @@
# BlenderBIM Add-on - OpenBIM Blender Add-on
# Copyright (C) 2021 Dion Moult <dion@thinkmoult.com>
#
# This file is part of BlenderBIM Add-on.
#
# BlenderBIM Add-on is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# BlenderBIM Add-on is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# 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/>.
@@ -0,0 +1,17 @@
# BlenderBIM Add-on - OpenBIM Blender Add-on
# Copyright (C) 2021 Dion Moult <dion@thinkmoult.com>
#
# This file is part of BlenderBIM Add-on.
#
# BlenderBIM Add-on is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# BlenderBIM Add-on is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# 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/>.
@@ -0,0 +1,17 @@
# BlenderBIM Add-on - OpenBIM Blender Add-on
# Copyright (C) 2021 Dion Moult <dion@thinkmoult.com>
#
# This file is part of BlenderBIM Add-on.
#
# BlenderBIM Add-on is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# BlenderBIM Add-on is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# 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/>.
@@ -0,0 +1,39 @@
# BlenderBIM Add-on - OpenBIM Blender Add-on
# Copyright (C) 2021 Dion Moult <dion@thinkmoult.com>
#
# This file is part of BlenderBIM Add-on.
#
# BlenderBIM Add-on is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# BlenderBIM Add-on is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# 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 test.bim.bootstrap
class TestVisualiseWorkScheduleDateRange(test.bim.bootstrap.NewFile):
@test.bim.bootstrap.scenario
def test_seeing_the_current_frame_date_as_text(self):
return """
Given an empty IFC project
And I press "bim.add_work_schedule"
And I press "bim.enable_editing_tasks(work_schedule=72)"
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 "P1W"
And I press "bim.visualise_work_schedule_date_range(work_schedule=72)"
When I am on frame "1"
Then the object "Timeline" has a body of "2021-01-01"
When I am on frame "2"
Then the object "Timeline" has a body of "2021-01-02"
"""
@@ -0,0 +1,17 @@
# BlenderBIM Add-on - OpenBIM Blender Add-on
# Copyright (C) 2021 Dion Moult <dion@thinkmoult.com>
#
# This file is part of BlenderBIM Add-on.
#
# BlenderBIM Add-on is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# BlenderBIM Add-on is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# 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/>.
+19
View File
@@ -1,4 +1,23 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
BlenderBIM Add-on - OpenBIM Blender Add-on
Copyright (C) 2021 Dion Moult <dion@thinkmoult.com>
This file is part of BlenderBIM Add-on.
BlenderBIM Add-on is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
BlenderBIM Add-on is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
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/>.
-->
<ids xmlns="http://standards.buildingsmart.org/IDS" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://standards.buildingsmart.org/IDS ids_04.xsd">
<specification name="Sample IDS" necessity="required">
<applicability>