Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender-addons.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'animation_animall/__init__.py')
-rw-r--r--animation_animall/__init__.py673
1 files changed, 673 insertions, 0 deletions
diff --git a/animation_animall/__init__.py b/animation_animall/__init__.py
new file mode 100644
index 00000000..d679c970
--- /dev/null
+++ b/animation_animall/__init__.py
@@ -0,0 +1,673 @@
+# SPDX-License-Identifier: GPL-2.0-or-later
+
+bl_info = {
+ "name": "AnimAll",
+ "author": "Daniel Salazar (ZanQdo), Damien Picard (pioverfour)",
+ "version": (0, 9, 6),
+ "blender": (3, 3, 0),
+ "location": "3D View > Toolbox > Animation tab > AnimAll",
+ "description": "Allows animation of mesh, lattice, curve and surface data",
+ "warning": "",
+ "doc_url": "{BLENDER_MANUAL_URL}/addons/animation/animall.html",
+ "category": "Animation",
+}
+
+import bpy
+from bpy.types import (Operator, Panel, AddonPreferences)
+from bpy.props import (BoolProperty, StringProperty)
+from bpy.app.handlers import persistent
+from bpy.app.translations import (pgettext_iface as iface_,
+ pgettext_data as data_)
+from . import translations
+
+
+# Property Definitions
+class AnimallProperties(bpy.types.PropertyGroup):
+ key_selected: BoolProperty(
+ name="Key Selected Only",
+ description="Insert keyframes only on selected elements",
+ default=False)
+
+ # Generic attributes
+ key_point_location: BoolProperty(
+ name="Location",
+ description="Insert keyframes on point locations",
+ default=False)
+ key_shape_key: BoolProperty(
+ name="Shape Key",
+ description="Insert keyframes on active Shape Key layer",
+ default=False)
+ key_material_index: BoolProperty(
+ name="Material Index",
+ description="Insert keyframes on face material indices",
+ default=False)
+
+ # Mesh attributes
+ key_vertex_bevel: BoolProperty(
+ name="Vertex Bevel",
+ description="Insert keyframes on vertex bevel weight",
+ default=False)
+ # key_vertex_crease: BoolProperty(
+ # name="Vertex Crease",
+ # description="Insert keyframes on vertex crease weight",
+ # default=False)
+ key_vertex_group: BoolProperty(
+ name="Vertex Group",
+ description="Insert keyframes on active vertex group values",
+ default=False)
+
+ key_edge_bevel: BoolProperty(
+ name="Edge Bevel",
+ description="Insert keyframes on edge bevel weight",
+ default=False)
+ key_edge_crease: BoolProperty(
+ name="Edge Crease",
+ description="Insert keyframes on edge creases",
+ default=False)
+
+ key_attribute: BoolProperty(
+ name="Attribute",
+ description="Insert keyframes on active attribute values",
+ default=False)
+ key_uvs: BoolProperty(
+ name="UV Map",
+ description="Insert keyframes on active UV coordinates",
+ default=False)
+
+ # Curve and surface attributes
+ key_radius: BoolProperty(
+ name="Radius",
+ description="Insert keyframes on point radius (Shrink/Fatten)",
+ default=False)
+ key_tilt: BoolProperty(
+ name="Tilt",
+ description="Insert keyframes on point tilt",
+ default=False)
+
+
+# Utility functions
+
+def refresh_ui_keyframes():
+ try:
+ for area in bpy.context.screen.areas:
+ if area.type in ('TIMELINE', 'GRAPH_EDITOR', 'DOPESHEET_EDITOR'):
+ area.tag_redraw()
+ except:
+ pass
+
+
+def insert_key(data, key, group=None):
+ try:
+ if group is not None:
+ data.keyframe_insert(key, group=group)
+ else:
+ data.keyframe_insert(key)
+ except:
+ pass
+
+
+def delete_key(data, key):
+ try:
+ data.keyframe_delete(key)
+ except:
+ pass
+
+
+def is_selected_vert_loop(data, loop_i):
+ """Get selection status of vertex corresponding to a loop"""
+ vertex_index = data.loops[loop_i].vertex_index
+ return data.vertices[vertex_index].select
+
+
+# GUI (Panel)
+
+class VIEW3D_PT_animall(Panel):
+ bl_space_type = 'VIEW_3D'
+ bl_region_type = 'UI'
+ bl_category = "Animate"
+ bl_label = ''
+
+ @classmethod
+ def poll(self, context):
+ return context.active_object and context.active_object.type in {'MESH', 'LATTICE', 'CURVE', 'SURFACE'}
+
+ def draw_header(self, context):
+
+ layout = self.layout
+ row = layout.row()
+ row.label (text = 'AnimAll', icon = 'ARMATURE_DATA')
+
+ def draw(self, context):
+ obj = context.active_object
+ animall_properties = context.scene.animall_properties
+
+ layout = self.layout
+
+ layout.label(text='Key:')
+
+ layout.use_property_split = True
+ layout.use_property_decorate = False
+
+ if obj.type == 'LATTICE':
+ col = layout.column(heading="Points", align=True)
+ col.prop(animall_properties, "key_point_location")
+
+ col = layout.column(heading="Others", align=True)
+ col.prop(animall_properties, "key_shape_key")
+
+ elif obj.type == 'MESH':
+ col = layout.column(heading="Points", align=True)
+ col.prop(animall_properties, "key_point_location")
+ col.prop(animall_properties, "key_vertex_bevel", text="Bevel")
+ col.prop(animall_properties, "key_vertex_group")
+
+ col = layout.column(heading="Edges", align=True)
+ col.prop(animall_properties, "key_edge_bevel", text="Bevel")
+ col.prop(animall_properties, "key_edge_crease", text="Crease")
+
+ col = layout.column(heading="Faces", align=True)
+ col.prop(animall_properties, "key_material_index")
+
+ col = layout.column(heading="Others", align=True)
+ col.prop(animall_properties, "key_attribute")
+ col.prop(animall_properties, "key_uvs")
+ col.prop(animall_properties, "key_shape_key")
+
+ # Vertex group update operator
+ if (obj.data.animation_data is not None
+ and obj.data.animation_data.action is not None):
+ for fcurve in context.active_object.data.animation_data.action.fcurves:
+ if fcurve.data_path.startswith("vertex_colors"):
+ col = layout.column(align=True)
+ col.label(text="Object includes old-style vertex colors. Consider updating them.", icon="ERROR")
+ col.operator("anim.update_vertex_color_animation_animall", icon="FILE_REFRESH")
+ break
+
+ elif obj.type in {'CURVE', 'SURFACE'}:
+ col = layout.column(align=True)
+ col = layout.column(heading="Points", align=True)
+ col.prop(animall_properties, "key_point_location")
+ col.prop(animall_properties, "key_radius")
+ col.prop(animall_properties, "key_tilt")
+
+ col = layout.column(heading="Splines", align=True)
+ col.prop(animall_properties, "key_material_index")
+
+ col = layout.column(heading="Others", align=True)
+ col.prop(animall_properties, "key_shape_key")
+
+ if animall_properties.key_shape_key:
+ shape_key = obj.active_shape_key
+ shape_key_index = obj.active_shape_key_index
+
+ if shape_key_index > 0:
+ col = layout.column(align=True)
+ row = col.row(align=True)
+ row.prop(shape_key, "value", text=shape_key.name, icon="SHAPEKEY_DATA")
+ row.prop(obj, "show_only_shape_key", text="")
+ if shape_key.value < 1:
+ col.label(text=iface_('Maybe set "%s" to 1.0?') % shape_key.name, icon="INFO")
+ elif shape_key is not None:
+ col = layout.column(align=True)
+ col.label(text="Cannot key on Basis Shape", icon="ERROR")
+ else:
+ col = layout.column(align=True)
+ col.label(text="No active Shape Key", icon="ERROR")
+
+ if animall_properties.key_point_location:
+ col.label(text='"Location" and "Shape Key" are redundant?', icon="INFO")
+
+ layout.use_property_split = False
+ layout.separator()
+ row = layout.row()
+ row.prop(animall_properties, "key_selected")
+
+ row = layout.row(align=True)
+ row.operator("anim.insert_keyframe_animall", icon="KEY_HLT")
+ row.operator("anim.delete_keyframe_animall", icon="KEY_DEHLT")
+ row = layout.row()
+ row.operator("anim.clear_animation_animall", icon="CANCEL")
+
+
+class ANIM_OT_insert_keyframe_animall(Operator):
+ bl_label = "Insert Key"
+ bl_idname = "anim.insert_keyframe_animall"
+ bl_description = "Insert a Keyframe"
+ bl_options = {'REGISTER', 'UNDO'}
+
+ def execute(self, context):
+ animall_properties = context.scene.animall_properties
+
+ if context.mode == 'OBJECT':
+ objects = context.selected_objects
+ else:
+ objects = context.objects_in_mode_unique_data[:]
+
+ mode = context.object.mode
+
+ # Separate loop for lattices, curves and surfaces, since keyframe insertion
+ # has to happen in Edit Mode, otherwise points move back upon mode switch...
+ # (except for curve shape keys)
+ for obj in [o for o in objects if o.type in {'CURVE', 'SURFACE', 'LATTICE'}]:
+ data = obj.data
+
+ if obj.type == 'LATTICE':
+ if animall_properties.key_shape_key:
+ if obj.active_shape_key_index > 0:
+ sk_name = obj.active_shape_key.name
+ for p_i, point in enumerate(obj.active_shape_key.data):
+ if not animall_properties.key_selected or data.points[p_i].select:
+ insert_key(point, 'co', group=data_("%s Point %s") % (sk_name, p_i))
+
+ if animall_properties.key_point_location:
+ for p_i, point in enumerate(data.points):
+ if not animall_properties.key_selected or point.select:
+ insert_key(point, 'co_deform', group=data_("Point %s") % p_i)
+
+ else:
+ if animall_properties.key_material_index:
+ for s_i, spline in enumerate(data.splines):
+ if (not animall_properties.key_selected
+ or any(point.select for point in spline.points)
+ or any(point.select_control_point for point in spline.bezier_points)):
+ insert_key(spline, 'material_index', group=data_("Spline %s") % s_i)
+
+ for s_i, spline in enumerate(data.splines):
+ if spline.type == 'BEZIER':
+ for v_i, CV in enumerate(spline.bezier_points):
+ if (not animall_properties.key_selected
+ or CV.select_control_point
+ or CV.select_left_handle
+ or CV.select_right_handle):
+ if animall_properties.key_point_location:
+ insert_key(CV, 'co', group=data_("Spline %s CV %s") % (s_i, v_i))
+ insert_key(CV, 'handle_left', group=data_("Spline %s CV %s") % (s_i, v_i))
+ insert_key(CV, 'handle_right', group=data_("Spline %s CV %s") % (s_i, v_i))
+
+ if animall_properties.key_radius:
+ insert_key(CV, 'radius', group=data_("Spline %s CV %s") % (s_i, v_i))
+
+ if animall_properties.key_tilt:
+ insert_key(CV, 'tilt', group=data_("Spline %s CV %s") % (s_i, v_i))
+
+ elif spline.type in ('POLY', 'NURBS'):
+ for v_i, CV in enumerate(spline.points):
+ if not animall_properties.key_selected or CV.select:
+ if animall_properties.key_point_location:
+ insert_key(CV, 'co', group=data_("Spline %s CV %s") % (s_i, v_i))
+
+ if animall_properties.key_radius:
+ insert_key(CV, 'radius', group=data_("Spline %s CV %s") % (s_i, v_i))
+
+ if animall_properties.key_tilt:
+ insert_key(CV, 'tilt', group=data_("Spline %s CV %s") % (s_i, v_i))
+
+ bpy.ops.object.mode_set(mode='OBJECT')
+
+ for obj in [o for o in objects if o.type in {'MESH', 'CURVE', 'SURFACE'}]:
+ data = obj.data
+ if obj.type == 'MESH':
+ if animall_properties.key_point_location:
+ for v_i, vert in enumerate(data.vertices):
+ if not animall_properties.key_selected or vert.select:
+ insert_key(vert, 'co', group=data_("Vertex %s") % v_i)
+
+ if animall_properties.key_vertex_bevel:
+ for v_i, vert in enumerate(data.vertices):
+ if not animall_properties.key_selected or vert.select:
+ insert_key(vert, 'bevel_weight', group=data_("Vertex %s") % v_i)
+ # if animall_properties.key_vertex_crease:
+ # for v_i, vert in enumerate(data.vertices):
+ # if not animall_properties.key_selected or vert.select:
+ # insert_key(vert, 'crease', group=data_("Vertex %s") % v_i)
+
+ if animall_properties.key_vertex_group:
+ for v_i, vert in enumerate(data.vertices):
+ if not animall_properties.key_selected or vert.select:
+ for group in vert.groups:
+ insert_key(group, 'weight', group=data_("Vertex %s") % v_i)
+
+ if animall_properties.key_edge_bevel:
+ for e_i, edge in enumerate(data.edges):
+ if not animall_properties.key_selected or edge.select:
+ insert_key(edge, 'bevel_weight', group=data_("Edge %s") % e_i)
+
+ if animall_properties.key_edge_crease:
+ for e_i, edge in enumerate(data.edges):
+ if not animall_properties.key_selected or edge.select:
+ insert_key(edge, 'crease', group=data_("Edge %s") % e_i)
+
+ if animall_properties.key_material_index:
+ for p_i, polygon in enumerate(data.polygons):
+ if not animall_properties.key_selected or polygon.select:
+ insert_key(polygon, 'material_index', group=data_("Face %s") % p_i)
+
+ if animall_properties.key_attribute:
+ if data.attributes.active is not None:
+ attribute = data.attributes.active
+ if attribute.data_type != 'STRING':
+ # Cannot animate string attributes?
+ if attribute.data_type in {'FLOAT', 'INT', 'BOOLEAN', 'INT8'}:
+ attribute_key = "value"
+ elif attribute.data_type in {'FLOAT_COLOR', 'BYTE_COLOR'}:
+ attribute_key = "color"
+ elif attribute.data_type in {'FLOAT_VECTOR', 'FLOAT2'}:
+ attribute_key = "vector"
+
+ if attribute.domain == 'POINT':
+ group = data_("Vertex %s")
+ elif attribute.domain == 'EDGE':
+ group = data_("Edge %s")
+ elif attribute.domain == 'FACE':
+ group = data_("Face %s")
+ elif attribute.domain == 'CORNER':
+ group = data_("Loop %s")
+
+ for e_i, _attribute_data in enumerate(attribute.data):
+ if (not animall_properties.key_selected
+ or attribute.domain == 'POINT' and data.vertices[e_i].select
+ or attribute.domain == 'EDGE' and data.edges[e_i].select
+ or attribute.domain == 'FACE' and data.polygons[e_i].select
+ or attribute.domain == 'CORNER' and is_selected_vert_loop(data, e_i)):
+ insert_key(data, f'attributes["{attribute.name}"].data[{e_i}].{attribute_key}',
+ group=group % e_i)
+
+ if animall_properties.key_uvs:
+ if data.uv_layers.active is not None:
+ for uv_i, uv in enumerate(data.uv_layers.active.data):
+ if not animall_properties.key_selected or uv.select:
+ insert_key(uv, 'uv', group=data_("UV layer %s") % uv_i)
+
+ if animall_properties.key_shape_key:
+ if obj.active_shape_key_index > 0:
+ sk_name = obj.active_shape_key.name
+ for v_i, vert in enumerate(obj.active_shape_key.data):
+ if not animall_properties.key_selected or data.vertices[v_i].select:
+ insert_key(vert, 'co', group=data_("%s Vertex %s") % (sk_name, v_i))
+
+ elif obj.type in {'CURVE', 'SURFACE'}:
+ # Shape key keys have to be inserted in object mode for curves...
+ if animall_properties.key_shape_key:
+ sk_name = obj.active_shape_key.name
+ global_spline_index = 0 # numbering for shape keys, which have flattened indices
+ for s_i, spline in enumerate(data.splines):
+ if spline.type == 'BEZIER':
+ for v_i, CV in enumerate(spline.bezier_points):
+ if (not animall_properties.key_selected
+ or CV.select_control_point
+ or CV.select_left_handle
+ or CV.select_right_handle):
+ if obj.active_shape_key_index > 0:
+ CV = obj.active_shape_key.data[global_spline_index]
+ insert_key(CV, 'co', group=data_("%s Spline %s CV %s") % (sk_name, s_i, v_i))
+ insert_key(CV, 'handle_left', group=data_("%s Spline %s CV %s") % (sk_name, s_i, v_i))
+ insert_key(CV, 'handle_right', group=data_("%s Spline %s CV %s") % (sk_name, s_i, v_i))
+ insert_key(CV, 'radius', group=data_("%s Spline %s CV %s") % (sk_name, s_i, v_i))
+ insert_key(CV, 'tilt', group=data_("%s Spline %s CV %s") % (sk_name, s_i, v_i))
+ global_spline_index += 1
+
+ elif spline.type in ('POLY', 'NURBS'):
+ for v_i, CV in enumerate(spline.points):
+ if not animall_properties.key_selected or CV.select:
+ if obj.active_shape_key_index > 0:
+ CV = obj.active_shape_key.data[global_spline_index]
+ insert_key(CV, 'co', group=data_("%s Spline %s CV %s") % (sk_name, s_i, v_i))
+ insert_key(CV, 'radius', group=data_("%s Spline %s CV %s") % (sk_name, s_i, v_i))
+ insert_key(CV, 'tilt', group=data_("%s Spline %s CV %s") % (sk_name, s_i, v_i))
+ global_spline_index += 1
+
+ bpy.ops.object.mode_set(mode=mode)
+ refresh_ui_keyframes()
+
+ return {'FINISHED'}
+
+
+class ANIM_OT_delete_keyframe_animall(Operator):
+ bl_label = "Delete Key"
+ bl_idname = "anim.delete_keyframe_animall"
+ bl_description = "Delete a Keyframe"
+ bl_options = {'REGISTER', 'UNDO'}
+
+ def execute(self, context):
+ animall_properties = context.scene.animall_properties
+
+ if context.mode == 'OBJECT':
+ objects = context.selected_objects
+ else:
+ objects = context.objects_in_mode_unique_data[:]
+
+ mode = context.object.mode
+
+ for obj in objects:
+ data = obj.data
+ if obj.type == 'MESH':
+ if animall_properties.key_point_location:
+ for vert in data.vertices:
+ if not animall_properties.key_selected or vert.select:
+ delete_key(vert, 'co')
+
+ if animall_properties.key_vertex_bevel:
+ for vert in data.vertices:
+ if not animall_properties.key_selected or vert.select:
+ delete_key(vert, 'bevel_weight')
+
+ if animall_properties.key_vertex_group:
+ for vert in data.vertices:
+ if not animall_properties.key_selected or vert.select:
+ for group in vert.groups:
+ delete_key(group, 'weight')
+
+ # if animall_properties.key_vertex_crease:
+ # for vert in data.vertices:
+ # if not animall_properties.key_selected or vert.select:
+ # delete_key(vert, 'crease')
+
+ if animall_properties.key_edge_bevel:
+ for edge in data.edges:
+ if not animall_properties.key_selected or edge.select:
+ delete_key(edge, 'bevel_weight')
+
+ if animall_properties.key_edge_crease:
+ for edge in data.edges:
+ if not animall_properties.key_selected or vert.select:
+ delete_key(edge, 'crease')
+
+ if animall_properties.key_shape_key:
+ if obj.active_shape_key:
+ for v_i, vert in enumerate(obj.active_shape_key.data):
+ if not animall_properties.key_selected or data.vertices[v_i].select:
+ delete_key(vert, 'co')
+
+ if animall_properties.key_uvs:
+ if data.uv_layers.active is not None:
+ for uv in data.uv_layers.active.data:
+ if not animall_properties.key_selected or uv.select:
+ delete_key(uv, 'uv')
+
+ if animall_properties.key_attribute:
+ if data.attributes.active is not None:
+ attribute = data.attributes.active
+ if attribute.data_type != 'STRING':
+ # Cannot animate string attributes?
+ if attribute.data_type in {'FLOAT', 'INT', 'BOOLEAN', 'INT8'}:
+ attribute_key = "value"
+ elif attribute.data_type in {'FLOAT_COLOR', 'BYTE_COLOR'}:
+ attribute_key = "color"
+ elif attribute.data_type in {'FLOAT_VECTOR', 'FLOAT2'}:
+ attribute_key = "vector"
+
+ for e_i, _attribute_data in enumerate(attribute.data):
+ if (not animall_properties.key_selected
+ or attribute.domain == 'POINT' and data.vertices[e_i].select
+ or attribute.domain == 'EDGE' and data.edges[e_i].select
+ or attribute.domain == 'FACE' and data.polygons[e_i].select
+ or attribute.domain == 'CORNER' and is_selected_vert_loop(data, e_i)):
+ delete_key(data, f'attributes["{attribute.name}"].data[{e_i}].{attribute_key}')
+
+ elif obj.type == 'LATTICE':
+ if animall_properties.key_shape_key:
+ if obj.active_shape_key:
+ for point in obj.active_shape_key.data:
+ delete_key(point, 'co')
+
+ if animall_properties.key_point_location:
+ for point in data.points:
+ if not animall_properties.key_selected or point.select:
+ delete_key(point, 'co_deform')
+
+ elif obj.type in {'CURVE', 'SURFACE'}:
+ # Run this outside the splines loop (only once)
+ if animall_properties.key_shape_key:
+ if obj.active_shape_key_index > 0:
+ for CV in obj.active_shape_key.data:
+ delete_key(CV, 'co')
+ delete_key(CV, 'handle_left')
+ delete_key(CV, 'handle_right')
+
+ for spline in data.splines:
+ if spline.type == 'BEZIER':
+ for CV in spline.bezier_points:
+ if (not animall_properties.key_selected
+ or CV.select_control_point
+ or CV.select_left_handle
+ or CV.select_right_handle):
+ if animall_properties.key_point_location:
+ delete_key(CV, 'co')
+ delete_key(CV, 'handle_left')
+ delete_key(CV, 'handle_right')
+ if animall_properties.key_radius:
+ delete_key(CV, 'radius')
+ if animall_properties.key_tilt:
+ delete_key(CV, 'tilt')
+
+ elif spline.type in ('POLY', 'NURBS'):
+ for CV in spline.points:
+ if not animall_properties.key_selected or CV.select:
+ if animall_properties.key_point_location:
+ delete_key(CV, 'co')
+ if animall_properties.key_radius:
+ delete_key(CV, 'radius')
+ if animall_properties.key_tilt:
+ delete_key(CV, 'tilt')
+
+ refresh_ui_keyframes()
+
+ return {'FINISHED'}
+
+
+class ANIM_OT_clear_animation_animall(Operator):
+ bl_label = "Clear Animation"
+ bl_idname = "anim.clear_animation_animall"
+ bl_description = ("Delete all keyframes for this object\n"
+ "If in a specific case it doesn't work\n"
+ "try to delete the keys manually")
+ bl_options = {'REGISTER', 'UNDO'}
+
+ def invoke(self, context, event):
+ wm = context.window_manager
+ return wm.invoke_confirm(self, event)
+
+ def execute(self, context):
+ if context.mode == 'OBJECT':
+ objects = context.selected_objects
+ else:
+ objects = context.objects_in_mode_unique_data
+
+ for obj in objects:
+ try:
+ data = obj.data
+ data.animation_data_clear()
+ except:
+ self.report({'WARNING'}, "Clear Animation could not be performed")
+ return {'CANCELLED'}
+
+ refresh_ui_keyframes()
+
+ return {'FINISHED'}
+
+
+class ANIM_OT_update_vertex_color_animation_animall(Operator):
+ bl_label = "Update Vertex Color Animation"
+ bl_idname = "anim.update_vertex_color_animation_animall"
+ bl_description = "Update old vertex color channel formats from pre-3.3 versions"
+ bl_options = {'REGISTER', 'UNDO'}
+
+ @classmethod
+ def poll(self, context):
+ if (context.active_object is None
+ or context.active_object.type != 'MESH'
+ or context.active_object.data.animation_data is None
+ or context.active_object.data.animation_data.action is None):
+ return False
+ for fcurve in context.active_object.data.animation_data.action.fcurves:
+ if fcurve.data_path.startswith("vertex_colors"):
+ return True
+
+ def execute(self, context):
+ for fcurve in context.active_object.data.animation_data.action.fcurves:
+ if fcurve.data_path.startswith("vertex_colors"):
+ fcurve.data_path = fcurve.data_path.replace("vertex_colors", "attributes")
+ return {'FINISHED'}
+
+# Add-ons Preferences Update Panel
+
+# Define Panel classes for updating
+panels = [
+ VIEW3D_PT_animall
+ ]
+
+
+def update_panel(self, context):
+ message = "AnimAll: Updating Panel locations has failed"
+ try:
+ for panel in panels:
+ if "bl_rna" in panel.__dict__:
+ bpy.utils.unregister_class(panel)
+
+ for panel in panels:
+ panel.bl_category = context.preferences.addons[__name__].preferences.category
+ bpy.utils.register_class(panel)
+
+ except Exception as e:
+ print("\n[{}]\n{}\n\nError:\n{}".format(__name__, message, e))
+ pass
+
+
+class AnimallAddonPreferences(AddonPreferences):
+ # this must match the addon name, use '__package__'
+ # when defining this in a submodule of a python package.
+ bl_idname = __name__
+
+ category: StringProperty(
+ name="Tab Category",
+ description="Choose a name for the category of the panel",
+ default="Animate",
+ update=update_panel
+ )
+
+ def draw(self, context):
+ layout = self.layout
+ row = layout.row()
+ col = row.column()
+
+ col.label(text="Tab Category:")
+ col.prop(self, "category", text="")
+
+register_classes, unregister_classes = bpy.utils.register_classes_factory(
+ (AnimallProperties, VIEW3D_PT_animall, ANIM_OT_insert_keyframe_animall,
+ ANIM_OT_delete_keyframe_animall, ANIM_OT_clear_animation_animall,
+ ANIM_OT_update_vertex_color_animation_animall, AnimallAddonPreferences))
+
+def register():
+ register_classes()
+ bpy.types.Scene.animall_properties = bpy.props.PointerProperty(type=AnimallProperties)
+ update_panel(None, bpy.context)
+ bpy.app.translations.register(__name__, translations.translations_dict)
+
+def unregister():
+ bpy.app.translations.unregister(__name__)
+ del bpy.types.Scene.animall_properties
+ unregister_classes()
+
+if __name__ == "__main__":
+ register()