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

99 lines
3.9 KiB
C#

// Animancer // https://kybernetik.com.au/animancer // Copyright 2018-2024 Kybernetik //
#if UNITY_EDITOR
using Animancer.Editor;
using System;
using System.Collections.Generic;
namespace Animancer.Editor
{
/// <summary>[Editor-Only]
/// An assembly attribute for configuring how the <see cref="PolymorphicDrawer"/>
/// displays a particular type.
/// </summary>
[AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)]
public sealed class PolymorphicDrawerDetails : Attribute
{
/************************************************************************************************************************/
/// <summary>A default instance.</summary>
public static readonly PolymorphicDrawerDetails
Default = new(null);
/************************************************************************************************************************/
/// <summary>The <see cref="System.Type"/> this attribute applies to.</summary>
public readonly Type Type;
/// <summary>Creates a new <see cref="PolymorphicDrawerDetails"/>.</summary>
public PolymorphicDrawerDetails(Type type)
=> Type = type;
/************************************************************************************************************************/
/// <summary>
/// Should the label and <see cref="TypeSelectionButton"/>
/// be drawn on a separate line before the field's regular GUI?
/// </summary>
public bool SeparateHeader { get; set; }
/************************************************************************************************************************/
private static readonly Dictionary<Type, PolymorphicDrawerDetails>
TypeToDetails = new();
/// <summary>Gathers all instances of this attribute in all currently loaded assemblies.</summary>
static PolymorphicDrawerDetails()
{
var assemblies = AppDomain.CurrentDomain.GetAssemblies();
for (int iAssembly = 0; iAssembly < assemblies.Length; iAssembly++)
{
var assembly = assemblies[iAssembly];
if (!assembly.IsDefined(typeof(PolymorphicDrawerDetails), false))
continue;
var attributes = assemblies[iAssembly].GetCustomAttributes(typeof(PolymorphicDrawerDetails), false);
for (int iAttribute = 0; iAttribute < attributes.Length; iAttribute++)
{
var attribute = (PolymorphicDrawerDetails)attributes[iAttribute];
TypeToDetails.Add(attribute.Type, attribute);
}
}
}
/************************************************************************************************************************/
/// <summary>
/// Returns the <see cref="PolymorphicDrawerDetails"/> associated with the `type` or any of its base types.
/// Returns <c>null</c> if none of them have any details.
/// </summary>
public static PolymorphicDrawerDetails Get(Type type)
{
if (TypeToDetails.TryGetValue(type, out var details))
return details;
if (type.BaseType != null)
details = Get(type.BaseType);
else
details = Default;
TypeToDetails.Add(type, details);
return details;
}
/// <summary>
/// Returns the <see cref="PolymorphicDrawerDetails"/> associated with the `obj` or any of its base types.
/// Returns <c>null</c> if none of them have any details.
/// </summary>
public static PolymorphicDrawerDetails Get(object obj)
=> obj == null
? Default
: Get(obj.GetType());
/************************************************************************************************************************/
}
}
#endif