// Animancer // https://kybernetik.com.au/animancer // Copyright 2018-2023 Kybernetik // #if UNITY_EDITOR #pragma warning disable CS0649 // Field is never assigned to, and will always have its default value. using Animancer.Units; using System.Collections.Generic; using System.IO; using UnityEditor; using UnityEngine; namespace Animancer.Editor { /// [Editor-Only] Persistent settings used by Animancer. /// /// This asset automatically creates itself when first accessed such as when opening the /// or viewing an . /// /// The default location is Assets/Plugins/Animancer/Editor, but you can freely move it (and the whole /// Animancer folder) anywhere in your project. /// /// These settings can also be accessed via the Settings in the /// (Window/Animation/Animancer Tools). /// /// https://kybernetik.com.au/animancer/api/Animancer.Editor/AnimancerSettings /// [HelpURL(Strings.DocsURLs.APIDocumentation + "." + nameof(Editor) + "/" + nameof(AnimancerSettings))] public class AnimancerSettings : ScriptableObject { /************************************************************************************************************************/ private static AnimancerSettings _Instance; /// /// Loads an existing if there is one anywhere in your project, but otherwise /// creates a new one and saves it in the same folder as this script. /// public static AnimancerSettings Instance { get { if (_Instance != null) return _Instance; _Instance = AnimancerEditorUtilities.FindAssetOfType(); if (_Instance != null) return _Instance; _Instance = CreateInstance(); _Instance.name = "Animancer Settings"; _Instance.hideFlags = HideFlags.DontSaveInBuild; var script = MonoScript.FromScriptableObject(_Instance); var path = AssetDatabase.GetAssetPath(script); path = Path.Combine(Path.GetDirectoryName(path), $"{_Instance.name}.asset"); AssetDatabase.CreateAsset(_Instance, path); return _Instance; } } /************************************************************************************************************************/ private SerializedObject _SerializedObject; /// The representing the . public static SerializedObject SerializedObject => Instance._SerializedObject ?? (Instance._SerializedObject = new SerializedObject(Instance)); /************************************************************************************************************************/ private readonly Dictionary SerializedProperties = new Dictionary(); private static SerializedProperty GetSerializedProperty(string propertyPath) { var properties = Instance.SerializedProperties; if (!properties.TryGetValue(propertyPath, out var property)) { property = SerializedObject.FindProperty(propertyPath); properties.Add(propertyPath, property); } return property; } /************************************************************************************************************************/ /// Base class for groups of fields that can be serialized inside . public abstract class Group { /************************************************************************************************************************/ private string _BasePropertyPath; /// [Internal] Sets the prefix for . internal void SetBasePropertyPath(string propertyPath) { _BasePropertyPath = propertyPath + "."; } /************************************************************************************************************************/ /// Returns a relative to the base of this group. protected SerializedProperty GetSerializedProperty(string propertyPath) => AnimancerSettings.GetSerializedProperty(_BasePropertyPath + propertyPath); /************************************************************************************************************************/ /// /// Draws a for a /// property in this group. /// protected SerializedProperty DoPropertyField(string propertyPath) { var property = GetSerializedProperty(propertyPath); EditorGUILayout.PropertyField(property, true); return property; } /************************************************************************************************************************/ } /************************************************************************************************************************/ /// Initializes the serialized fields. protected virtual void OnEnable() { if (_TransitionPreviewWindow == null) _TransitionPreviewWindow = new TransitionPreviewWindow.Settings(); _TransitionPreviewWindow.SetBasePropertyPath(nameof(_TransitionPreviewWindow)); } /************************************************************************************************************************/ /// Calls on the . public static new void SetDirty() => EditorUtility.SetDirty(_Instance); /************************************************************************************************************************/ [SerializeField] private TransitionPreviewWindow.Settings _TransitionPreviewWindow; /// Settings for the . internal static TransitionPreviewWindow.Settings TransitionPreviewWindow => Instance._TransitionPreviewWindow; /************************************************************************************************************************/ [SerializeField] private AnimationTimeAttribute.Settings _AnimationTimeFields; /// Settings for the . public static AnimationTimeAttribute.Settings AnimationTimeFields => Instance._AnimationTimeFields; /************************************************************************************************************************/ [SerializeField, Range(0.01f, 1)] [Tooltip("The amount of time between repaint commands when 'Display Options/Repaint Constantly' is disabled")] private float _InspectorRepaintInterval = 0.25f; /// /// The amount of time between repaint commands when /// is disabled. /// public static float InspectorRepaintInterval => Instance._InspectorRepaintInterval; /************************************************************************************************************************/ [SerializeField] [Seconds(Rule = Validate.Value.IsNotNegative)] [DefaultValue(0.02f)] [Tooltip("The amount of time that will be added by a single frame step")] private float _FrameStep = 0.02f; /// The amount of time that will be added by a single frame step (in seconds). public static float FrameStep => Instance._FrameStep; /************************************************************************************************************************/ [SerializeField] [Tooltip("The frame rate to use for new animations")] private float _NewAnimationFrameRate = 12; /// The frame rate to use for new animations. public static SerializedProperty NewAnimationFrameRate => GetSerializedProperty(nameof(_NewAnimationFrameRate)); /************************************************************************************************************************/ [SerializeField] [Tooltip("Should Animancer Event Callbacks be hidden in the Inspector?")] private bool _HideEventCallbacks; /// Should Animancer Event Callbacks be hidden in the Inspector? public static bool HideEventCallbacks => Instance._HideEventCallbacks; /************************************************************************************************************************/ /// A custom Inspector for . [CustomEditor(typeof(AnimancerSettings), true), CanEditMultipleObjects] public class Editor : UnityEditor.Editor { /************************************************************************************************************************/ /// public override void OnInspectorGUI() { base.OnInspectorGUI(); EditorGUILayout.BeginHorizontal(); using (ObjectPool.Disposable.AcquireContent(out var label, "Disabled Warnings")) { EditorGUI.BeginChangeCheck(); var value = EditorGUILayout.EnumFlagsField(label, Validate.PermanentlyDisabledWarnings); if (EditorGUI.EndChangeCheck()) Validate.PermanentlyDisabledWarnings = (OptionalWarning)value; } if (GUILayout.Button("Help", EditorStyles.miniButton, AnimancerGUI.DontExpandWidth)) Application.OpenURL(Strings.DocsURLs.OptionalWarning); EditorGUILayout.EndHorizontal(); } /************************************************************************************************************************/ } /************************************************************************************************************************/ } } #endif