StateMachine1.StateSelector.cs 3.4 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283
  1. // Animancer // https://kybernetik.com.au/animancer // Copyright 2018-2024 Kybernetik //
  2. using System.Collections.Generic;
  3. namespace Animancer.FSM
  4. {
  5. /// <summary>An object with a <see cref="Priority"/>.</summary>
  6. /// <remarks>
  7. /// <strong>Documentation:</strong>
  8. /// <see href="https://kybernetik.com.au/animancer/docs/manual/fsm/utilities#state-selectors">
  9. /// State Selectors</see>
  10. /// </remarks>
  11. /// https://kybernetik.com.au/animancer/api/Animancer.FSM/IPrioritizable
  12. ///
  13. public interface IPrioritizable : IState
  14. {
  15. float Priority { get; }
  16. }
  17. /************************************************************************************************************************/
  18. public partial class StateMachine<TState>
  19. {
  20. /// <summary>A prioritised list of potential states for a <see cref="StateMachine{TState}"/> to enter.</summary>
  21. ///
  22. /// <remarks>
  23. /// <strong>Documentation:</strong>
  24. /// <see href="https://kybernetik.com.au/animancer/docs/manual/fsm#state-selectors">
  25. /// State Selectors</see>
  26. /// <para></para>
  27. /// <strong>Example:</strong><code>
  28. /// public StateMachine&lt;CharacterState&gt; stateMachine;
  29. /// public CharacterState run;
  30. /// public CharacterState idle;
  31. ///
  32. /// private readonly StateMachine&lt;CharacterState&gt;.StateSelector
  33. /// Selector = new();
  34. ///
  35. /// private void Awake()
  36. /// {
  37. /// Selector.Add(1, run);
  38. /// Selector.Add(0, idle);
  39. /// }
  40. ///
  41. /// public void RunOrIdle()
  42. /// {
  43. /// stateMachine.TrySetState(Selector.Values);
  44. /// // The "run" state has the highest priority so this will enter it if "run.CanEnterState" returns true.
  45. /// // Otherwise if "idle.CanEnterState" returns true it will enter that state instead.
  46. /// // If neither allows the transition, nothing happens and "stateMachine.TrySetState" returns false.
  47. /// }
  48. /// </code></remarks>
  49. ///
  50. /// https://kybernetik.com.au/animancer/api/Animancer.FSM/StateSelector
  51. ///
  52. public class StateSelector : SortedList<float, TState>
  53. {
  54. public StateSelector() : base(ReverseComparer<float>.Instance) { }
  55. /// <summary>Adds the `state` to this selector with its <see cref="IPrioritizable.Priority"/>.</summary>
  56. public void Add<TPrioritizable>(TPrioritizable state)
  57. where TPrioritizable : TState, IPrioritizable
  58. => Add(state.Priority, state);
  59. }
  60. }
  61. /************************************************************************************************************************/
  62. /// <summary>An <see cref="IComparer{T}"/> which reverses the default comparison.</summary>
  63. /// https://kybernetik.com.au/animancer/api/Animancer.FSM/ReverseComparer_1
  64. public class ReverseComparer<T> : IComparer<T>
  65. {
  66. /// <summary>The singleton instance.</summary>
  67. public static readonly ReverseComparer<T> Instance = new();
  68. /// <summary>No need to let users create other instances.</summary>
  69. private ReverseComparer() { }
  70. /// <summary>Uses <see cref="Comparer{T}.Default"/> with the parameters swapped.</summary>
  71. public int Compare(T x, T y) => Comparer<T>.Default.Compare(y, x);
  72. }
  73. }