2025-05-09 15:40:34 +08:00

88 lines
3.0 KiB
C#

// Animancer // https://kybernetik.com.au/animancer // Copyright 2018-2024 Kybernetik //
#if UNITY_EDITOR
using System;
using UnityEditor;
using Object = UnityEngine.Object;
namespace Animancer.Editor
{
/// <summary>[Editor-Only]
/// A utility for manually drawing a <see cref="UnityEditor.Editor"/>.
/// </summary>
/// https://kybernetik.com.au/animancer/api/Animancer.Editor/CachedEditor
public class CachedEditor : IDisposable
{
/************************************************************************************************************************/
[NonSerialized] private Object[] _Targets = Array.Empty<Object>();
[NonSerialized] private UnityEditor.Editor _Editor;
[NonSerialized] private bool _WillCleanup;
/************************************************************************************************************************/
/// <summary>
/// Creates a <see cref="UnityEditor.Editor"/> for the `target`
/// and caches it to be returned by subsequent calls with the same `target`.
/// </summary>
public UnityEditor.Editor GetEditor(Object target)
{
if (_Targets.Length == 1 &&
_Targets[0] == target &&
_Editor != null)
return _Editor;
Dispose();
AnimancerUtilities.SetLength(ref _Targets, 1);
_Targets[0] = target;
_Editor = UnityEditor.Editor.CreateEditor(target);
EnsureCleanup();
return _Editor;
}
/// <summary>
/// Creates a <see cref="UnityEditor.Editor"/> for the `targets`
/// and caches it to be returned by subsequent calls with the same `targets`.
/// </summary>
public UnityEditor.Editor GetEditor(Object[] targets)
{
if (AnimancerUtilities.ContentsAreEqual(targets, _Targets) &&
_Editor != null)
return _Editor;
Dispose();
_Targets = targets;
_Editor = UnityEditor.Editor.CreateEditor(targets);
EnsureCleanup();
return _Editor;
}
/************************************************************************************************************************/
/// <summary>Destroys the cached <see cref="UnityEditor.Editor"/>.</summary>
public void Dispose()
=> Object.DestroyImmediate(_Editor);
/************************************************************************************************************************/
/// <summary>Ensures that <see cref="Dispose"/> will be called before assemblies are reloaded.</summary>
private void EnsureCleanup()
{
if (_WillCleanup)
return;
_WillCleanup = true;
AssemblyReloadEvents.beforeAssemblyReload += Dispose;
}
/************************************************************************************************************************/
}
}
#endif