// Animancer // https://kybernetik.com.au/animancer // Copyright 2018-2026 Kybernetik // #if UNITY_EDITOR using Animancer.TransitionLibraries; using System.Collections.Generic; using UnityEditor; using UnityEngine; namespace Animancer.Editor.TransitionLibraries { /// [Editor-Only] /// Additional data for a which is excluded from Runtime Builds. /// /// https://kybernetik.com.au/animancer/api/Animancer.Editor.TransitionLibraries/TransitionLibraryEditorDataAsset [AnimancerHelpUrl(typeof(TransitionLibraryEditorDataAsset))] public partial class TransitionLibraryEditorDataAsset : ScriptableObject { /************************************************************************************************************************/ /// Libraries mapped to their editor data. /// /// Libraries can't have a direct reference to this class /// because it's in the Editor assembly which the Runtime assembly doesn't reference. /// private static readonly Dictionary LibraryToEditorData = new(); /************************************************************************************************************************/ /// The name of the serialized backing field of . internal const string LibraryFieldName = nameof(_Library); [SerializeField] private TransitionLibraryAsset _Library; /// The library this data is associated with. public TransitionLibraryAsset Library => _Library; /************************************************************************************************************************/ /// The name of the serialized backing field of . internal const string DataFieldName = nameof(_Data); [SerializeField] private TransitionLibraryEditorDataInternal _Data; /// [] The data contained in this asset. public TransitionLibraryEditorDataInternal Data { get => _Data ??= new(); set { SetLibrary(this, _Library); _Data = value; EditorUtility.SetDirty(this); } } /************************************************************************************************************************/ /// Registers this data for the . protected virtual void OnEnable() { if (_Library != null) LibraryToEditorData[_Library] = this; } /// Un-registers this data for the . protected virtual void OnDisable() { if (_Library != null) LibraryToEditorData.Remove(_Library); } /************************************************************************************************************************/ /// Sets the . public static void SetLibrary(TransitionLibraryEditorDataAsset data, TransitionLibraryAsset library) { if (library != null) LibraryToEditorData.Remove(library); data._Library = library; if (library != null) LibraryToEditorData.Add(library, data); } /************************************************************************************************************************/ /// Tries to get the `data` associated with the `library`. private static bool TryGet( TransitionLibraryAsset library, out TransitionLibraryEditorDataAsset asset) { if (!LibraryToEditorData.TryGetValue(library, out asset)) return false; if (asset != null) { SetLibrary(asset, library); return true; } LibraryToEditorData.Remove(library); return false; } /************************************************************************************************************************/ /// /// Returns the sub-asset of the `library` if one exists. /// public static TransitionLibraryEditorDataAsset GetEditorData(TransitionLibraryAsset library) { if (TryGet(library, out var asset)) return asset; var assetPath = AssetDatabase.GetAssetPath(library); if (string.IsNullOrEmpty(assetPath)) return null; var subAssets = AssetDatabase.LoadAllAssetsAtPath(assetPath); for (int i = 0; i < subAssets.Length; i++) { if (subAssets[i] is TransitionLibraryEditorDataAsset editorData) { asset = editorData; SetLibrary(asset, library); return asset; } } return null; } /************************************************************************************************************************/ /// /// Returns the sub-asset of the `library` if one exists. /// Otherwise, creates and saves a new one. /// public static TransitionLibraryEditorDataAsset GetOrCreateEditorData(TransitionLibraryAsset library) { var data = library.GetEditorData(); if (data != null) return data; data = CreateInstance(); data.name = "Editor Data"; data.hideFlags = HideFlags.DontSaveInBuild | HideFlags.HideInHierarchy; SetLibrary(data, library); EditorApplication.CallbackFunction addSubAsset = null; addSubAsset = () => { if (AssetDatabase.Contains(library)) { EditorApplication.update -= addSubAsset; AssetDatabase.AddObjectToAsset(data, library); AssetDatabase.SaveAssets(); } }; EditorApplication.update += addSubAsset; return data; } /************************************************************************************************************************/ } /// [Editor-Only] Extension methods for . /// https://kybernetik.com.au/animancer/api/Animancer.Editor.TransitionLibraries/TransitionLibraryEditorDataExtensions public static class TransitionLibraryEditorDataExtensions { /************************************************************************************************************************/ /// public static TransitionLibraryEditorDataAsset GetEditorData(this TransitionLibraryAsset library) => TransitionLibraryEditorDataAsset.GetEditorData(library); /// public static TransitionLibraryEditorDataAsset GetOrCreateEditorData(this TransitionLibraryAsset library) => TransitionLibraryEditorDataAsset.GetOrCreateEditorData(library); /************************************************************************************************************************/ } } #endif