/// <summary> /// Pushes a list of nodes as a new stack frame onto the call stack. /// </summary> /// <param name="label"> /// The list of nodes to push onto the call stack. /// </param> public void Inject(List <Node> nodes) { if (nodes == null) { throw new ArgumentNullException(nameof(nodes)); } Stack.Push(new StackFrame(nodes)); Yield = null; Continue(); }
public Rumor(SerializationInfo info, StreamingContext context) { Nodes = info.GetValue <Dictionary <string, List <Node> > >("nodes"); State = info.GetValue <RumorState>("state"); Scope = info.GetValue <RumorScope>("scope"); Stack = info.GetValue <Stack <StackFrame> >("stack"); FinishCount = info.GetValue <int>("finishCount"); CancelCount = info.GetValue <int>("cancelCount"); Yield = info.GetValue <Yield>("yield"); AutoAdvance = info.GetValue <float>("autoAdvance"); Bindings = new RumorBindings(); }
/// <summary> /// This should be called after any operation that may allow execution /// to continue. /// </summary> private void Continue() { // There is nothing to do if (Stack.Count == 0) { return; } while (Stack.Count > 0) { // Check if the current yield is finished if (Yield != null) { if (Yield.Finished == true) { Yield = null; } // Auto-advance, if applicable else if (Yield is ForAdvance && AutoAdvance >= 0 && Yield.Elapsed >= AutoAdvance) { Yield = null; } // Wait for the current yield to finish else { return; } } // Check if this frame is complete var frame = Stack.Peek(); if (frame.Done) { Stack.Pop(); continue; } // Execute the next node in the stack frame Yield = frame.Execute(this); if (Yield is ForAdvance && AutoAdvance != 0) { OnWaitForAdvance?.Invoke(); return; } else if (Yield is ForChoose) { OnWaitForChoose?.Invoke(State.GetChoices()); OnWaitForChooseTimeout?.Invoke( State.GetChoices(), (Yield as ForChoose).Timeout ); return; } else if (Yield is ForSeconds) { return; } } OnFinish?.Invoke(); FinishCount++; }