-
Notifications
You must be signed in to change notification settings - Fork 8
/
action_operators.py
177 lines (136 loc) · 5.58 KB
/
action_operators.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
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
import bpy
class DATA_OT_ap_action_new(bpy.types.Operator):
bl_idname = "armature.ap_action_new"
bl_label = "New Action"
bl_description = "Creates a new action"
bl_options = {"REGISTER", "UNDO"}
idx: bpy.props.IntProperty()
@classmethod
def poll(cls, context):
return context.mode == 'POSE'
def execute(self, context):
prefs = context.scene.ap_preferences
armature = context.active_object.data
ap_pose = armature.ap_poses[self.idx]
pose_name = ap_pose.name
action = bpy.data.actions.new(name=pose_name)
action.use_fake_user = True
ap_pose.action = action
if ap_pose.type == 'POSE':
action.name = prefs.pose_prefix + action.name
elif ap_pose.type == 'COMBO':
action.name = prefs.combo_prefix + action.name
return {'FINISHED'}
class DATA_OT_ap_action_duplicate(bpy.types.Operator):
bl_idname = "armature.ap_action_duplicate"
bl_label = "Duplicate action"
bl_description = "Duplicate action that is assigned to pose"
bl_options = {"REGISTER", "UNDO"}
idx: bpy.props.IntProperty()
@classmethod
def poll(cls, context):
if context.mode == 'POSE':
idx = context.active_object.data.ap_poses_index
if idx != -1 and context.active_object.data.ap_poses[idx].action:
return True
return False
def execute(self, context):
armature = context.active_object.data
ap_pose = armature.ap_poses[self.idx]
action = ap_pose.action
new_action = action.copy()
ap_pose.action = new_action
return {'FINISHED'}
class DATA_OT_ap_action_delete(bpy.types.Operator):
bl_idname = "armature.ap_action_delete"
bl_label = "Delete action"
bl_description = "Permanently deletes action that is assigned to pose"
bl_options = {"REGISTER", "UNDO"}
idx: bpy.props.IntProperty()
@classmethod
def poll(cls, context):
if context.mode == 'POSE':
idx = context.active_object.data.ap_poses_index
if context.active_object.data.ap_poses[idx].action:
return True
return False
def execute(self, context):
armature = context.active_object.data
ap_pose = armature.ap_poses[self.idx]
action = ap_pose.action
bpy.data.actions.remove(action)
return {'FINISHED'}
### Adapted from https://github.com/Muream/actionman
class DATA_OT_ap_remove_flat_curves(bpy.types.Operator):
bl_idname = "armature.ap_remove_flat_curves"
bl_label = "Remove Flat Curves"
bl_description = "Removes all curves that have no value change between keyframes"
bl_options = {"REGISTER", "UNDO"}
idx: bpy.props.IntProperty()
@classmethod
def poll(cls, context):
armature = context.active_object.data
ap_poses = armature.ap_poses
return context.mode == 'POSE' and ap_poses and ap_poses[armature.ap_poses_index].action
def execute(self, context):
obj = context.active_object
armature = context.active_object.data
armature_pose = context.active_object.pose
ap_pose = armature.ap_poses[self.idx]
action = ap_pose.action
ap_state = armature.ap_state
ap_bone_transforms = armature.ap_bone_transforms
for fcurve in action.fcurves:
points = fcurve.keyframe_points
first_value = None
is_flat_curve = True
for point in points:
coordinates = point.co
value = round(coordinates[1], 5)
if first_value is None: # storing the value of the first point.
first_value = value
else: # comparing every point's value to the first value.
if value != first_value:
is_flat_curve = False
break
if is_flat_curve:
action.fcurves.remove(fcurve)
for group in action.groups:
if len(group.channels) == 0:
action.groups.remove(group)
self.report({'INFO'}, 'Flat curves removed')
return {'FINISHED'}
class DATA_OT_ap_action_rename(bpy.types.Operator):
bl_idname = "armature.ap_action_rename"
bl_label = "Rename Action"
bl_description = "Rename action."
bl_options = {"REGISTER", "UNDO"}
text: bpy.props.StringProperty(name="Name", default='')
@classmethod
def poll(cls, context):
if context.mode == 'POSE':
idx = context.active_object.data.ap_poses_index
if context.active_object.data.ap_poses[idx].action:
return True
return False
def execute(self, context):
armature = context.active_object.data
ap_pose = armature.ap_poses[armature.ap_poses_index]
action = ap_pose.action
action.name = self.text
return {'FINISHED'}
def invoke(self, context, event):
armature = context.active_object.data
ap_pose = armature.ap_poses[armature.ap_poses_index]
action = ap_pose.action
self.text = action.name
wm = context.window_manager
return wm.invoke_props_dialog(self)
classes = [
DATA_OT_ap_remove_flat_curves,
DATA_OT_ap_action_new,
DATA_OT_ap_action_duplicate,
DATA_OT_ap_action_delete,
DATA_OT_ap_action_rename,
]
register, unregister = bpy.utils.register_classes_factory(classes)