StateMachine2.WithDefault.cs 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142
  1. // Animancer // https://kybernetik.com.au/animancer // Copyright 2018-2024 Kybernetik //
  2. using System;
  3. using UnityEngine;
  4. namespace Animancer.FSM
  5. {
  6. /// https://kybernetik.com.au/animancer/api/Animancer.FSM/StateMachine_2
  7. partial class StateMachine<TKey, TState>
  8. {
  9. /// <summary>A <see cref="StateMachine{TKey, TState}"/> with a <see cref="DefaultKey"/>.</summary>
  10. /// <remarks>
  11. /// See <see cref="InitializeAfterDeserialize"/> if using this class in a serialized field.
  12. /// <para></para>
  13. /// <strong>Documentation:</strong>
  14. /// <see href="https://kybernetik.com.au/animancer/docs/manual/fsm/changing-states#default-states">
  15. /// Default States</see>
  16. /// </remarks>
  17. /// https://kybernetik.com.au/animancer/api/Animancer.FSM/WithDefault
  18. ///
  19. [Serializable]
  20. public new class WithDefault : StateMachine<TKey, TState>
  21. {
  22. /************************************************************************************************************************/
  23. [SerializeField]
  24. private TKey _DefaultKey;
  25. /// <summary>The starting state and main state to return to when nothing else is active.</summary>
  26. /// <remarks>
  27. /// If the <see cref="CurrentState"/> is <c>null</c> when setting this value, it calls
  28. /// <see cref="ForceSetState(TKey)"/> to enter the specified state immediately.
  29. /// <para></para>
  30. /// For a character, this would typically be their <em>Idle</em> state.
  31. /// </remarks>
  32. public TKey DefaultKey
  33. {
  34. get => _DefaultKey;
  35. set
  36. {
  37. _DefaultKey = value;
  38. if (CurrentState == null && value != null)
  39. ForceSetState(value);
  40. }
  41. }
  42. /************************************************************************************************************************/
  43. /// <summary>Calls <see cref="ForceSetState(TKey)"/> with the <see cref="DefaultKey"/>.</summary>
  44. /// <remarks>This delegate is cached to avoid allocating garbage when used in Animancer Events.</remarks>
  45. public readonly Action ForceSetDefaultState;
  46. /************************************************************************************************************************/
  47. /// <summary>Creates a new <see cref="WithDefault"/>.</summary>
  48. public WithDefault()
  49. {
  50. // Silly C# doesn't allow instance delegates to be assigned using field initializers.
  51. ForceSetDefaultState = () => ForceSetState(_DefaultKey);
  52. }
  53. /************************************************************************************************************************/
  54. /// <summary>Creates a new <see cref="WithDefault"/> and sets the <see cref="DefaultKey"/>.</summary>
  55. public WithDefault(TKey defaultKey)
  56. : this()
  57. {
  58. _DefaultKey = defaultKey;
  59. ForceSetState(defaultKey);
  60. }
  61. /************************************************************************************************************************/
  62. /// <inheritdoc/>
  63. public override void InitializeAfterDeserialize()
  64. {
  65. if (CurrentState != null)
  66. {
  67. using (new KeyChange<TKey>(this, default, _DefaultKey))
  68. using (new StateChange<TState>(this, null, CurrentState))
  69. CurrentState.OnEnterState();
  70. }
  71. else
  72. {
  73. ForceSetState(_DefaultKey);
  74. }
  75. // Don't call the base method.
  76. }
  77. /************************************************************************************************************************/
  78. /// <summary>Attempts to enter the <see cref="DefaultKey"/> and returns true if successful.</summary>
  79. /// <remarks>
  80. /// This method returns true immediately if the specified <see cref="DefaultKey"/> is already the
  81. /// <see cref="CurrentKey"/>. To allow directly re-entering the same state, use
  82. /// <see cref="TryResetDefaultState"/> instead.
  83. /// </remarks>
  84. public TState TrySetDefaultState() => TrySetState(_DefaultKey);
  85. /************************************************************************************************************************/
  86. /// <summary>Attempts to enter the <see cref="DefaultKey"/> and returns true if successful.</summary>
  87. /// <remarks>
  88. /// This method does not check if the <see cref="DefaultKey"/> is already the <see cref="CurrentKey"/>.
  89. /// To do so, use <see cref="TrySetDefaultState"/> instead.
  90. /// </remarks>
  91. public TState TryResetDefaultState() => TryResetState(_DefaultKey);
  92. /************************************************************************************************************************/
  93. #if UNITY_EDITOR && UNITY_IMGUI
  94. /************************************************************************************************************************/
  95. /// <inheritdoc/>
  96. public override int GUILineCount => 2;
  97. /************************************************************************************************************************/
  98. /// <inheritdoc/>
  99. public override void DoGUI(ref Rect area)
  100. {
  101. area.height = UnityEditor.EditorGUIUtility.singleLineHeight;
  102. UnityEditor.EditorGUI.BeginChangeCheck();
  103. var state = StateMachineUtilities.DoGenericField(area, "Default Key", DefaultKey);
  104. if (UnityEditor.EditorGUI.EndChangeCheck())
  105. DefaultKey = state;
  106. StateMachineUtilities.NextVerticalArea(ref area);
  107. base.DoGUI(ref area);
  108. }
  109. /************************************************************************************************************************/
  110. #endif
  111. /************************************************************************************************************************/
  112. }
  113. }
  114. }