Sin descripción
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

StateGraph.cs 4.5KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using UnityEngine;
  5. namespace Unity.VisualScripting
  6. {
  7. [SerializationVersion("A")]
  8. public sealed class StateGraph : Graph, IGraphEventListener
  9. {
  10. public StateGraph()
  11. {
  12. states = new GraphElementCollection<IState>(this);
  13. transitions = new GraphConnectionCollection<IStateTransition, IState, IState>(this);
  14. groups = new GraphElementCollection<GraphGroup>(this);
  15. sticky = new GraphElementCollection<StickyNote>(this);
  16. elements.Include(states);
  17. elements.Include(transitions);
  18. elements.Include(groups);
  19. elements.Include(sticky);
  20. }
  21. public override IGraphData CreateData()
  22. {
  23. return new StateGraphData(this);
  24. }
  25. public void StartListening(GraphStack stack)
  26. {
  27. stack.GetGraphData<StateGraphData>().isListening = true;
  28. var activeStates = GetActiveStatesNoAlloc(stack);
  29. foreach (var state in activeStates)
  30. {
  31. (state as IGraphEventListener)?.StartListening(stack);
  32. }
  33. activeStates.Free();
  34. }
  35. public void StopListening(GraphStack stack)
  36. {
  37. var activeStates = GetActiveStatesNoAlloc(stack);
  38. foreach (var state in activeStates)
  39. {
  40. (state as IGraphEventListener)?.StopListening(stack);
  41. }
  42. activeStates.Free();
  43. stack.GetGraphData<StateGraphData>().isListening = false;
  44. }
  45. public bool IsListening(GraphPointer pointer)
  46. {
  47. return pointer.GetGraphData<StateGraphData>().isListening;
  48. }
  49. #region Elements
  50. [DoNotSerialize]
  51. public GraphElementCollection<IState> states { get; internal set; }
  52. [DoNotSerialize]
  53. public GraphConnectionCollection<IStateTransition, IState, IState> transitions { get; internal set; }
  54. [DoNotSerialize]
  55. public GraphElementCollection<GraphGroup> groups { get; internal set; }
  56. [DoNotSerialize]
  57. public GraphElementCollection<StickyNote> sticky { get; private set; }
  58. #endregion
  59. #region Lifecycle
  60. // Active state detection happens twice:
  61. //
  62. // 1. Before the enumeration, because any state
  63. // that becomes active during an update shouldn't
  64. // be updated until the next update
  65. //
  66. // 2. Inside the update method, because a state
  67. // that was active during enumeration and no longer
  68. // is shouldn't be updated.
  69. private HashSet<IState> GetActiveStatesNoAlloc(GraphPointer pointer)
  70. {
  71. var activeStates = HashSetPool<IState>.New();
  72. foreach (var state in states)
  73. {
  74. var stateData = pointer.GetElementData<State.Data>(state);
  75. if (stateData.isActive)
  76. {
  77. activeStates.Add(state);
  78. }
  79. }
  80. return activeStates;
  81. }
  82. public void Start(Flow flow)
  83. {
  84. flow.stack.GetGraphData<StateGraphData>().isListening = true;
  85. foreach (var state in states.Where(s => s.isStart))
  86. {
  87. try
  88. {
  89. state.OnEnter(flow, StateEnterReason.Start);
  90. }
  91. catch (Exception ex)
  92. {
  93. state.HandleException(flow.stack, ex);
  94. throw;
  95. }
  96. }
  97. }
  98. public void Stop(Flow flow)
  99. {
  100. var activeStates = GetActiveStatesNoAlloc(flow.stack);
  101. foreach (var state in activeStates)
  102. {
  103. try
  104. {
  105. state.OnExit(flow, StateExitReason.Stop);
  106. }
  107. catch (Exception ex)
  108. {
  109. state.HandleException(flow.stack, ex);
  110. throw;
  111. }
  112. }
  113. activeStates.Free();
  114. flow.stack.GetGraphData<StateGraphData>().isListening = false;
  115. }
  116. #endregion
  117. public static StateGraph WithStart()
  118. {
  119. var stateGraph = new StateGraph();
  120. var startState = FlowState.WithEnterUpdateExit();
  121. startState.isStart = true;
  122. startState.nest.embed.title = "Start";
  123. startState.position = new Vector2(-86, -15);
  124. stateGraph.states.Add(startState);
  125. return stateGraph;
  126. }
  127. }
  128. }