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(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 obj, Action action) { try { UndoDisable(obj); action.Invoke(); } finally { UndoEnable(obj); } } internal static TResult NoUndo(T obj, Func action) { try { UndoDisable(obj); return action.Invoke(); } finally { UndoEnable(obj); } } private static void UndoDisable(T state) { GetPushUndoProperty().SetValue(state, false); } private static void UndoEnable(T state) { GetPushUndoProperty().SetValue(state, true); } private static PropertyInfo GetPushUndoProperty() { return typeof(T) .GetProperty("pushUndo", BindingFlags.Instance | BindingFlags.NonPublic); } } }