// Note on transition timing: The outgoing transition will trigger on the update() after the task completes. It may // be desired that the transition is triggered 'manually' as soon as the task completes. public static ITransitionBuilder BindAsyncLamdaAndTransitionOnDone(this IStateConstruction state, Func <UniTask> task) { // If the state is entered then exited then entered again before the first UniTask completes, // we need a way to have the first task not cause a transition. Use a simple counter. uint execCounter = 0; bool transitionShouldTrigger = false; state.AddEntryAction(async() => { transitionShouldTrigger = false; execCounter++; uint thisTasksCounter = execCounter; await task(); if (thisTasksCounter == execCounter) { transitionShouldTrigger = true; } }); var t = new MultiTransition(state.Graph, state.ToRuntimeState()); state.AddTransition(t); t.When(() => transitionShouldTrigger); return(t); }
public FluentBuilder State(string name) { NoTokenStateConstruction newState = m_graph.NewState(name); m_stateInContext = newState; if (m_states.ContainsKey(name)) { Debug.LogError("Hapn FluentBuilder: multiple states declared with same name."); } m_states[name] = newState; if (m_waitingTransitions.ContainsKey(name)) { foreach (IBaseTransitionBuilder t in m_waitingTransitions[name]) { // Transitions with- and without-tokens can transition to no-token states. t.To(newState); } m_waitingTransitions.Remove(name); } LinkWaitingThingsToNewState(name, newState); AssignTransitionsAndClear(newState); return(this); }
private void LinkWaitingThingsToNewState(string name, IStateConstruction state) { if (m_waitingStateGroups.ContainsKey(name)) { foreach (var sg in m_waitingStateGroups[name]) { state.AddGroup(sg); } m_waitingTransitions.Remove(name); } }
public FluentBuilder <T> State <T>(string name) { WithTokenStateConstruction <T> newState = m_graph.NewState <T>(name); m_stateInContext = newState; if (m_states.ContainsKey(name)) { Debug.LogError("Hapn Fluent Builder: multiple states declared with same name."); } m_states[name] = newState; if (m_waitingTransitions.ContainsKey(name)) { foreach (IBaseTransitionBuilder t in m_waitingTransitions[name]) { if (t is ITransitionBuilder <T> typedT) { typedT.To(newState); } else { Debug.LogErrorFormat("FluentBuilder: State '{0}' that requires token created, but transitions-without-tokens were awaiting a state with this name.", name); } } m_waitingTransitions.Remove(name); } LinkWaitingThingsToNewState(name, newState); foreach (var t in m_transitionsToNextState) { var castTransition = t as ITransitionBuilder <T>; if (t == null) { throw new InvalidOperationException("A transition was waiting to be connected to a state with a different token type (or no token) compared to the new state"); } castTransition.To(newState); } m_transitionsToNextState.Clear(); return(new FluentBuilder <T>(this, newState)); }
public static void BindEaseAnimation(this IStateConstruction state, float duration, Func <(Vector3, Vector3)> initValues, Action <Vector3> output)
public FluentBuilder(Graph g) { m_graph = g; m_stateInContext = null; }
public static (ITransitionBuilder success, ITransitionBuilder <Exception> fail) BindAsyncLamdaAndTransitionByResult(this IStateConstruction state, Func <UniTask <bool> > task) { // If the state is entered then exited then entered again before the first UniTask completes, // we need a way to have the first task not cause a transition. Avoid alloc by using a simple counter. uint execCounter = 0; bool successTransitionShouldTrigger = false; Exception e = null; state.AddEntryAction(async() => { successTransitionShouldTrigger = false; e = null; execCounter++; uint thisTasksCounter = execCounter; try { bool result = await task(); if (thisTasksCounter == execCounter) { if (result) { successTransitionShouldTrigger = true; } else { e = new Exception("Test returned false"); } } } catch (Exception eInstance) { Debug.LogException(eInstance); if (thisTasksCounter == execCounter) { e = eInstance; } } }); var tFail = new MultiTransition <Exception>(state.Graph, state.ToRuntimeState()); state.AddTransition(tFail); var tSuccess = new MultiTransition(state.Graph, state.ToRuntimeState()); state.AddTransition(tSuccess); tSuccess.When(() => successTransitionShouldTrigger); tFail.When(() => e); return(tSuccess, tFail); }
public static (ITransitionBuilder success, ITransitionBuilder <Exception> fail) BindAsyncLamdaAndTransitionByResult(this IStateConstruction state, Func <UniTask> task) { return(state.BindAsyncLamdaAndTransitionByResult(() => task().ContinueWith(() => true))); }