-
Notifications
You must be signed in to change notification settings - Fork 33
/
ops_proxy.py
122 lines (93 loc) · 3.76 KB
/
ops_proxy.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
121
122
# SPDX-FileCopyrightText: 2014-2024 Mikhail Rachinskiy
# SPDX-License-Identifier: GPL-3.0-or-later
import bpy
from bpy.types import Operator
class ANIM_OT_bake(Operator):
bl_label = "Bake Animation"
bl_description = "Bake procedural animation into keyframes"
bl_idname = "anim.commotion_bake"
bl_options = {"REGISTER", "UNDO"}
def modal(self, context, event):
if event.type in {"ESC", "RIGHTMOUSE"}:
self.cancel(context)
return {"FINISHED"}
elif event.type == "TIMER":
scene = context.scene
props = scene.commotion
if self.frame <= scene.frame_end:
for ob in props.proxy_coll_animated.objects:
for dp in self.dpaths:
ob.keyframe_insert(data_path=dp)
if self.use_sk:
try:
ob_sk = ob.data.shape_keys
ob_sk.keyframe_insert(data_path="eval_time")
except AttributeError:
pass
self.frame += 1
scene.frame_set(self.frame)
else:
self.cancel(context)
return {"FINISHED"}
return {"RUNNING_MODAL"}
def cancel(self, context):
wm = context.window_manager
wm.event_timer_remove(self._timer)
def execute(self, context):
wm = context.window_manager
self._timer = wm.event_timer_add(1 / 60, window=context.window)
wm.modal_handler_add(self)
return {"RUNNING_MODAL"}
def invoke(self, context, event):
scene = context.scene
props = scene.commotion
if (
not (props.proxy_coll_animated and props.proxy_coll_effectors) or
not (props.proxy_use_loc or props.proxy_use_rot or props.proxy_use_sca or props.proxy_use_sk)
):
return {"CANCELLED"}
self.frame = scene.frame_start
scene.frame_set(self.frame)
self.dpaths = []
if props.proxy_use_loc:
self.dpaths.append("delta_location")
if props.proxy_use_rot:
self.dpaths.append("delta_rotation_euler")
if props.proxy_use_sca:
self.dpaths.append("delta_scale")
self.use_sk = props.proxy_use_sca
return self.execute(context)
class ANIM_OT_bake_remove(Operator):
bl_label = "Free Bake"
bl_description = "Remove baked keyframes"
bl_idname = "anim.commotion_bake_remove"
bl_options = {"REGISTER", "UNDO"}
def execute(self, context):
scene = context.scene
props = scene.commotion
if not props.proxy_coll_animated:
return {"CANCELLED"}
reset_loc = props.proxy_start_loc if props.proxy_use_loc else (0.0, 0.0, 0.0)
reset_rot = props.proxy_start_rot if props.proxy_use_rot else (0.0, 0.0, 0.0)
reset_sca = props.proxy_start_sca if props.proxy_use_sca else (1.0, 1.0, 1.0)
reset_sk = props.proxy_start_sk if props.proxy_use_sk else 0.0
ob_data_prev = None
for ob in props.proxy_coll_animated.objects:
try:
action = ob.animation_data.action
bpy.data.actions.remove(action)
except AttributeError:
pass
ob.delta_location = reset_loc
ob.delta_rotation_euler = reset_rot
ob.delta_scale = reset_sca
if ob.data is not ob_data_prev:
try:
sk = ob.data.shape_keys
action = sk.animation_data.action
bpy.data.actions.remove(action)
sk.eval_time = reset_sk
except AttributeError:
pass
ob_data_prev = ob.data
return {"FINISHED"}