PolymorphicDrawerDetails.cs 3.9 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798
  1. // Animancer // https://kybernetik.com.au/animancer // Copyright 2018-2024 Kybernetik //
  2. #if UNITY_EDITOR
  3. using Animancer.Editor;
  4. using System;
  5. using System.Collections.Generic;
  6. namespace Animancer.Editor
  7. {
  8. /// <summary>[Editor-Only]
  9. /// An assembly attribute for configuring how the <see cref="PolymorphicDrawer"/>
  10. /// displays a particular type.
  11. /// </summary>
  12. [AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)]
  13. public sealed class PolymorphicDrawerDetails : Attribute
  14. {
  15. /************************************************************************************************************************/
  16. /// <summary>A default instance.</summary>
  17. public static readonly PolymorphicDrawerDetails
  18. Default = new(null);
  19. /************************************************************************************************************************/
  20. /// <summary>The <see cref="System.Type"/> this attribute applies to.</summary>
  21. public readonly Type Type;
  22. /// <summary>Creates a new <see cref="PolymorphicDrawerDetails"/>.</summary>
  23. public PolymorphicDrawerDetails(Type type)
  24. => Type = type;
  25. /************************************************************************************************************************/
  26. /// <summary>
  27. /// Should the label and <see cref="TypeSelectionButton"/>
  28. /// be drawn on a separate line before the field's regular GUI?
  29. /// </summary>
  30. public bool SeparateHeader { get; set; }
  31. /************************************************************************************************************************/
  32. private static readonly Dictionary<Type, PolymorphicDrawerDetails>
  33. TypeToDetails = new();
  34. /// <summary>Gathers all instances of this attribute in all currently loaded assemblies.</summary>
  35. static PolymorphicDrawerDetails()
  36. {
  37. var assemblies = AppDomain.CurrentDomain.GetAssemblies();
  38. for (int iAssembly = 0; iAssembly < assemblies.Length; iAssembly++)
  39. {
  40. var assembly = assemblies[iAssembly];
  41. if (!assembly.IsDefined(typeof(PolymorphicDrawerDetails), false))
  42. continue;
  43. var attributes = assemblies[iAssembly].GetCustomAttributes(typeof(PolymorphicDrawerDetails), false);
  44. for (int iAttribute = 0; iAttribute < attributes.Length; iAttribute++)
  45. {
  46. var attribute = (PolymorphicDrawerDetails)attributes[iAttribute];
  47. TypeToDetails.Add(attribute.Type, attribute);
  48. }
  49. }
  50. }
  51. /************************************************************************************************************************/
  52. /// <summary>
  53. /// Returns the <see cref="PolymorphicDrawerDetails"/> associated with the `type` or any of its base types.
  54. /// Returns <c>null</c> if none of them have any details.
  55. /// </summary>
  56. public static PolymorphicDrawerDetails Get(Type type)
  57. {
  58. if (TypeToDetails.TryGetValue(type, out var details))
  59. return details;
  60. if (type.BaseType != null)
  61. details = Get(type.BaseType);
  62. else
  63. details = Default;
  64. TypeToDetails.Add(type, details);
  65. return details;
  66. }
  67. /// <summary>
  68. /// Returns the <see cref="PolymorphicDrawerDetails"/> associated with the `obj` or any of its base types.
  69. /// Returns <c>null</c> if none of them have any details.
  70. /// </summary>
  71. public static PolymorphicDrawerDetails Get(object obj)
  72. => obj == null
  73. ? Default
  74. : Get(obj.GetType());
  75. /************************************************************************************************************************/
  76. }
  77. }
  78. #endif