2025-12-01
This commit is contained in:
@@ -0,0 +1,63 @@
|
||||
import bpy
|
||||
|
||||
|
||||
class RemoveStaticFcurvesOperator(bpy.types.Operator):
|
||||
"""Operator to remove static FCurves"""
|
||||
bl_idname = "graph.remove_static_fcurves"
|
||||
bl_label = "Remove Static FCurves"
|
||||
bl_options = {"REGISTER", "UNDO"}
|
||||
|
||||
def execute(self, context):
|
||||
has_selection = any(obj.select_get()
|
||||
for obj in bpy.context.selected_objects)
|
||||
|
||||
if not has_selection:
|
||||
self.report({'ERROR_INVALID_INPUT'}, "Please select objects.")
|
||||
else:
|
||||
self.remove_static_fcurves()
|
||||
self.report({'INFO'}, "Removed static animation channels.")
|
||||
return {'FINISHED'}
|
||||
|
||||
@staticmethod
|
||||
def is_static_fcurve(fcurve):
|
||||
"""Check if an FCurve is static (all keyframes have the same value)."""
|
||||
keyframes = fcurve.keyframe_points
|
||||
if len(keyframes) < 2:
|
||||
return True # A single keyframe is considered static
|
||||
|
||||
first_value = keyframes[0].co[1]
|
||||
return all(kf.co[1] == first_value for kf in keyframes)
|
||||
|
||||
@staticmethod
|
||||
def remove_static_fcurves():
|
||||
"""Remove static FCurves that have no data."""
|
||||
for obj in bpy.context.selected_objects:
|
||||
if obj.animation_data and obj.animation_data.action:
|
||||
action = obj.animation_data.action
|
||||
fcurves_to_remove = [
|
||||
fcurve for fcurve in action.fcurves if RemoveStaticFcurvesOperator.is_static_fcurve(fcurve)]
|
||||
|
||||
for fcurve in fcurves_to_remove:
|
||||
action.fcurves.remove(fcurve)
|
||||
|
||||
|
||||
def menu_func(self, context):
|
||||
self.layout.operator(RemoveStaticFcurvesOperator.bl_idname)
|
||||
|
||||
|
||||
def register():
|
||||
bpy.utils.register_class(RemoveStaticFcurvesOperator)
|
||||
bpy.types.GRAPH_MT_channel.append(menu_func)
|
||||
bpy.types.DOPESHEET_MT_channel.append(menu_func)
|
||||
print("[Remove Static FCurves] registered")
|
||||
|
||||
|
||||
def unregister():
|
||||
bpy.utils.unregister_class(RemoveStaticFcurvesOperator)
|
||||
bpy.types.GRAPH_MT_channel.remove(menu_func)
|
||||
bpy.types.DOPESHEET_MT_channel.remove(menu_func)
|
||||
print("[Remove Static FCurves] unregistered")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
register()
|
||||
@@ -0,0 +1,75 @@
|
||||
schema_version = "1.0.0"
|
||||
|
||||
# Example of manifest file for a Blender extension
|
||||
# Change the values according to your extension
|
||||
id = "remove_static_fcurves"
|
||||
version = "0.2.1"
|
||||
name = "Remove Static FCurves"
|
||||
tagline = "Clean up animation channels that have no data"
|
||||
maintainer = "Loki McKay <lokimckay@gmail.com>"
|
||||
# Supported types: "add-on", "theme"
|
||||
type = "add-on"
|
||||
|
||||
# # Optional: link to documentation, support, source files, etc
|
||||
# website = "https://extensions.blender.org/add-ons/my-example-package/"
|
||||
|
||||
# # Optional: tag list defined by Blender and server, see:
|
||||
# # https://docs.blender.org/manual/en/dev/advanced/extensions/tags.html
|
||||
tags = ["Animation"]
|
||||
|
||||
blender_version_min = "4.2.0"
|
||||
# # Optional: Blender version that the extension does not support, earlier versions are supported.
|
||||
# # This can be omitted and defined later on the extensions platform if an issue is found.
|
||||
# blender_version_max = "5.1.0"
|
||||
|
||||
# License conforming to https://spdx.org/licenses/ (use "SPDX: prefix)
|
||||
# https://docs.blender.org/manual/en/dev/advanced/extensions/licenses.html
|
||||
license = [
|
||||
"SPDX:GPL-3.0-or-later",
|
||||
]
|
||||
# # Optional: required by some licenses.
|
||||
# copyright = [
|
||||
# "2002-2024 Developer Name",
|
||||
# "1998 Company Name",
|
||||
# ]
|
||||
|
||||
# # Optional: list of supported platforms. If omitted, the extension will be available in all operating systems.
|
||||
# platforms = ["windows-x64", "macos-arm64", "linux-x64"]
|
||||
# # Other supported platforms: "windows-arm64", "macos-x64"
|
||||
|
||||
# # Optional: bundle 3rd party Python modules.
|
||||
# # https://docs.blender.org/manual/en/dev/advanced/extensions/python_wheels.html
|
||||
# wheels = [
|
||||
# "./wheels/hexdump-3.3-py3-none-any.whl",
|
||||
# "./wheels/jsmin-3.0.1-py3-none-any.whl",
|
||||
# ]
|
||||
|
||||
# # Optional: add-ons can list which resources they will require:
|
||||
# # * files (for access of any filesystem operations)
|
||||
# # * network (for internet access)
|
||||
# # * clipboard (to read and/or write the system clipboard)
|
||||
# # * camera (to capture photos and videos)
|
||||
# # * microphone (to capture audio)
|
||||
# #
|
||||
# # If using network, remember to also check `bpy.app.online_access`
|
||||
# # https://docs.blender.org/manual/en/dev/advanced/extensions/addons.html#internet-access
|
||||
# #
|
||||
# # For each permission it is important to also specify the reason why it is required.
|
||||
# # Keep this a single short sentence without a period (.) at the end.
|
||||
# # For longer explanations use the documentation or detail page.
|
||||
#
|
||||
# [permissions]
|
||||
# network = "Need to sync motion-capture data to server"
|
||||
# files = "Import/export FBX from/to disk"
|
||||
# clipboard = "Copy and paste bone transforms"
|
||||
|
||||
# # Optional: advanced build settings.
|
||||
# # https://docs.blender.org/manual/en/dev/advanced/extensions/command_line_arguments.html#command-line-args-extension-build
|
||||
# [build]
|
||||
# # These are the default build excluded patterns.
|
||||
# # You only need to edit them if you want different options.
|
||||
# paths_exclude_pattern = [
|
||||
# "__pycache__/",
|
||||
# "/.git/",
|
||||
# "/*.zip",
|
||||
# ]
|
||||
Reference in New Issue
Block a user