117 lines
4.5 KiB
C#
117 lines
4.5 KiB
C#
using System.IO;
|
|
using UnityEditor;
|
|
using UnityEngine;
|
|
using System.Collections.Generic;
|
|
|
|
public class AnimationEditor {
|
|
[MenuItem("Assets/Scale Animation Transforms...", true)]
|
|
private static bool ValidateScaleMenu() {
|
|
// enable only when an AnimationClip is selected
|
|
return Selection.objects != null && Selection.objects.Length > 0 && System.Array.Exists(Selection.objects, o => o is AnimationClip);
|
|
}
|
|
|
|
[MenuItem("Assets/Scale Animation Transforms...")]
|
|
private static void ScaleSelectedClips() {
|
|
// default scale - you can change or prompt
|
|
float scale = 2.0f;
|
|
|
|
var clips = new List<AnimationClip>();
|
|
foreach (var o in Selection.objects)
|
|
if (o is AnimationClip clip)
|
|
clips.Add(clip);
|
|
|
|
if (clips.Count == 0) {
|
|
EditorUtility.DisplayDialog("Scale Animation", "No AnimationClip selected.", "OK");
|
|
return;
|
|
}
|
|
|
|
if (!EditorUtility.DisplayDialog("Scale Animation", $"Scale translations in {clips.Count} clip(s) by {scale}?", "Yes", "No"))
|
|
return;
|
|
|
|
foreach (AnimationClip clip in clips) {
|
|
ScaleClip(clip, scale);
|
|
}
|
|
|
|
EditorUtility.DisplayDialog("Scale Animation", "Done scaling selected clips.", "OK");
|
|
}
|
|
|
|
public static void ScaleClip(AnimationClip clip, float scale, string saveFolder) {
|
|
string origPath = AssetDatabase.GetAssetPath(clip);
|
|
|
|
string ext = Path.GetExtension(origPath);
|
|
string nameNoExt = Path.GetFileNameWithoutExtension(origPath);
|
|
string fileName = $"{nameNoExt}_scaled{ext}";
|
|
string savePath = Path.Combine(saveFolder, fileName).Replace("\\", "/");
|
|
|
|
if (AssetDatabase.LoadAssetAtPath<Object>(savePath) != null) {
|
|
if (!AssetDatabase.DeleteAsset(savePath)) {
|
|
Debug.LogError($"Failed to delete existing asset at {savePath}");
|
|
return;
|
|
}
|
|
Debug.Log($"Deleted old {savePath}");
|
|
AssetDatabase.Refresh();
|
|
}
|
|
|
|
if (!AssetDatabase.CopyAsset(origPath, savePath)) {
|
|
Debug.LogError($"Failed to duplicate asset: {origPath} -> {savePath}");
|
|
return;
|
|
}
|
|
|
|
AssetDatabase.ImportAsset(savePath);
|
|
AnimationClip newClip = AssetDatabase.LoadAssetAtPath<AnimationClip>(savePath);
|
|
if (newClip == null) {
|
|
Debug.LogError($"Failed to load duplicated clip at: {savePath}");
|
|
return;
|
|
}
|
|
ScaleClip(newClip, scale);
|
|
|
|
}
|
|
|
|
public static void ScaleClip(AnimationClip clip, float scale) {
|
|
// make editable copy if needed (if clip is in model import, make sure to duplicate or modify import settings)
|
|
Undo.RegisterCompleteObjectUndo(clip, "Scale Animation Translations");
|
|
|
|
// Collect curve bindings for position-like properties.
|
|
EditorCurveBinding[] bindings = AnimationUtility.GetCurveBindings(clip);
|
|
foreach (EditorCurveBinding binding in bindings) {
|
|
string prop = binding.propertyName;
|
|
if (string.IsNullOrEmpty(prop))
|
|
continue;
|
|
|
|
// Identify position/localPosition/property patterns to scale:
|
|
// common property names:
|
|
// "m_LocalPosition.x", "m_LocalPosition.y", "m_LocalPosition.z"
|
|
// "localPosition.x", etc. or custom paths that animate transform.localPosition
|
|
// We'll scale any curve with "position" or "LocalPosition" in propertyName (case-insensitive).
|
|
|
|
string lower = prop.ToLowerInvariant();
|
|
bool isPos =
|
|
lower.Contains("m_localposition") ||
|
|
lower.Contains("localposition") ||
|
|
lower.Contains(".position") ||
|
|
lower == "position.x" || lower == "position.y" || lower == "position.z";
|
|
|
|
if (!isPos)
|
|
continue;
|
|
|
|
AnimationCurve curve = AnimationUtility.GetEditorCurve(clip, binding);
|
|
if (curve == null) continue;
|
|
|
|
// scale each keyframe value
|
|
Keyframe[] keys = curve.keys;
|
|
for (int i = 0; i < keys.Length; i++) {
|
|
Keyframe k = keys[i];
|
|
k.value *= scale;
|
|
k.inTangent *= scale;
|
|
k.outTangent *= scale;
|
|
keys[i] = k;
|
|
}
|
|
|
|
curve.keys = keys;
|
|
AnimationUtility.SetEditorCurve(clip, binding, curve);
|
|
}
|
|
|
|
EditorUtility.SetDirty(clip);
|
|
AssetDatabase.SaveAssets();
|
|
}
|
|
} |