using UnityEngine; using UnityEngine.Serialization; using System; using System.Collections; using System.Collections.Generic; namespace Fungus { /** * The Sequence class has been renamed to Block to be more descriptive. */ [ExecuteInEditMode] [RequireComponent(typeof(Flowchart))] [AddComponentMenu("")] [Obsolete("Use Block class instead")] public class Sequence : Block {} [ExecuteInEditMode] [RequireComponent(typeof(Flowchart))] [AddComponentMenu("")] public class Block : Node { [FormerlySerializedAs("sequenceName")] public string blockName = "New Block"; [TextArea(2, 5)] [Tooltip("Description text to display under the block node")] public string description = ""; [Tooltip("Slow down execution in the editor to make it easier to visualise program flow")] public bool runSlowInEditor = true; public EventHandler eventHandler; [HideInInspector] [System.NonSerialized] public Command activeCommand; // Index of last command executed before the current one // -1 indicates no previous command [HideInInspector] [System.NonSerialized] public int previousActiveCommandIndex = -1; [HideInInspector] [System.NonSerialized] public float executingIconTimer; [HideInInspector] public List commandList = new List(); protected int executionCount; protected virtual void Awake() { // Give each child command a reference back to its parent block // and tell each command its index in the list. int index = 0; foreach (Command command in commandList) { command.parentBlock = this; command.commandIndex = index++; } } #if UNITY_EDITOR // The user can modify the command list order while playing in the editor, // so we keep the command indices updated every frame. There's no need to // do this in player builds so we compile this bit out for those builds. void Update() { int index = 0; foreach (Command command in commandList) { if (command == null) // Null entry will be deleted automatically later { continue; } command.commandIndex = index++; } } #endif public virtual Flowchart GetFlowchart() { Flowchart flowchart = GetComponent(); if (flowchart == null) { // Legacy support for earlier system where Blocks were children of the Flowchart if (transform.parent != null) { flowchart = transform.parent.GetComponent(); } } return flowchart; } public virtual bool HasError() { foreach (Command command in commandList) { if (command.errorMessage.Length > 0) { return true; } } return false; } public virtual bool IsExecuting() { Flowchart flowchart = GetFlowchart(); if (flowchart == null) { return false; } return (activeCommand != null); } public virtual int GetExecutionCount() { return executionCount; } public virtual void ExecuteCommand(int commandIndex) { if (activeCommand == null) { previousActiveCommandIndex = -1; } else { previousActiveCommandIndex = activeCommand.commandIndex; } if (commandIndex >= commandList.Count) { Stop(); return; } if (commandIndex == 0) { executionCount++; } Flowchart flowchart = GetFlowchart(); // Skip disabled commands, comments and labels while (commandIndex < commandList.Count && (!commandList[commandIndex].enabled || commandList[commandIndex].GetType() == typeof(Comment) || commandList[commandIndex].GetType() == typeof(Label))) { commandIndex = commandList[commandIndex].commandIndex + 1; } if (commandIndex >= commandList.Count) { Stop(); return; } Command nextCommand = commandList[commandIndex]; activeCommand = null; executingIconTimer = 0.5f; if (nextCommand == null) { Stop(); } else { if (flowchart.gameObject.activeInHierarchy) { // Auto select a command in some situations if ((flowchart.selectedCommands.Count == 0 && commandIndex == 0) || (flowchart.selectedCommands.Count == 1 && flowchart.selectedCommands[0].commandIndex == previousActiveCommandIndex)) { flowchart.ClearSelectedCommands(); flowchart.AddSelectedCommand(nextCommand); } if (runSlowInEditor && nextCommand.RunSlowInEditor()) { StartCoroutine(ExecuteAfterDelay(nextCommand, flowchart.runSlowDuration)); } else { activeCommand = nextCommand; nextCommand.Execute(); } } } } IEnumerator ExecuteAfterDelay(Command nextCommand, float delay) { activeCommand = nextCommand; yield return new WaitForSeconds(delay); nextCommand.Execute(); } public virtual void Stop() { Flowchart flowchart = GetFlowchart(); if (flowchart == null) { return; } activeCommand = null; flowchart.ClearSelectedCommands(); } public virtual List GetConnectedBlocks() { List connectedBlocks = new List(); foreach (Command command in commandList) { if (command != null) { command.GetConnectedBlocks(ref connectedBlocks); } } return connectedBlocks; } public virtual System.Type GetPreviousActiveCommandType() { if (previousActiveCommandIndex >= 0 && previousActiveCommandIndex < commandList.Count) { return commandList[previousActiveCommandIndex].GetType(); } return null; } } }