glTF exporter: Export DEF bones only, without animation, is now possible
[blender-addons.git] / animation_animall.py
blob944f4a2faed70a62619ecd930c6b711cedac4f23
1 # SPDX-License-Identifier: GPL-2.0-or-later
3 bl_info = {
4 "name": "AnimAll",
5 "author": "Daniel Salazar (ZanQdo), Damien Picard (pioverfour)",
6 "version": (0, 9, 6),
7 "blender": (3, 3, 0),
8 "location": "3D View > Toolbox > Animation tab > AnimAll",
9 "description": "Allows animation of mesh, lattice, curve and surface data",
10 "warning": "",
11 "doc_url": "{BLENDER_MANUAL_URL}/addons/animation/animall.html",
12 "category": "Animation",
15 import bpy
16 from bpy.types import (
17 Operator,
18 Panel,
19 AddonPreferences,
21 from bpy.props import (
22 BoolProperty,
23 StringProperty,
25 from bpy.app.handlers import persistent
28 # Property Definitions
29 class AnimallProperties(bpy.types.PropertyGroup):
30 key_selected: BoolProperty(
31 name="Key Selected Only",
32 description="Insert keyframes only on selected elements",
33 default=False)
35 # Generic attributes
36 key_point_location: BoolProperty(
37 name="Location",
38 description="Insert keyframes on point locations",
39 default=False)
40 key_shape_key: BoolProperty(
41 name="Shape Key",
42 description="Insert keyframes on active Shape Key layer",
43 default=False)
44 key_material_index: BoolProperty(
45 name="Material Index",
46 description="Insert keyframes on face material indices",
47 default=False)
49 # Mesh attributes
50 key_vertex_bevel: BoolProperty(
51 name="Vertex Bevel",
52 description="Insert keyframes on vertex bevel weight",
53 default=False)
54 # key_vertex_crease: BoolProperty(
55 # name="Vertex Crease",
56 # description="Insert keyframes on vertex crease weight",
57 # default=False)
58 key_vertex_group: BoolProperty(
59 name="Vertex Group",
60 description="Insert keyframes on active vertex group values",
61 default=False)
63 key_edge_bevel: BoolProperty(
64 name="Edge Bevel",
65 description="Insert keyframes on edge bevel weight",
66 default=False)
67 key_edge_crease: BoolProperty(
68 name="Edge Crease",
69 description="Insert keyframes on edge creases",
70 default=False)
72 key_attribute: BoolProperty(
73 name="Attribute",
74 description="Insert keyframes on active attribute values",
75 default=False)
76 key_uvs: BoolProperty(
77 name="UV Map",
78 description="Insert keyframes on active UV coordinates",
79 default=False)
81 # Curve and surface attributes
82 key_radius: BoolProperty(
83 name="Radius",
84 description="Insert keyframes on point radius (Shrink/Fatten)",
85 default=False)
86 key_tilt: BoolProperty(
87 name="Tilt",
88 description="Insert keyframes on point tilt",
89 default=False)
92 # Utility functions
94 def refresh_ui_keyframes():
95 try:
96 for area in bpy.context.screen.areas:
97 if area.type in ('TIMELINE', 'GRAPH_EDITOR', 'DOPESHEET_EDITOR'):
98 area.tag_redraw()
99 except:
100 pass
103 def insert_key(data, key, group=None):
104 try:
105 if group is not None:
106 data.keyframe_insert(key, group=group)
107 else:
108 data.keyframe_insert(key)
109 except:
110 pass
113 def delete_key(data, key):
114 try:
115 data.keyframe_delete(key)
116 except:
117 pass
120 def is_selected_vert_loop(data, loop_i):
121 """Get selection status of vertex corresponding to a loop"""
122 vertex_index = data.loops[loop_i].vertex_index
123 return data.vertices[vertex_index].select
126 # GUI (Panel)
128 class VIEW3D_PT_animall(Panel):
129 bl_space_type = 'VIEW_3D'
130 bl_region_type = 'UI'
131 bl_category = "Animate"
132 bl_label = ''
134 @classmethod
135 def poll(self, context):
136 return context.active_object and context.active_object.type in {'MESH', 'LATTICE', 'CURVE', 'SURFACE'}
138 def draw_header(self, context):
140 layout = self.layout
141 row = layout.row()
142 row.label (text = 'AnimAll', icon = 'ARMATURE_DATA')
144 def draw(self, context):
145 obj = context.active_object
146 animall_properties = context.scene.animall_properties
148 layout = self.layout
150 layout.label(text='Key:')
152 layout.use_property_split = True
153 layout.use_property_decorate = False
155 if obj.type == 'LATTICE':
156 col = layout.column(heading="Points", align=True)
157 col.prop(animall_properties, "key_point_location")
159 col = layout.column(heading="Others", align=True)
160 col.prop(animall_properties, "key_shape_key")
162 elif obj.type == 'MESH':
163 col = layout.column(heading="Points", align=True)
164 col.prop(animall_properties, "key_point_location")
165 col.prop(animall_properties, "key_vertex_bevel", text="Bevel")
166 col.prop(animall_properties, "key_vertex_group")
168 col = layout.column(heading="Edges", align=True)
169 col.prop(animall_properties, "key_edge_bevel", text="Bevel")
170 col.prop(animall_properties, "key_edge_crease", text="Crease")
172 col = layout.column(heading="Faces", align=True)
173 col.prop(animall_properties, "key_material_index")
175 col = layout.column(heading="Others", align=True)
176 col.prop(animall_properties, "key_attribute")
177 col.prop(animall_properties, "key_uvs")
178 col.prop(animall_properties, "key_shape_key")
180 # Vertex group update operator
181 if (obj.data.animation_data is not None
182 and obj.data.animation_data.action is not None):
183 for fcurve in context.active_object.data.animation_data.action.fcurves:
184 if fcurve.data_path.startswith("vertex_colors"):
185 col = layout.column(align=True)
186 col.label(text="Object includes old-style vertex colors. Consider updating them.", icon="ERROR")
187 col.operator("anim.update_vertex_color_animation_animall", icon="FILE_REFRESH")
188 break
190 elif obj.type in {'CURVE', 'SURFACE'}:
191 col = layout.column(align=True)
192 col = layout.column(heading="Points", align=True)
193 col.prop(animall_properties, "key_point_location")
194 col.prop(animall_properties, "key_radius")
195 col.prop(animall_properties, "key_tilt")
197 col = layout.column(heading="Splines", align=True)
198 col.prop(animall_properties, "key_material_index")
200 col = layout.column(heading="Others", align=True)
201 col.prop(animall_properties, "key_shape_key")
203 if animall_properties.key_shape_key:
204 shape_key = obj.active_shape_key
205 shape_key_index = obj.active_shape_key_index
207 if shape_key_index > 0:
208 col = layout.column(align=True)
209 row = col.row(align=True)
210 row.prop(shape_key, "value", text=shape_key.name, icon="SHAPEKEY_DATA")
211 row.prop(obj, "show_only_shape_key", text="")
212 if shape_key.value < 1:
213 col.label(text='Maybe set "%s" to 1.0?' % shape_key.name, icon="INFO")
214 elif shape_key is not None:
215 col = layout.column(align=True)
216 col.label(text="Cannot key on Basis Shape", icon="ERROR")
217 else:
218 col = layout.column(align=True)
219 col.label(text="No active Shape Key", icon="ERROR")
221 if animall_properties.key_point_location:
222 col.label(text='"Location" and "Shape Key" are redundant?', icon="INFO")
224 layout.use_property_split = False
225 layout.separator()
226 row = layout.row()
227 row.prop(animall_properties, "key_selected")
229 row = layout.row(align=True)
230 row.operator("anim.insert_keyframe_animall", icon="KEY_HLT")
231 row.operator("anim.delete_keyframe_animall", icon="KEY_DEHLT")
232 row = layout.row()
233 row.operator("anim.clear_animation_animall", icon="CANCEL")
236 class ANIM_OT_insert_keyframe_animall(Operator):
237 bl_label = "Insert Key"
238 bl_idname = "anim.insert_keyframe_animall"
239 bl_description = "Insert a Keyframe"
240 bl_options = {'REGISTER', 'UNDO'}
242 def execute(op, context):
243 animall_properties = context.scene.animall_properties
245 if context.mode == 'OBJECT':
246 objects = context.selected_objects
247 else:
248 objects = context.objects_in_mode_unique_data[:]
250 mode = context.object.mode
252 # Separate loop for lattices, curves and surfaces, since keyframe insertion
253 # has to happen in Edit Mode, otherwise points move back upon mode switch...
254 # (except for curve shape keys)
255 for obj in [o for o in objects if o.type in {'CURVE', 'SURFACE', 'LATTICE'}]:
256 data = obj.data
258 if obj.type == 'LATTICE':
259 if animall_properties.key_shape_key:
260 if obj.active_shape_key_index > 0:
261 sk_name = obj.active_shape_key.name
262 for p_i, point in enumerate(obj.active_shape_key.data):
263 if not animall_properties.key_selected or data.points[p_i].select:
264 insert_key(point, 'co', group="%s Point %s" % (sk_name, p_i))
266 if animall_properties.key_point_location:
267 for p_i, point in enumerate(data.points):
268 if not animall_properties.key_selected or point.select:
269 insert_key(point, 'co_deform', group="Point %s" % p_i)
271 else:
272 if animall_properties.key_material_index:
273 for s_i, spline in enumerate(data.splines):
274 if (not animall_properties.key_selected
275 or any(point.select for point in spline.points)
276 or any(point.select_control_point for point in spline.bezier_points)):
277 insert_key(spline, 'material_index', group="Spline %s" % s_i)
279 for s_i, spline in enumerate(data.splines):
280 if spline.type == 'BEZIER':
281 for v_i, CV in enumerate(spline.bezier_points):
282 if (not animall_properties.key_selected
283 or CV.select_control_point
284 or CV.select_left_handle
285 or CV.select_right_handle):
286 if animall_properties.key_point_location:
287 insert_key(CV, 'co', group="Spline %s CV %s" % (s_i, v_i))
288 insert_key(CV, 'handle_left', group="Spline %s CV %s" % (s_i, v_i))
289 insert_key(CV, 'handle_right', group="Spline %s CV %s" % (s_i, v_i))
291 if animall_properties.key_radius:
292 insert_key(CV, 'radius', group="Spline %s CV %s" % (s_i, v_i))
294 if animall_properties.key_tilt:
295 insert_key(CV, 'tilt', group="Spline %s CV %s" % (s_i, v_i))
297 elif spline.type in ('POLY', 'NURBS'):
298 for v_i, CV in enumerate(spline.points):
299 if not animall_properties.key_selected or CV.select:
300 if animall_properties.key_point_location:
301 insert_key(CV, 'co', group="Spline %s CV %s" % (s_i, v_i))
303 if animall_properties.key_radius:
304 insert_key(CV, 'radius', group="Spline %s CV %s" % (s_i, v_i))
306 if animall_properties.key_tilt:
307 insert_key(CV, 'tilt', group="Spline %s CV %s" % (s_i, v_i))
309 bpy.ops.object.mode_set(mode='OBJECT')
311 for obj in [o for o in objects if o.type in {'MESH', 'CURVE', 'SURFACE'}]:
312 data = obj.data
313 if obj.type == 'MESH':
314 if animall_properties.key_point_location:
315 for v_i, vert in enumerate(data.vertices):
316 if not animall_properties.key_selected or vert.select:
317 insert_key(vert, 'co', group="Vertex %s" % v_i)
319 if animall_properties.key_vertex_bevel:
320 for v_i, vert in enumerate(data.vertices):
321 if not animall_properties.key_selected or vert.select:
322 insert_key(vert, 'bevel_weight', group="Vertex %s" % v_i)
323 # if animall_properties.key_vertex_crease:
324 # for v_i, vert in enumerate(data.vertices):
325 # if not animall_properties.key_selected or vert.select:
326 # insert_key(vert, 'crease', group="Vertex %s" % v_i)
328 if animall_properties.key_vertex_group:
329 for v_i, vert in enumerate(data.vertices):
330 if not animall_properties.key_selected or vert.select:
331 for group in vert.groups:
332 insert_key(group, 'weight', group="Vertex %s" % v_i)
334 if animall_properties.key_edge_bevel:
335 for e_i, edge in enumerate(data.edges):
336 if not animall_properties.key_selected or edge.select:
337 insert_key(edge, 'bevel_weight', group="Edge %s" % e_i)
339 if animall_properties.key_edge_crease:
340 for e_i, edge in enumerate(data.edges):
341 if not animall_properties.key_selected or edge.select:
342 insert_key(edge, 'crease', group="Edge %s" % e_i)
344 if animall_properties.key_material_index:
345 for p_i, polygon in enumerate(data.polygons):
346 if not animall_properties.key_selected or polygon.select:
347 insert_key(polygon, 'material_index', group="Face %s" % p_i)
349 if animall_properties.key_attribute:
350 if data.attributes.active is not None:
351 attribute = data.attributes.active
352 if attribute.data_type != 'STRING':
353 # Cannot animate string attributes?
354 if attribute.data_type in {'FLOAT', 'INT', 'BOOLEAN', 'INT8'}:
355 attribute_key = "value"
356 elif attribute.data_type in {'FLOAT_COLOR', 'BYTE_COLOR'}:
357 attribute_key = "color"
358 elif attribute.data_type in {'FLOAT_VECTOR', 'FLOAT2'}:
359 attribute_key = "vector"
361 if attribute.domain == 'POINT':
362 group = "Vertex %s"
363 elif attribute.domain == 'EDGE':
364 group = "Edge %s"
365 elif attribute.domain == 'FACE':
366 group = "Face %s"
367 elif attribute.domain == 'CORNER':
368 group = "Loop %s"
370 for e_i, _attribute_data in enumerate(attribute.data):
371 if (not animall_properties.key_selected
372 or attribute.domain == 'POINT' and data.vertices[e_i].select
373 or attribute.domain == 'EDGE' and data.edges[e_i].select
374 or attribute.domain == 'FACE' and data.polygons[e_i].select
375 or attribute.domain == 'CORNER' and is_selected_vert_loop(data, e_i)):
376 insert_key(data, f'attributes["{attribute.name}"].data[{e_i}].{attribute_key}',
377 group=group % e_i)
379 if animall_properties.key_uvs:
380 if data.uv_layers.active is not None:
381 for uv_i, uv in enumerate(data.uv_layers.active.data):
382 if not animall_properties.key_selected or uv.select:
383 insert_key(uv, 'uv', group="UV layer %s" % uv_i)
385 if animall_properties.key_shape_key:
386 if obj.active_shape_key_index > 0:
387 sk_name = obj.active_shape_key.name
388 for v_i, vert in enumerate(obj.active_shape_key.data):
389 if not animall_properties.key_selected or data.vertices[v_i].select:
390 insert_key(vert, 'co', group="%s Vertex %s" % (sk_name, v_i))
392 elif obj.type in {'CURVE', 'SURFACE'}:
393 # Shape key keys have to be inserted in object mode for curves...
394 if animall_properties.key_shape_key:
395 sk_name = obj.active_shape_key.name
396 global_spline_index = 0 # numbering for shape keys, which have flattened indices
397 for s_i, spline in enumerate(data.splines):
398 if spline.type == 'BEZIER':
399 for v_i, CV in enumerate(spline.bezier_points):
400 if (not animall_properties.key_selected
401 or CV.select_control_point
402 or CV.select_left_handle
403 or CV.select_right_handle):
404 if obj.active_shape_key_index > 0:
405 CV = obj.active_shape_key.data[global_spline_index]
406 insert_key(CV, 'co', group="%s Spline %s CV %s" % (sk_name, s_i, v_i))
407 insert_key(CV, 'handle_left', group="%s Spline %s CV %s" % (sk_name, s_i, v_i))
408 insert_key(CV, 'handle_right', group="%s Spline %s CV %s" % (sk_name, s_i, v_i))
409 insert_key(CV, 'radius', group="%s Spline %s CV %s" % (sk_name, s_i, v_i))
410 insert_key(CV, 'tilt', group="%s Spline %s CV %s" % (sk_name, s_i, v_i))
411 global_spline_index += 1
413 elif spline.type in ('POLY', 'NURBS'):
414 for v_i, CV in enumerate(spline.points):
415 if not animall_properties.key_selected or CV.select:
416 if obj.active_shape_key_index > 0:
417 CV = obj.active_shape_key.data[global_spline_index]
418 insert_key(CV, 'co', group="%s Spline %s CV %s" % (sk_name, s_i, v_i))
419 insert_key(CV, 'radius', group="%s Spline %s CV %s" % (sk_name, s_i, v_i))
420 insert_key(CV, 'tilt', group="%s Spline %s CV %s" % (sk_name, s_i, v_i))
421 global_spline_index += 1
423 bpy.ops.object.mode_set(mode=mode)
424 refresh_ui_keyframes()
426 return {'FINISHED'}
429 class ANIM_OT_delete_keyframe_animall(Operator):
430 bl_label = "Delete Key"
431 bl_idname = "anim.delete_keyframe_animall"
432 bl_description = "Delete a Keyframe"
433 bl_options = {'REGISTER', 'UNDO'}
436 def execute(op, context):
437 animall_properties = context.scene.animall_properties
439 if context.mode == 'OBJECT':
440 objects = context.selected_objects
441 else:
442 objects = context.objects_in_mode_unique_data[:]
444 mode = context.object.mode
446 for obj in objects:
447 data = obj.data
448 if obj.type == 'MESH':
449 if animall_properties.key_point_location:
450 for vert in data.vertices:
451 if not animall_properties.key_selected or vert.select:
452 delete_key(vert, 'co')
454 if animall_properties.key_vertex_bevel:
455 for vert in data.vertices:
456 if not animall_properties.key_selected or vert.select:
457 delete_key(vert, 'bevel_weight')
459 if animall_properties.key_vertex_group:
460 for vert in data.vertices:
461 if not animall_properties.key_selected or vert.select:
462 for group in vert.groups:
463 delete_key(group, 'weight')
465 # if animall_properties.key_vertex_crease:
466 # for vert in data.vertices:
467 # if not animall_properties.key_selected or vert.select:
468 # delete_key(vert, 'crease')
470 if animall_properties.key_edge_bevel:
471 for edge in data.edges:
472 if not animall_properties.key_selected or edge.select:
473 delete_key(edge, 'bevel_weight')
475 if animall_properties.key_edge_crease:
476 for edge in data.edges:
477 if not animall_properties.key_selected or vert.select:
478 delete_key(edge, 'crease')
480 if animall_properties.key_shape_key:
481 if obj.active_shape_key:
482 for v_i, vert in enumerate(obj.active_shape_key.data):
483 if not animall_properties.key_selected or data.vertices[v_i].select:
484 delete_key(vert, 'co')
486 if animall_properties.key_uvs:
487 if data.uv_layers.active is not None:
488 for uv in data.uv_layers.active.data:
489 if not animall_properties.key_selected or uv.select:
490 delete_key(uv, 'uv')
492 if animall_properties.key_attribute:
493 if data.attributes.active is not None:
494 attribute = data.attributes.active
495 if attribute.data_type != 'STRING':
496 # Cannot animate string attributes?
497 if attribute.data_type in {'FLOAT', 'INT', 'BOOLEAN', 'INT8'}:
498 attribute_key = "value"
499 elif attribute.data_type in {'FLOAT_COLOR', 'BYTE_COLOR'}:
500 attribute_key = "color"
501 elif attribute.data_type in {'FLOAT_VECTOR', 'FLOAT2'}:
502 attribute_key = "vector"
504 for e_i, _attribute_data in enumerate(attribute.data):
505 if (not animall_properties.key_selected
506 or attribute.domain == 'POINT' and data.vertices[e_i].select
507 or attribute.domain == 'EDGE' and data.edges[e_i].select
508 or attribute.domain == 'FACE' and data.polygons[e_i].select
509 or attribute.domain == 'CORNER' and is_selected_vert_loop(data, e_i)):
510 delete_key(data, f'attributes["{attribute.name}"].data[{e_i}].{attribute_key}')
512 elif obj.type == 'LATTICE':
513 if animall_properties.key_shape_key:
514 if obj.active_shape_key:
515 for point in obj.active_shape_key.data:
516 delete_key(point, 'co')
518 if animall_properties.key_point_location:
519 for point in data.points:
520 if not animall_properties.key_selected or point.select:
521 delete_key(point, 'co_deform')
523 elif obj.type in {'CURVE', 'SURFACE'}:
524 # Run this outside the splines loop (only once)
525 if animall_properties.key_shape_key:
526 if obj.active_shape_key_index > 0:
527 for CV in obj.active_shape_key.data:
528 delete_key(CV, 'co')
529 delete_key(CV, 'handle_left')
530 delete_key(CV, 'handle_right')
532 for spline in data.splines:
533 if spline.type == 'BEZIER':
534 for CV in spline.bezier_points:
535 if (not animall_properties.key_selected
536 or CV.select_control_point
537 or CV.select_left_handle
538 or CV.select_right_handle):
539 if animall_properties.key_point_location:
540 delete_key(CV, 'co')
541 delete_key(CV, 'handle_left')
542 delete_key(CV, 'handle_right')
543 if animall_properties.key_radius:
544 delete_key(CV, 'radius')
545 if animall_properties.key_tilt:
546 delete_key(CV, 'tilt')
548 elif spline.type in ('POLY', 'NURBS'):
549 for CV in spline.points:
550 if not animall_properties.key_selected or CV.select:
551 if animall_properties.key_point_location:
552 delete_key(CV, 'co')
553 if animall_properties.key_radius:
554 delete_key(CV, 'radius')
555 if animall_properties.key_tilt:
556 delete_key(CV, 'tilt')
558 refresh_ui_keyframes()
560 return {'FINISHED'}
563 class ANIM_OT_clear_animation_animall(Operator):
564 bl_label = "Clear Animation"
565 bl_idname = "anim.clear_animation_animall"
566 bl_description = ("Delete all keyframes for this object\n"
567 "If in a specific case it doesn't work\n"
568 "try to delete the keys manually")
569 bl_options = {'REGISTER', 'UNDO'}
571 def invoke(self, context, event):
572 wm = context.window_manager
573 return wm.invoke_confirm(self, event)
575 def execute(self, context):
576 if context.mode == 'OBJECT':
577 objects = context.selected_objects
578 else:
579 objects = context.objects_in_mode_unique_data
581 for obj in objects:
582 try:
583 data = obj.data
584 data.animation_data_clear()
585 except:
586 self.report({'WARNING'}, "Clear Animation could not be performed")
587 return {'CANCELLED'}
589 refresh_ui_keyframes()
591 return {'FINISHED'}
594 class ANIM_OT_update_vertex_color_animation_animall(Operator):
595 bl_label = "Update Vertex Color Animation"
596 bl_idname = "anim.update_vertex_color_animation_animall"
597 bl_description = "Update old vertex color channel formats from pre-3.3 versions"
598 bl_options = {'REGISTER', 'UNDO'}
600 @classmethod
601 def poll(self, context):
602 if (context.active_object is None
603 or context.active_object.type != 'MESH'
604 or context.active_object.data.animation_data is None
605 or context.active_object.data.animation_data.action is None):
606 return False
607 for fcurve in context.active_object.data.animation_data.action.fcurves:
608 if fcurve.data_path.startswith("vertex_colors"):
609 return True
611 def execute(self, context):
612 for fcurve in context.active_object.data.animation_data.action.fcurves:
613 if fcurve.data_path.startswith("vertex_colors"):
614 fcurve.data_path = fcurve.data_path.replace("vertex_colors", "attributes")
615 return {'FINISHED'}
617 # Add-ons Preferences Update Panel
619 # Define Panel classes for updating
620 panels = [
621 VIEW3D_PT_animall
625 def update_panel(self, context):
626 message = "AnimAll: Updating Panel locations has failed"
627 try:
628 for panel in panels:
629 if "bl_rna" in panel.__dict__:
630 bpy.utils.unregister_class(panel)
632 for panel in panels:
633 panel.bl_category = context.preferences.addons[__name__].preferences.category
634 bpy.utils.register_class(panel)
636 except Exception as e:
637 print("\n[{}]\n{}\n\nError:\n{}".format(__name__, message, e))
638 pass
641 class AnimallAddonPreferences(AddonPreferences):
642 # this must match the addon name, use '__package__'
643 # when defining this in a submodule of a python package.
644 bl_idname = __name__
646 category: StringProperty(
647 name="Tab Category",
648 description="Choose a name for the category of the panel",
649 default="Animate",
650 update=update_panel
653 def draw(self, context):
654 layout = self.layout
655 row = layout.row()
656 col = row.column()
658 col.label(text="Tab Category:")
659 col.prop(self, "category", text="")
662 def register():
663 bpy.utils.register_class(AnimallProperties)
664 bpy.types.Scene.animall_properties = bpy.props.PointerProperty(type=AnimallProperties)
665 bpy.utils.register_class(VIEW3D_PT_animall)
666 bpy.utils.register_class(ANIM_OT_insert_keyframe_animall)
667 bpy.utils.register_class(ANIM_OT_delete_keyframe_animall)
668 bpy.utils.register_class(ANIM_OT_clear_animation_animall)
669 bpy.utils.register_class(ANIM_OT_update_vertex_color_animation_animall)
670 bpy.utils.register_class(AnimallAddonPreferences)
671 update_panel(None, bpy.context)
674 def unregister():
675 del bpy.types.Scene.animall_properties
676 bpy.utils.unregister_class(AnimallProperties)
677 bpy.utils.unregister_class(VIEW3D_PT_animall)
678 bpy.utils.unregister_class(ANIM_OT_insert_keyframe_animall)
679 bpy.utils.unregister_class(ANIM_OT_delete_keyframe_animall)
680 bpy.utils.unregister_class(ANIM_OT_clear_animation_animall)
681 bpy.utils.unregister_class(ANIM_OT_update_vertex_color_animation_animall)
682 bpy.utils.unregister_class(AnimallAddonPreferences)
684 if __name__ == "__main__":
685 register()