diff --git a/Assets/Fungus/Scripts/Components/Block.cs b/Assets/Fungus/Scripts/Components/Block.cs index 41278dfd..9be9693f 100644 --- a/Assets/Fungus/Scripts/Components/Block.cs +++ b/Assets/Fungus/Scripts/Components/Block.cs @@ -213,6 +213,7 @@ namespace Fungus var flowchart = GetFlowchart(); executionState = ExecutionState.Executing; + BlockSignals.DoBlockStart(this); #if UNITY_EDITOR // Select the executing block & the first command @@ -278,6 +279,7 @@ namespace Fungus // This icon timer is managed by the FlowchartWindow class, but we also need to // set it here in case a command starts and finishes execution before the next window update. command.ExecutingIconTimer = Time.realtimeSinceStartup + FungusConstants.ExecutingIconFadeTime; + BlockSignals.DoCommandExecute(this, command, i, commandList.Count); command.Execute(); // Wait until the executing command sets another command to jump to via Command.Continue() @@ -298,6 +300,7 @@ namespace Fungus executionState = ExecutionState.Idle; activeCommand = null; + BlockSignals.DoBlockEnd(this); if (onComplete != null) { diff --git a/Assets/Fungus/Scripts/Signals/BlockSignals.cs b/Assets/Fungus/Scripts/Signals/BlockSignals.cs new file mode 100644 index 00000000..0492d850 --- /dev/null +++ b/Assets/Fungus/Scripts/Signals/BlockSignals.cs @@ -0,0 +1,36 @@ +using Fungus.Utils; + +namespace Fungus +{ + /// + /// Block event signalling system. + /// You can use this to be notified about various events in the Block execution process. + /// + public static class BlockSignals + { + #region Public members + + /// + /// BlockStart signal. Sent when the Block starts execution. + /// + public static event BlockStartHandler OnBlockStart; + public delegate void BlockStartHandler(Block block); + public static void DoBlockStart(Block block) { if (OnBlockStart != null) OnBlockStart(block); } + + /// + /// BlockEnd signal. Sent when the Block ends execution. + /// + public static event BlockEndHandler OnBlockEnd; + public delegate void BlockEndHandler(Block block); + public static void DoBlockEnd(Block block) { if (OnBlockEnd != null) OnBlockEnd(block); } + + /// + /// CommandExecute signal. Sent just before a Command in a Block executes. + /// + public static event CommandExecuteHandler OnCommandExecute; + public delegate void CommandExecuteHandler(Block block, Command command, int commandIndex, int maxCommandIndex); + public static void DoCommandExecute(Block block, Command command, int commandIndex, int maxCommandIndex) { if (OnCommandExecute != null) OnCommandExecute(block, command, commandIndex, maxCommandIndex); } + + #endregion + } +} diff --git a/Assets/Fungus/Scripts/Signals/BlockSignals.cs.meta b/Assets/Fungus/Scripts/Signals/BlockSignals.cs.meta new file mode 100644 index 00000000..d3c70701 --- /dev/null +++ b/Assets/Fungus/Scripts/Signals/BlockSignals.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 12109e10b0f034bbab8a7a5d700bc070 +timeCreated: 1474988491 +licenseType: Free +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Fungus/Scripts/Signals/WriterSignals.cs b/Assets/Fungus/Scripts/Signals/WriterSignals.cs index 01b1a67d..ff9680d5 100644 --- a/Assets/Fungus/Scripts/Signals/WriterSignals.cs +++ b/Assets/Fungus/Scripts/Signals/WriterSignals.cs @@ -15,22 +15,22 @@ namespace Fungus /// /// TextTagToken signal. Sent for each unique token when writing text. /// - public delegate void TextTagTokenHandler(Writer writer, TextTagToken token, int index, int maxIndex); public static event TextTagTokenHandler OnTextTagToken; + public delegate void TextTagTokenHandler(Writer writer, TextTagToken token, int index, int maxIndex); public static void DoTextTagToken(Writer writer, TextTagToken token, int index, int maxIndex) { if(OnTextTagToken != null) OnTextTagToken(writer, token, index, maxIndex); } /// /// WriterState signal. Sent when the writer changes state. /// - public delegate void WriterStateHandler(Writer writer, WriterState writerState); public static event WriterStateHandler OnWriterState; + public delegate void WriterStateHandler(Writer writer, WriterState writerState); public static void DoWriterState(Writer writer, WriterState writerState) { if (OnWriterState != null) OnWriterState(writer, writerState); } /// /// WriterInput signal. Sent when the writer receives player input. /// - public delegate void WriterInputHandler(Writer writer); public static event WriterInputHandler OnWriterInput; + public delegate void WriterInputHandler(Writer writer); public static void DoWriterInput(Writer writer) { if (OnWriterInput != null) OnWriterInput(writer); } /// diff --git a/Assets/Tests/Signals/BlockSignalsTester.cs b/Assets/Tests/Signals/BlockSignalsTester.cs new file mode 100644 index 00000000..754d9a26 --- /dev/null +++ b/Assets/Tests/Signals/BlockSignalsTester.cs @@ -0,0 +1,53 @@ +using UnityEngine; +using System.Collections; +using Fungus.Commands; + +namespace Fungus +{ + /// + /// Checks if Block signals are being sent correctly. + /// + [AddComponentMenu("")] + public class BlockSignalsTester : MonoBehaviour + { + bool started = false; + bool commandExecuted = false; + + void OnEnable() + { + BlockSignals.OnBlockStart += OnBlockStart; + BlockSignals.OnBlockEnd += OnBlockEnd; + BlockSignals.OnCommandExecute += OnCommandExecute; + } + + void OnDisable() + { + BlockSignals.OnBlockStart -= OnBlockStart; + BlockSignals.OnBlockEnd -= OnBlockEnd; + BlockSignals.OnCommandExecute -= OnCommandExecute; + } + + void OnBlockStart(Block block) + { + IntegrationTest.Assert(block.BlockName == "Start"); + + started = true; + } + + void OnBlockEnd(Block block) + { + IntegrationTest.Assert(started); + IntegrationTest.Assert(commandExecuted); + + IntegrationTest.Pass(); + } + + void OnCommandExecute(Block block, Command command, int commandIndex, int maxCommandIndex) + { + IntegrationTest.Assert(commandIndex == 0); + IntegrationTest.Assert(maxCommandIndex == 1); + IntegrationTest.Assert(command.GetType() == typeof(Wait)); + commandExecuted = true; + } + } +} \ No newline at end of file diff --git a/Assets/Tests/Signals/BlockSignalsTester.cs.meta b/Assets/Tests/Signals/BlockSignalsTester.cs.meta new file mode 100644 index 00000000..6fe2ffc5 --- /dev/null +++ b/Assets/Tests/Signals/BlockSignalsTester.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 5d396ca39a0454e2ca06d4aad7c5706c +timeCreated: 1474988463 +licenseType: Free +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Tests/Signals/SignalsTests.unity b/Assets/Tests/Signals/SignalsTests.unity index c5fba771..c368d289 100644 --- a/Assets/Tests/Signals/SignalsTests.unity +++ b/Assets/Tests/Signals/SignalsTests.unity @@ -264,7 +264,7 @@ MonoBehaviour: m_Script: {fileID: 11500000, guid: 61dddfdc5e0e44ca298d8f46f7f5a915, type: 3} m_Name: m_EditorClassIdentifier: - selectedFlowchart: {fileID: 411939904} + selectedFlowchart: {fileID: 330763419} --- !u!4 &286067097 Transform: m_ObjectHideFlags: 1 @@ -278,6 +278,129 @@ Transform: m_Children: [] m_Father: {fileID: 0} m_RootOrder: 1 +--- !u!1 &330763414 +GameObject: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 142980, guid: 5e7fbc8d4eb714b279eeeef2262c1e1a, type: 2} + m_PrefabInternal: {fileID: 0} + serializedVersion: 4 + m_Component: + - 4: {fileID: 330763415} + - 114: {fileID: 330763419} + - 114: {fileID: 330763418} + - 114: {fileID: 330763417} + - 114: {fileID: 330763416} + m_Layer: 0 + m_Name: Flowchart + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &330763415 +Transform: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 467082, guid: 5e7fbc8d4eb714b279eeeef2262c1e1a, type: 2} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 330763414} + m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_Children: [] + m_Father: {fileID: 467145139} + m_RootOrder: 0 +--- !u!114 &330763416 +MonoBehaviour: + m_ObjectHideFlags: 2 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 330763414} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 3315ad2ebb85443909a1203d56d9344e, type: 3} + m_Name: + m_EditorClassIdentifier: + itemId: 1 + indentLevel: 0 + _duration: + floatRef: {fileID: 0} + floatVal: 1 + durationOLD: 0 +--- !u!114 &330763417 +MonoBehaviour: + m_ObjectHideFlags: 2 + m_PrefabParentObject: {fileID: 11462346, guid: 5e7fbc8d4eb714b279eeeef2262c1e1a, + type: 2} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 330763414} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: d2f6487d21a03404cb21b245f0242e79, type: 3} + m_Name: + m_EditorClassIdentifier: + parentBlock: {fileID: 330763418} +--- !u!114 &330763418 +MonoBehaviour: + m_ObjectHideFlags: 2 + m_PrefabParentObject: {fileID: 11433304, guid: 5e7fbc8d4eb714b279eeeef2262c1e1a, + type: 2} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 330763414} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 3d3d73aef2cfc4f51abf34ac00241f60, type: 3} + m_Name: + m_EditorClassIdentifier: + nodeRect: + serializedVersion: 2 + x: 67 + y: 70 + width: 120 + height: 40 + itemId: 0 + blockName: Start + description: + eventHandler: {fileID: 330763417} + commandList: + - {fileID: 330763416} +--- !u!114 &330763419 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 11430050, guid: 5e7fbc8d4eb714b279eeeef2262c1e1a, + type: 2} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 330763414} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 7a334fe2ffb574b3583ff3b18b4792d3, type: 3} + m_Name: + m_EditorClassIdentifier: + version: 1 + scrollPos: {x: 0, y: 0} + variablesScrollPos: {x: 0, y: 0} + variablesExpanded: 1 + blockViewHeight: 400 + zoom: 1 + scrollViewRect: + serializedVersion: 2 + x: -343 + y: -340 + width: 1114 + height: 859 + selectedBlock: {fileID: 330763418} + selectedCommands: [] + variables: [] + description: + stepPause: 0 + colorCommands: 1 + hideComponents: 1 + saveSelection: 1 + localizationId: + showLineNumbers: 0 + hideCommands: [] + luaEnvironment: {fileID: 0} + luaBindingName: flowchart --- !u!1 &411939899 GameObject: m_ObjectHideFlags: 0 @@ -494,6 +617,58 @@ MonoBehaviour: commandList: - {fileID: 411939906} - {fileID: 411939905} +--- !u!1 &467145137 +GameObject: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + serializedVersion: 4 + m_Component: + - 4: {fileID: 467145139} + - 114: {fileID: 467145138} + m_Layer: 0 + m_Name: BlockSignalsTest + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!114 &467145138 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 467145137} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: b1dba0b27b0864740a8720e920aa88c0, type: 3} + m_Name: + m_EditorClassIdentifier: + timeout: 5 + ignored: 0 + succeedAfterAllAssertionsAreExecuted: 0 + expectException: 0 + expectedExceptionList: + succeedWhenExceptionIsThrown: 0 + includedPlatforms: -1 + platformsToIgnore: [] + dynamic: 0 + dynamicTypeName: +--- !u!4 &467145139 +Transform: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 467145137} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_Children: + - {fileID: 330763415} + - {fileID: 676488089} + m_Father: {fileID: 0} + m_RootOrder: 3 --- !u!1 &597475644 GameObject: m_ObjectHideFlags: 0 @@ -581,6 +756,46 @@ Transform: m_Children: [] m_Father: {fileID: 0} m_RootOrder: 0 +--- !u!1 &676488088 +GameObject: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + serializedVersion: 4 + m_Component: + - 4: {fileID: 676488089} + - 114: {fileID: 676488090} + m_Layer: 0 + m_Name: BlockSignalsTester + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &676488089 +Transform: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 676488088} + m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_Children: [] + m_Father: {fileID: 467145139} + m_RootOrder: 1 +--- !u!114 &676488090 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 676488088} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 5d396ca39a0454e2ca06d4aad7c5706c, type: 3} + m_Name: + m_EditorClassIdentifier: --- !u!1 &759754969 GameObject: m_ObjectHideFlags: 0 @@ -642,7 +857,7 @@ Transform: m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} m_Children: [] m_Father: {fileID: 0} - m_RootOrder: 4 + m_RootOrder: 5 --- !u!1 &1201908855 GameObject: m_ObjectHideFlags: 0 @@ -816,4 +1031,4 @@ Transform: m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} m_Children: [] m_Father: {fileID: 0} - m_RootOrder: 3 + m_RootOrder: 4