public void GetEntered(ref HashSet <int> entered) { foreach (var d in destinations) { entered.UnionWith(statechart.GetSuperstates(d, GetScope())); } }
bool Step() { #if SC_PROFILE_SINGLE stopwatch.Start(); #endif // Preparations CTs.Clear(); entered.Clear(); exited.Clear(); active.Clear(); foreach (var s in status.b_configuration) { active.UnionWith(machine.GetSuperstates(s)); } #if SC_PROFILE_SINGLE stopwatch.Stop(); prepare.Accumulate(stopwatch); stopwatch.Reset(); stopwatch.Start(); #endif // Search Paths foreach (var s in status.b_configuration) { var next = machine.TryExit(s, status); if (next != (null, null)) { CTs.Add(new CT(machine, s, next.waypoints, next.destinations)); } } #if SC_PROFILE_SINGLE stopwatch.Stop(); search.Accumulate(stopwatch); stopwatch.Reset(); stopwatch.Start(); #endif // Validate Paths // Sort by scope high to low CTs.Sort(); // Remove conflicting paths by priority for (int i = 0; i < CTs.Count; i++) { if (active.IsSupersetOf(machine.GetSuperstates(CTs[i].GetSource()))) { generic.Clear(); CTs[i].GetExited(ref generic); active.ExceptWith(generic); exited.UnionWith(generic); generic.Clear(); CTs[i].GetEntered(ref generic); entered.UnionWith(generic); } else { CTs[i] = null; } } // Remove any so far untouched parallel regions which have been implicitly exited generic.Clear(); foreach (var act in active) { var ancestors = machine.GetSuperstates(act); ancestors.Reverse(); foreach (var a in ancestors) { if (!active.Contains(a)) { generic.UnionWith(machine.GetSuperstates(act, a)); break; } } } active.ExceptWith(generic); exited.UnionWith(generic); // Implicitly enter all so far untouched parallel regions generic.Clear(); foreach (var e in entered) { if (machine.GetNodeType(e) == Node.Type.Parallel) { generic.UnionWith(machine.GetNodeComponents(e)); } } generic.ExceptWith(active); generic.ExceptWith(entered); foreach (var r in generic) { var next = machine.TryEnter(r, status); if (next != (null, null)) { entered.UnionWith(next.destinations); } // else: ERROR (Limitation) } // Cleanup entered.ExceptWith(active); #if SC_PROFILE_SINGLE stopwatch.Stop(); validate.Accumulate(stopwatch); stopwatch.Reset(); stopwatch.Start(); #endif // Execute Step // Update configuration status.b_configuration.ExceptWith(ExtractAtomic(exited)); status.b_configuration.UnionWith(ExtractAtomic(entered)); // Execute actions DoActions(exited, Action.Type.EXIT); DoActions(active, Action.Type.STAY); foreach (var p in CTs) { if (p != null) { DoActions(p.GetWaypoints()); } } DoActions(entered, Action.Type.ENTRY); // Clear and add events for next step status.events.Clear(); foreach (var s in exited) { status.events.Add(new SCEvent("exit." + machine.GetNodeName(s))); } foreach (var s in entered) { status.events.Add(new SCEvent("enter." + machine.GetNodeName(s))); } #if SC_PROFILE_SINGLE stopwatch.Stop(); execute.Accumulate(stopwatch); stopwatch.Reset(); if (prepare.SampleCount % 1000 == 0) // Reduce clutter { Debug.Log( "Prepare: " + prepare.GetStatistics(AccumulatedTime.TimeUnit.µs) + "\nSearch: " + search.GetStatistics(AccumulatedTime.TimeUnit.µs) + "\nValidate: " + validate.GetStatistics(AccumulatedTime.TimeUnit.µs) + "\nExecute: " + execute.GetStatistics(AccumulatedTime.TimeUnit.µs)); } #endif #if SC_LOG_FUNCTIONALITY StringBuilder builder = new StringBuilder(this.ToString()); builder.Append(" is now in\n"); builder.Append(status.ToString()); builder.Append("\nafter executing\n"); foreach (var ct in CTs) { if (ct != null) { builder.Append(ct); builder.Append("\n\t"); } } Debug.Log(builder.ToString()); #endif #if SC_DEBUG if (!machine.IsValid(status)) { StringBuilder sb = new StringBuilder("Invalid configuration in instance "); sb.Append(this); sb.Append(":\n\t"); sb.Append(status.ToString()); sb.Append("\nIt occured while executing:"); foreach (var ct in CTs) { if (ct != null) { sb.Append(ct); sb.Append("\n\t"); } } Debug.LogError(sb.ToString()); } #endif return(exited.Count > 0 || entered.Count > 0); }