Files
HauntedBloodlines/Assets/Editor/ReverseAnimationContext.cs
2025-05-29 22:31:40 +03:00

127 lines
4.5 KiB
C#

using UnityEditor;
using UnityEngine;
using System.IO;
using System.Collections.Generic;
using UnityEditor.Animations;
public static class ReverseAnimationContext
{
[MenuItem("Assets/Create Reversed Clip", false, 14)]
private static void ReverseClips()
{
List<AnimatorController> animConts = new List<AnimatorController>();
var animators = Object.FindObjectsOfType<Animator>();
AssetDatabase.FindAssets("t:AnimatorController");
List<AnimationClip> clips = GetSelectedClips();
if (clips != null && clips.Count > 0)
{
foreach (AnimationClip clip in clips)
{
ReverseClip(clip, animators);
}
Debug.Log("All selected clips reversed");
}
}
public static List<AnimationClip> GetSelectedClips()
{
var clips = Selection.GetFiltered(typeof(AnimationClip), SelectionMode.Assets);
List<AnimationClip> animClips = new List<AnimationClip>();
if (clips.Length > 0)
{
foreach (var clip in clips)
{
animClips.Add(clip as AnimationClip);
}
return animClips;
}
return null;
}
private static void ReverseClip(AnimationClip clip, Animator[] animators)//List<AnimatorController> animConts
{
AnimationClip originalClip = clip;
string directoryPath = Path.GetDirectoryName(AssetDatabase.GetAssetPath(clip)); //Selection.activeObject
string fileName = Path.GetFileName(AssetDatabase.GetAssetPath(clip));
string fileExtension = Path.GetExtension(AssetDatabase.GetAssetPath(clip));
fileName = fileName.Split('.')[0];
string copiedFilePath = directoryPath + Path.DirectorySeparatorChar + fileName + "_Reversed" + fileExtension;
AssetDatabase.CopyAsset(AssetDatabase.GetAssetPath(clip), copiedFilePath);
clip = (AnimationClip)AssetDatabase.LoadAssetAtPath(copiedFilePath, typeof(AnimationClip));
if (clip == null)
return;
float clipLength = clip.length;
var curves = AnimationUtility.GetCurveBindings(clip);
foreach (EditorCurveBinding binding in curves)
{
var animCurve = AnimationUtility.GetEditorCurve(clip, binding);
var keys = animCurve.keys;
int keyCount = keys.Length;
for (int i = 0; i < keyCount; i++)
{
Keyframe K = keys[i];
K.time = clipLength - K.time;
var tmp = -K.inTangent;
K.inTangent = -K.outTangent;
K.outTangent = tmp;
keys[i] = K;
}
animCurve.keys = keys;
clip.SetCurve(binding.path, binding.type, binding.propertyName, animCurve);
}
var events = AnimationUtility.GetAnimationEvents(clip);
if (events.Length > 0)
{
for (int i = 0; i < events.Length; i++)
{
events[i].time = clipLength - events[i].time;
}
AnimationUtility.SetAnimationEvents(clip, events);
}
foreach (Animator anim in animators)
{
AnimationClip[] clips = AnimationUtility.GetAnimationClips(anim.gameObject);
bool foundClip = false;
foreach (AnimationClip c in clips)
{
if (c == originalClip)
{
foundClip = true;
break;
}
}
if (foundClip)
{
Debug.Log("Found the animator containing the original clip that was reversed, adding new clip to its state machine...");
AnimatorController controller = UnityEditor.AssetDatabase.LoadAssetAtPath<UnityEditor.Animations.AnimatorController>(UnityEditor.AssetDatabase.GetAssetPath(anim.runtimeAnimatorController));
AnimatorStateMachine asm = controller.layers[0].stateMachine;
AnimatorState animState = asm.AddState(clip.name);
animState.motion = clip;
}
}
}
[MenuItem("Assets/Create Reversed Clip", true)]
static bool ReverseClipValidation()
{
return Selection.activeObject && Selection.activeObject.GetType() == typeof(AnimationClip);
}
public static AnimationClip GetSelectedClip()
{
var clips = Selection.GetFiltered(typeof(AnimationClip), SelectionMode.Assets);
if (clips.Length > 0)
{
return clips[0] as AnimationClip;
}
return null;
}
}