StateMachine1.StateSelector.cs 3.3 KB

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