TryCreateTransitionAttribute.cs 3.4 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586
  1. // Animancer // https://kybernetik.com.au/animancer // Copyright 2018-2024 Kybernetik //
  2. using System;
  3. using System.Collections.Generic;
  4. using UnityEditor;
  5. using UnityEngine;
  6. using Object = UnityEngine.Object;
  7. namespace Animancer
  8. {
  9. /// <summary>Attribute for static methods which try to create a transition from an object.</summary>
  10. /// <remarks>
  11. /// The method signature must be:
  12. /// <c>static ITransitionDetailed TryCreateTransition(Object target)</c>
  13. /// </remarks>
  14. /// https://kybernetik.com.au/animancer/api/Animancer/TryCreateTransitionAttribute
  15. [AttributeUsage(AttributeTargets.Method)]
  16. public sealed class TryCreateTransitionAttribute : Attribute
  17. {
  18. /************************************************************************************************************************/
  19. #if UNITY_EDITOR
  20. /************************************************************************************************************************/
  21. private static List<Func<Object, ITransitionDetailed>> _Methods;
  22. /// <summary>[Editor-Only] Ensures that all methods with this attribute have been gathered.</summary>
  23. private static void InitializeMethods()
  24. {
  25. if (_Methods != null)
  26. return;
  27. _Methods = new();
  28. foreach (var method in TypeCache.GetMethodsWithAttribute<TryCreateTransitionAttribute>())
  29. {
  30. try
  31. {
  32. var func = Delegate.CreateDelegate(typeof(Func<Object, ITransitionDetailed>), method);
  33. _Methods.Add((Func<Object, ITransitionDetailed>)func);
  34. }
  35. catch (Exception exception)
  36. {
  37. Debug.LogError(
  38. $"Failed to create delegate for" +
  39. $" {method.DeclaringType.GetNameCS()}.{method.Name}," +
  40. $" it must take one {typeof(Object).FullName} parameter" +
  41. $" and return {typeof(ITransition).FullName}" +
  42. $": {exception}");
  43. }
  44. }
  45. }
  46. /************************************************************************************************************************/
  47. /// <summary>[Editor-Only] Tries to create an asset containing an appropriate transition for the `target`.</summary>
  48. public static TransitionAssetBase TryCreateTransitionAsset(Object target)
  49. {
  50. if (target is TransitionAssetBase asset)
  51. return asset;
  52. var assetType = TransitionAssetBase.CreateInstance;
  53. if (assetType == null)
  54. return null;
  55. InitializeMethods();
  56. for (int i = 0; i < _Methods.Count; i++)
  57. {
  58. var transition = _Methods[i](target);
  59. if (transition is not null)
  60. {
  61. var created = TransitionAssetBase.CreateInstance(transition);
  62. created.name = target.name;
  63. return created;
  64. }
  65. }
  66. return null;
  67. }
  68. /************************************************************************************************************************/
  69. #endif
  70. /************************************************************************************************************************/
  71. }
  72. }