1 # ##### BEGIN GPL LICENSE BLOCK #####
3 # This program is free software; you can redistribute it and/or
4 # modify it under the terms of the GNU General Public License
5 # as published by the Free Software Foundation; either version 2
6 # of the License, or (at your option) any later version.
8 # This program is distributed in the hope that it will be useful,
9 # but WITHOUT ANY WARRANTY; without even the implied warranty of
10 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 # GNU General Public License for more details.
13 # You should have received a copy of the GNU General Public License
14 # along with this program; if not, write to the Free Software Foundation,
15 # Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17 # ##### END GPL LICENSE BLOCK #####
21 "author": "Daniel Salazar <zanqdo@gmail.com>",
23 "blender": (2, 80, 0),
24 "location": "3D View > Toolbox > Animation tab > AnimAll",
25 "description": "Allows animation of mesh, lattice, curve and surface data",
27 "wiki_url": "https://wiki.blender.org/index.php/Extensions:2.6/Py/"
28 "Scripts/Animation/AnimAll",
29 "category": "Animation",
33 Thanks to Campbell Barton and Joshua Leung for hes API additions and fixes
34 Daniel 'ZanQdo' Salazar
38 from bpy
.types
import (
43 from bpy
.props
import (
49 # Property Definitions
50 class AnimallProperties(bpy
.types
.PropertyGroup
):
51 key_selected
: BoolProperty(
53 description
="Insert keyframes only on selected elements",
56 key_shape
: BoolProperty(
58 description
="Insert keyframes on active Shape Key layer",
61 key_uvs
: BoolProperty(
63 description
="Insert keyframes on active UV coordinates",
66 key_ebevel
: BoolProperty(
68 description
="Insert keyframes on edge bevel weight",
71 key_vbevel
: BoolProperty(
73 description
="Insert keyframes on vertex bevel weight",
76 key_crease
: BoolProperty(
78 description
="Insert keyframes on edge creases",
81 key_vcols
: BoolProperty(
83 description
="Insert keyframes on active Vertex Color values",
86 key_vgroups
: BoolProperty(
88 description
="Insert keyframes on active Vertex group values",
91 key_points
: BoolProperty(
93 description
="Insert keyframes on point locations",
96 key_radius
: BoolProperty(
98 description
="Insert keyframes on point radius (Shrink/Fatten)",
101 key_tilt
: BoolProperty(
103 description
="Insert keyframes on point tilt",
110 def refresh_ui_keyframes():
112 for area
in bpy
.context
.screen
.areas
:
113 if area
.type in ('TIMELINE', 'GRAPH_EDITOR', 'DOPESHEET_EDITOR'):
119 def insert_key(data
, key
, group
=''):
121 data
.keyframe_insert(key
, group
=group
)
126 def delete_key(data
, key
):
128 data
.keyframe_delete(key
)
135 class VIEW3D_PT_animall(Panel
):
136 bl_space_type
= 'VIEW_3D'
137 bl_region_type
= 'UI'
138 bl_category
= "Animation"
142 def poll(self
, context
):
143 return context
.active_object
and context
.active_object
.type in {'MESH', 'LATTICE', 'CURVE', 'SURFACE'}
145 def draw(self
, context
):
146 obj
= context
.active_object
147 animall_properties
= context
.window_manager
.animall_properties
150 col
= layout
.column(align
=True)
152 row
.prop(animall_properties
, "key_selected")
157 if obj
.type == 'LATTICE':
158 row
.prop(animall_properties
, "key_points")
159 row
.prop(animall_properties
, "key_shape")
161 elif obj
.type == 'MESH':
162 row
.prop(animall_properties
, "key_points")
163 row
.prop(animall_properties
, "key_shape")
165 row
.prop(animall_properties
, "key_ebevel")
166 row
.prop(animall_properties
, "key_vbevel")
168 row
.prop(animall_properties
, "key_crease")
169 row
.prop(animall_properties
, "key_uvs")
171 row
.prop(animall_properties
, "key_vcols")
172 row
.prop(animall_properties
, "key_vgroups")
174 elif obj
.type == 'CURVE':
175 row
.prop(animall_properties
, "key_points")
176 row
.prop(animall_properties
, "key_shape")
178 row
.prop(animall_properties
, "key_radius")
179 row
.prop(animall_properties
, "key_tilt")
181 elif obj
.type == 'SURFACE':
182 row
.prop(animall_properties
, "key_points")
183 row
.prop(animall_properties
, "key_shape")
185 row
.prop(animall_properties
, "key_radius")
186 row
.prop(animall_properties
, "key_tilt")
189 row
= layout
.row(align
=True)
190 row
.operator("anim.insert_keyframe_animall", icon
="KEY_HLT")
191 row
.operator("anim.delete_keyframe_animall", icon
="KEY_DEHLT")
193 row
.operator("anim.clear_animation_animall", icon
="X")
195 if animall_properties
.key_shape
:
196 shape_key
= obj
.active_shape_key
197 shape_key_index
= obj
.active_shape_key_index
199 split
= layout
.split()
202 if shape_key_index
> 0:
203 row
.label(text
=shape_key
.name
, icon
="SHAPEKEY_DATA")
204 row
.prop(shape_key
, "value", text
="")
205 row
.prop(obj
, "show_only_shape_key", text
="")
206 if shape_key
.value
< 1:
208 row
.label(text
='Maybe set "%s" to 1.0?' % shape_key
.name
, icon
="INFO")
210 row
.label(text
="Cannot key on Basis Shape", icon
="ERROR")
212 row
.label(text
="No active Shape Key", icon
="ERROR")
214 if animall_properties
.key_points
and animall_properties
.key_shape
:
216 row
.label(text
='"Points" and "Shape" are redundant?', icon
="INFO")
219 class ANIM_OT_insert_keyframe_animall(Operator
):
221 bl_idname
= "anim.insert_keyframe_animall"
222 bl_description
= "Insert a Keyframe"
223 bl_options
= {'REGISTER', 'UNDO'}
225 def invoke(self
, context
, event
):
226 self
.execute(context
)
230 def execute(op
, context
):
231 obj
= context
.active_object
232 animall_properties
= context
.window_manager
.animall_properties
234 # Maybe this should be done for all object types,
235 # but keys can only be inserted in Edit Mode for CURVEs and SURFACEs,
236 # and Object Mode for MESHes and LATTICEs.
237 # Putting it inside if blocks for now
239 # if obj.type in {'MESH', 'LATTICE', 'CURVE', 'SURFACE'}:
241 # bpy.ops.object.mode_set(mode='OBJECT')
244 if obj
.type == 'MESH':
246 bpy
.ops
.object.mode_set(mode
='OBJECT')
249 if animall_properties
.key_points
:
250 for v_i
, vert
in enumerate(data
.vertices
):
251 if not animall_properties
.key_selected
or vert
.select
:
252 insert_key(vert
, 'co', group
="vertex %s" % v_i
)
254 if animall_properties
.key_vbevel
:
255 for v_i
, vert
in enumerate(data
.vertices
):
256 if not animall_properties
.key_selected
or vert
.select
:
257 insert_key(vert
, 'bevel_weight', group
="vertex %s" % v_i
)
259 if animall_properties
.key_vgroups
:
260 for v_i
, vert
in enumerate(data
.vertices
):
261 if not animall_properties
.key_selected
or vert
.select
:
262 for group
in vert
.groups
:
263 insert_key(group
, 'weight', group
="vertex %s" % v_i
)
265 if animall_properties
.key_ebevel
:
266 for e_i
, edge
in enumerate(data
.edges
):
267 if not animall_properties
.key_selected
or edge
.select
:
268 insert_key(edge
, 'bevel_weight', group
="edge %s" % e_i
)
270 if animall_properties
.key_crease
:
271 for e_i
, edge
in enumerate(data
.edges
):
272 if not animall_properties
.key_selected
or edge
.select
:
273 insert_key(edge
, 'crease', group
="edge %s" % e_i
)
275 if animall_properties
.key_shape
:
276 if obj
.active_shape_key_index
> 0:
277 for v_i
, vert
in enumerate(obj
.active_shape_key
.data
):
278 insert_key(vert
, 'co', group
="vertex %s" % v_i
)
280 if animall_properties
.key_uvs
:
281 if data
.uv_layers
.active
is not None:
282 for uv_i
, uv
in enumerate(data
.uv_layers
.active
.data
):
283 insert_key(uv
, 'uv', group
="UV layer %s" % uv_i
)
285 if animall_properties
.key_vcols
:
286 for v_col_layer
in data
.vertex_colors
:
287 if v_col_layer
.active
: # only insert in active VCol layer
288 for v_i
, data
in enumerate(v_col_layer
.data
):
289 insert_key(data
, 'color', group
="Loop %s" % v_i
)
291 bpy
.ops
.object.mode_set(mode
=mode
)
293 elif obj
.type == 'LATTICE':
295 bpy
.ops
.object.mode_set(mode
='OBJECT')
298 if animall_properties
.key_shape
:
299 if obj
.active_shape_key_index
> 0:
300 for p_i
, point
in enumerate(obj
.active_shape_key
.data
):
301 insert_key(point
, 'co', group
="Point %s" % p_i
)
303 if animall_properties
.key_points
:
304 for p_i
, point
in enumerate(data
.points
):
305 if not animall_properties
.key_selected
or point
.select
:
306 insert_key(point
, 'co_deform', group
="Point %s" % p_i
)
308 bpy
.ops
.object.mode_set(mode
=mode
)
310 elif obj
.type in {'CURVE', 'SURFACE'}:
313 # run this outside the splines loop (only once)
314 if animall_properties
.key_shape
:
315 if obj
.active_shape_key_index
> 0:
316 for CV
in obj
.active_shape_key
.data
:
318 insert_key(CV
, 'handle_left')
319 insert_key(CV
, 'handle_right')
321 for s_i
, spline
in enumerate(data
.splines
):
322 if spline
.type == 'BEZIER':
323 for v_i
, CV
in enumerate(spline
.bezier_points
):
324 if (not animall_properties
.key_selected
325 or CV
.select_control_point
326 or CV
.select_left_handle
327 or CV
.select_right_handle
):
328 if animall_properties
.key_points
:
329 insert_key(CV
, 'co', group
="spline %s CV %s" % (s_i
, v_i
))
330 insert_key(CV
, 'handle_left', group
="spline %s CV %s" % (s_i
, v_i
))
331 insert_key(CV
, 'handle_right', group
="spline %s CV %s" % (s_i
, v_i
))
333 if animall_properties
.key_radius
:
334 insert_key(CV
, 'radius', group
="spline %s CV %s" % (s_i
, v_i
))
336 if animall_properties
.key_tilt
:
337 insert_key(CV
, 'tilt', group
="spline %s CV %s" % (s_i
, v_i
))
339 elif spline
.type in ('POLY', 'NURBS'):
340 for v_i
, CV
in enumerate(spline
.points
):
341 if not animall_properties
.key_selected
or CV
.select
:
342 if animall_properties
.key_points
:
343 insert_key(CV
, 'co', group
="spline %s CV %s" % (s_i
, v_i
))
345 if animall_properties
.key_radius
:
346 insert_key(CV
, 'radius', group
="spline %s CV %s" % (s_i
, v_i
))
348 if animall_properties
.key_tilt
:
349 insert_key(CV
, 'tilt', group
="spline %s CV %s" % (s_i
, v_i
))
351 # See previous remark
352 # # Set previous mode
353 # if obj.type in {'MESH', 'LATTICE', 'CURVE', 'SURFACE'}:
354 # bpy.ops.object.mode_set(mode=mode)
356 refresh_ui_keyframes()
361 class ANIM_OT_delete_keyframe_animall(Operator
):
363 bl_idname
= "anim.delete_keyframe_animall"
364 bl_description
= "Delete a Keyframe"
365 bl_options
= {'REGISTER', 'UNDO'}
367 def invoke(self
, context
, event
):
368 self
.execute(context
)
372 def execute(op
, context
):
373 obj
= context
.active_object
374 animall_properties
= context
.window_manager
.animall_properties
377 if obj
.type in {'MESH', 'LATTICE', 'CURVE', 'SURFACE'}:
379 bpy
.ops
.object.mode_set(mode
='OBJECT')
383 if obj
.type == 'MESH':
384 if animall_properties
.key_shape
:
385 if obj
.active_shape_key
:
386 for vert
in obj
.active_shape_key
.data
:
387 delete_key(vert
, 'co')
389 if animall_properties
.key_points
:
390 for vert
in data
.vertices
:
391 delete_key(vert
, 'co')
393 if animall_properties
.key_ebevel
:
394 for edge
in data
.edges
:
395 delete_key(edge
, 'bevel_weight')
397 if animall_properties
.key_vbevel
:
398 for vert
in data
.vertices
:
399 delete_key(vert
, 'bevel_weight')
401 if animall_properties
.key_crease
:
402 for edge
in data
.edges
:
403 delete_key(edge
, 'crease')
405 if animall_properties
.key_vgroups
:
406 for vert
in data
.vertices
:
407 for group
in vert
.groups
:
408 delete_key(group
, 'weight')
410 if animall_properties
.key_uvs
:
411 for UV
in data
.uv_layers
.active
.data
:
414 if animall_properties
.key_vcols
:
415 for v_col_layer
in data
.vertex_colors
:
416 if v_col_layer
.active
: # only delete in active VCol layer
417 for data
in v_col_layer
.data
:
418 delete_key(data
, 'color')
420 if obj
.type == 'LATTICE':
421 if animall_properties
.key_shape
:
422 if obj
.active_shape_key
:
423 for point
in obj
.active_shape_key
.data
:
424 delete_key(point
, 'co')
426 if animall_properties
.key_points
:
427 for point
in data
.points
:
428 delete_key(Point
, 'co_deform')
430 if obj
.type in {'CURVE', 'SURFACE'}:
431 # run this outside the splines loop (only once)
432 if animall_properties
.key_shape
:
433 if obj
.active_shape_key_index
> 0:
434 for CV
in obj
.active_shape_key
.data
:
436 delete_key(CV
, 'handle_left')
437 delete_key(CV
, 'handle_right')
439 for spline
in data
.splines
:
440 if spline
.type == 'BEZIER':
441 for CV
in spline
.bezier_points
:
442 if animall_properties
.key_points
:
444 delete_key(CV
, 'handle_left')
445 delete_key(CV
, 'handle_right')
446 if animall_properties
.key_radius
:
447 delete_key(CV
, 'radius')
448 if animall_properties
.key_tilt
:
449 delete_key(CV
, 'tilt')
451 elif spline
.type == 'NURBS':
452 for CV
in spline
.points
:
453 if animall_properties
.key_points
:
455 if animall_properties
.key_radius
:
456 delete_key(CV
, 'radius')
457 if animall_properties
.key_tilt
:
458 delete_key(CV
, 'tilt')
461 if obj
.type in {'MESH', 'LATTICE', 'CURVE', 'SURFACE'}:
462 bpy
.ops
.object.mode_set(mode
=mode
)
464 refresh_ui_keyframes()
469 class ANIM_OT_clear_animation_animall(Operator
):
470 bl_label
= "Clear Animation"
471 bl_idname
= "anim.clear_animation_animall"
472 bl_description
= ("Delete all keyframes for this object\n"
473 "If in a specific case it doesn't work\n"
474 "try to delete the keys manually")
475 bl_options
= {'REGISTER', 'UNDO'}
477 def invoke(self
, context
, event
):
478 wm
= context
.window_manager
479 return wm
.invoke_confirm(self
, event
)
481 def execute(self
, context
):
483 data
= context
.active_object
.data
484 data
.animation_data_clear()
486 self
.report({'WARNING'}, "Clear Animation could not be performed")
489 refresh_ui_keyframes()
494 # Add-ons Preferences Update Panel
496 # Define Panel classes for updating
502 def update_panel(self
, context
):
503 message
= "AnimAll: Updating Panel locations has failed"
506 if "bl_rna" in panel
.__dict
__:
507 bpy
.utils
.unregister_class(panel
)
510 panel
.bl_category
= context
.preferences
.addons
[__name__
].preferences
.category
511 bpy
.utils
.register_class(panel
)
513 except Exception as e
:
514 print("\n[{}]\n{}\n\nError:\n{}".format(__name__
, message
, e
))
518 class AnimallAddonPreferences(AddonPreferences
):
519 # this must match the addon name, use '__package__'
520 # when defining this in a submodule of a python package.
523 category
: StringProperty(
525 description
="Choose a name for the category of the panel",
530 def draw(self
, context
):
535 col
.label(text
="Tab Category:")
536 col
.prop(self
, "category", text
="")
540 bpy
.utils
.register_class(AnimallProperties
)
541 bpy
.types
.WindowManager
.animall_properties
= bpy
.props
.PointerProperty(type=AnimallProperties
)
542 bpy
.utils
.register_class(VIEW3D_PT_animall
)
543 bpy
.utils
.register_class(ANIM_OT_insert_keyframe_animall
)
544 bpy
.utils
.register_class(ANIM_OT_delete_keyframe_animall
)
545 bpy
.utils
.register_class(ANIM_OT_clear_animation_animall
)
546 bpy
.utils
.register_class(AnimallAddonPreferences
)
547 update_panel(None, bpy
.context
)
551 del bpy
.types
.WindowManager
.animall_properties
552 bpy
.utils
.unregister_class(AnimallProperties
)
553 bpy
.utils
.unregister_class(VIEW3D_PT_animall
)
554 bpy
.utils
.unregister_class(ANIM_OT_insert_keyframe_animall
)
555 bpy
.utils
.unregister_class(ANIM_OT_delete_keyframe_animall
)
556 bpy
.utils
.unregister_class(ANIM_OT_clear_animation_animall
)
557 bpy
.utils
.unregister_class(AnimallAddonPreferences
)
559 if __name__
== "__main__":