-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathkeyframe_importer.py
120 lines (90 loc) · 3.51 KB
/
keyframe_importer.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
# SPDX-License-Identifier: BSD-2-Clause
import pickle
import bpy
from bpy.props import StringProperty
from bpy.types import Operator, Panel
from bpy_extras.io_utils import ImportHelper
bl_info = {
"name": "Keyframe Importer",
"author": "Nicholas Pfaff",
"version": (1, 0),
"blender": (4, 0, 0),
"location": "View3D > UI > Keyframe Importer",
"description": "Import keyframes from recording server",
"category": "Animation",
}
class KeyframeImportOperator(Operator, ImportHelper):
"""
Import keyframes from a pickle file.
The data must have the following format:
```
[
[
{
"name": "object_name",
"location": (x, y, z),
"rotation_quaternion": (x, y, z, w),
},
...
]
]
```
where the outer list is a list of frames and the inner list is a list of objects.
The keyframes are only added for the objects that are already present in the scene.
Hence, the recommended workflow is to first load the .blend file that was exported
by `drake_recording_server.py` and then import the keyframe pickle file that was
saved by the server.
"""
bl_idname = "animation.import_keyframes"
bl_label = "Import Keyframes"
filename_ext = ".pkl"
filter_glob: StringProperty(default="*.pkl", options={"HIDDEN"})
def execute(self, context):
try:
with open(self.filepath, "rb") as f:
keyframes = pickle.load(f)
for frame_idx, frame_data in enumerate(keyframes):
# Set the current frame.
bpy.context.scene.frame_set(frame_idx)
for obj_data in frame_data:
obj_name = obj_data["name"]
if obj_name not in bpy.data.objects:
self.report(
{"WARNING"},
f"Object {obj_name} not found in scene",
)
continue
obj = bpy.data.objects[obj_name]
# Set location.
obj.location = obj_data["location"]
obj.keyframe_insert(data_path="location")
# Set rotation.
obj.rotation_mode = "QUATERNION"
obj.rotation_quaternion = obj_data["rotation_quaternion"]
obj.keyframe_insert(data_path="rotation_quaternion")
# Set animation range.
bpy.context.scene.frame_start = 0
bpy.context.scene.frame_end = len(keyframes) - 1
self.report({"INFO"}, f"Successfully imported {len(keyframes)} frames")
return {"FINISHED"}
except Exception as e:
self.report({"ERROR"}, f"Error importing keyframes: {str(e)}")
return {"CANCELLED"}
class KeyframeImporterPanel(Panel):
"""Creates a Panel in the 3D Viewport UI"""
bl_label = "Keyframe Importer"
bl_idname = "VIEW3D_PT_keyframe_importer"
bl_space_type = "VIEW_3D"
bl_region_type = "UI"
bl_category = "Keyframe Importer"
def draw(self, context):
layout = self.layout
layout.operator(KeyframeImportOperator.bl_idname, text="Import Keyframes")
def register():
bpy.utils.register_class(KeyframeImportOperator)
bpy.utils.register_class(KeyframeImporterPanel)
def unregister():
bpy.utils.unregister_class(KeyframeImportOperator)
bpy.utils.unregister_class(KeyframeImporterPanel)
if __name__ == "__main__":
register()