Skip to content

Instantly share code, notes, and snippets.

@AnomalousUnderdog
Last active October 17, 2017 16:11
Show Gist options
  • Save AnomalousUnderdog/3f61553421484194398d119f3a632b4b to your computer and use it in GitHub Desktop.
Save AnomalousUnderdog/3f61553421484194398d119f3a632b4b to your computer and use it in GitHub Desktop.
Edit keyframes of selected armature bones to each match their first keyframes.
bl_info = {
"name": "Fix Seams of Cyclic Keyframes",
"description": "Edit keyframes of selected armature bones to each match their first keyframes.",
"author": "Ferdinand Joseph Fernandez",
"version": (1, 3),
"location": "Dopesheet > Key > Fix Seams of Cyclic Keyframes",
"support": "TESTING",
"category": "Animation",
}
#
# I am putting the MIT license notice right inside this file because this add-on
# is just one file at the moment. --Ferdinand
#
# ----------------------
#
# Copyright (c) 2017 Ferdinand Joseph Fernandez
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in all
# copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.
#
import bpy, bgl, blf, math
from bpy.props import *
class FixSeamsOfCyclicKeyframes(bpy.types.Operator):
"""Fix Seams of Cyclic Keyframes"""
bl_idname = "animation.fix_end_of_cyclic_keyframes"
bl_label = "Fix Seams of Cyclic Keyframes"
bl_options = {'REGISTER', 'UNDO'}
# def __init__(self):
# self.text_display = ""
def execute(self, context):
if (bpy.context.selected_pose_bones is None or len(bpy.context.selected_pose_bones) == 0):
# no bone selected
self.report({'WARNING'}, "No bone selected.")
return {'CANCELLED'}
bone_names = [b.name for b in bpy.context.selected_pose_bones]
fcurves = bpy.context.active_object.animation_data.action.fcurves
#print("start")
for curve in fcurves:
#print (curve.data_path)
# if this curve belongs to the currently selected bone
if curve.data_path.split('"')[1] in bone_names:
keyframePoints = curve.keyframe_points
if len(keyframePoints) > 0:
#for keyframe in keyframePoints:
# print(keyframe.co)
firstKeyframeCo = keyframePoints[0].co
lastKeyframeCo = keyframePoints[len(keyframePoints)-1].co
#print("last keyframe: %s" % lastKeyframeCo)
deltaY = firstKeyframeCo[1] - lastKeyframeCo[1]
if (abs(deltaY) > 0.0001):
#print("deltaY for %s: %s" % (curve.data_path, deltaY))
for idx in range(len(keyframePoints)):
#print(idx)
if (idx > 0):
keyframePoints[idx].co[1] += deltaY
keyframePoints[idx].handle_left[1] += deltaY
keyframePoints[idx].handle_right[1] += deltaY
return {'FINISHED'}
def menu_separator(self, context):
self.layout.separator()
def fix_cyclic_keyframes_menu(self, context):
self.layout.operator(FixSeamsOfCyclicKeyframes.bl_idname)
# keymaps are stored here so they can be accessed after registration
addon_keymaps = []
def register():
bpy.utils.register_module(__name__)
# menu registration
bpy.types.DOPESHEET_MT_key.prepend(menu_separator)
bpy.types.DOPESHEET_MT_key.prepend(fix_cyclic_keyframes_menu)
# # hotkey registration
# wm = bpy.context.window_manager
# kc = wm.keyconfigs.addon
# if kc:
# keymap = kc.keymaps.new(name='Dopesheet', space_type='DOPESHEET_EDITOR')
# keymap_item = keymap.keymap_items.new(GetSelectedKeyframesLength.bl_idname, 'Q', 'PRESS')
#
# # add to list so we can unregister afterwards
# addon_keymaps.append((keymap, keymap_item))
def unregister():
# # unregister hotkey
# wm = bpy.context.window_manager
# kc = wm.keyconfigs.addon
# if kc:
# for km, kmi in addon_keymaps:
# km.keymap_items.remove(kmi)
#
# addon_keymaps.clear()
bpy.utils.unregister_module(__name__)
# unregister menu
bpy.types.DOPESHEET_MT_key.remove(fix_cyclic_keyframes_menu)
bpy.types.DOPESHEET_MT_key.remove(menu_separator)
if __name__ == "__main__":
register()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment