Files
2026-09-18 14:01:10 +01:00

162 lines
5.8 KiB
C#

using System;
using System.Reflection;
using UnityEditor;
using UnityEditor.Animations;
using UnityEngine;
using Object = UnityEngine.Object;
using Random = UnityEngine.Random;
// ReSharper disable once CheckNamespace
namespace AnimatorAsCode.V1
{
internal static class AacInternals
{
internal const string AutoGeneratedPrefix = "zAutogenerated/";
// The legacy prefix is preserved, because we need to still be able to clean up
// assets generated using that legacy prefix from previous versions.
internal const string AutoGeneratedLegacyPrefix = "zAutogenerated__";
internal static AnimatorController NewAnimatorController(AacConfiguration component, string suffix)
{
var animatorController = new AnimatorController();
animatorController.name = Internal_GenerateAnimationName(component, suffix); // FIXME animation name conflict
animatorController.hideFlags = HideFlags.None;
component.ContainerProvider.SaveAsPersistenceRequired(animatorController);
return animatorController;
}
internal static AnimationClip NewClip(AacConfiguration component, string suffix)
{
return RegisterClip(component, suffix, new AnimationClip());
}
internal static AnimationClip RegisterClip(AacConfiguration component, string suffix, AnimationClip clip)
{
clip.name = Internal_GenerateAnimationName(component, suffix);
clip.hideFlags = HideFlags.None;
component.ContainerProvider.SaveAsRegular(clip);
return clip;
}
internal static BlendTree NewBlendTreeAsRaw(AacConfiguration component, string suffix)
{
var clip = new BlendTree();
clip.name = Internal_GenerateAnimationName(component, suffix);
clip.hideFlags = HideFlags.None;
component.ContainerProvider.SaveAsRegular(clip);
return clip;
}
internal static T DuplicateAssetIntoContainer<T>(AacConfiguration component, T assetToDuplicate) where T : Object
{
var duplicated = (T)Object.Instantiate(assetToDuplicate);
duplicated.name = Internal_GenerateAnimationName(component, assetToDuplicate.name);
duplicated.hideFlags = HideFlags.None;
component.ContainerProvider.SaveAsRegular(duplicated);
return duplicated;
}
private static string Internal_GenerateAnimationName(AacConfiguration component, string middle)
{
return AutoGeneratedPrefix + component.AssetKey + "__" + middle + "_" + Random.Range(0, Int32.MaxValue); // FIXME animation name conflict
}
internal static AvatarMask NewAvatarMask(AacConfiguration component, string fullLayerName)
{
var avatarMask = new AvatarMask();
avatarMask.name = AutoGeneratedPrefix + component.AssetKey + "_" + fullLayerName + "__AvatarMask";
avatarMask.hideFlags = HideFlags.None;
component.ContainerProvider.SaveAsRegular(avatarMask);
return avatarMask;
}
internal static EditorCurveBinding Binding(AacConfiguration component, Type type, Transform transform, string propertyName)
{
return new EditorCurveBinding
{
path = ResolveRelativePath(component.AnimatorRoot, transform),
type = type,
propertyName = propertyName
};
}
internal static void SetCurve(AnimationClip clip, EditorCurveBinding binding, AnimationCurve curve)
{
// https://forum.unity.com/threads/new-animationclip-property-names.367288/#post-2384172
clip.SetCurve(binding.path, binding.type, binding.propertyName, curve);
}
internal static AnimationCurve OneFrame(float desiredValue)
{
return AnimationCurve.Constant(0f, 1 / 60f, desiredValue);
}
internal static AnimationCurve ConstantSeconds(float seconds, float desiredValue)
{
return AnimationCurve.Constant(0f, seconds, desiredValue);
}
internal static string ResolveRelativePath(Transform avatar, Transform item)
{
if (avatar == item)
{
// TODO: Is this correct??
return "";
}
if (item.parent != avatar && item.parent != null)
{
return ResolveRelativePath(avatar, item.parent) + "/" + item.name;
}
return item.name;
}
internal static EditorCurveBinding ToSubBinding(EditorCurveBinding binding, string suffix)
{
return new EditorCurveBinding {path = binding.path, type = binding.type, propertyName = binding.propertyName + "." + suffix};
}
internal static void NoUndo<T>(T obj, Action action)
{
try
{
UndoDisable(obj);
action.Invoke();
}
finally
{
UndoEnable(obj);
}
}
internal static TResult NoUndo<T, TResult>(T obj, Func<TResult> action)
{
try
{
UndoDisable(obj);
return action.Invoke();
}
finally
{
UndoEnable(obj);
}
}
private static void UndoDisable<T>(T state)
{
GetPushUndoProperty<T>().SetValue(state, false);
}
private static void UndoEnable<T>(T state)
{
GetPushUndoProperty<T>().SetValue(state, true);
}
private static PropertyInfo GetPushUndoProperty<T>()
{
return typeof(T)
.GetProperty("pushUndo", BindingFlags.Instance | BindingFlags.NonPublic);
}
}
}