Browse Source

Merge pull request #410 from FungusGames/fungus-script-support

Fungus script support
master
Chris Gregan 9 years ago
parent
commit
9f02563a6b
  1. 41
      Assets/Fungus/Flowchart/Scripts/Block.cs
  2. 4
      Assets/Fungus/Flowchart/Scripts/Commands/Call.cs
  3. 131
      Assets/Fungus/Flowchart/Scripts/Flowchart.cs
  4. 2
      Assets/Fungus/Narrative/Scripts/Commands/Say.cs
  5. 10
      Assets/Fungus/Narrative/Scripts/MenuDialog.cs
  6. 10
      Assets/Fungus/Narrative/Scripts/SayDialog.cs
  7. 414
      Assets/Fungus/Thirdparty/CSVParser/CsvParser.cs
  8. 8
      Assets/Fungus/UI/Scripts/Writer.cs
  9. 38
      Assets/Tests/Scripting/Scripting.unity

41
Assets/Fungus/Flowchart/Scripts/Block.cs

@ -142,26 +142,25 @@ namespace Fungus
return executionCount;
}
public virtual bool Execute(Action onComplete = null)
/// <summary>
/// Execute the Block in a coroutine. Only one running instance of each Block is permitted.
/// </summary>
/// <param name="commandIndex">Index of command to start execution at</param>
/// <param name="onComplete">Delegate function to call when execution completes</param>
public virtual IEnumerator Execute(int commandIndex = 0, Action onComplete = null)
{
if (executionState != ExecutionState.Idle)
{
return false;
}
if (!executionInfoSet)
{
SetExecutionInfo();
}
if (executionState != ExecutionState.Idle)
{
yield break;
}
executionCount++;
StartCoroutine(ExecuteBlock(onComplete));
if (!executionInfoSet)
{
SetExecutionInfo();
}
return true;
}
executionCount++;
protected virtual IEnumerator ExecuteBlock(Action onComplete = null)
{
Flowchart flowchart = GetFlowchart();
executionState = ExecutionState.Executing;
@ -175,6 +174,8 @@ namespace Fungus
}
#endif
jumpToCommandIndex = commandIndex;
int i = 0;
while (true)
{
@ -248,10 +249,10 @@ namespace Fungus
executionState = ExecutionState.Idle;
activeCommand = null;
if (onComplete != null)
{
onComplete();
}
if (onComplete != null)
{
onComplete();
}
}
public virtual void Stop()

4
Assets/Fungus/Flowchart/Scripts/Commands/Call.cs

@ -64,12 +64,12 @@ namespace Fungus
flowchart.selectedBlock = targetBlock;
}
targetBlock.Execute(onComplete);
StartCoroutine(targetBlock.Execute(0, onComplete));
}
else
{
// Execute block in another Flowchart
targetFlowchart.ExecuteBlock(targetBlock, onComplete);
targetFlowchart.ExecuteBlock(targetBlock, 0, onComplete);
}
}

131
Assets/Fungus/Flowchart/Scripts/Flowchart.cs

@ -371,61 +371,50 @@ namespace Fungus
}
/**
* Start running another Flowchart by executing a specific child block.
* The block must be in an idle state to be executed.
* Execute a child block in the Flowchart.
* You can use this method in a UI event. e.g. to handle a button click.
* Returns true if the Block started execution.
*/
public virtual void ExecuteBlock(string blockName)
{
Block [] blocks = GetComponentsInChildren<Block>();
foreach (Block block in blocks)
{
if (block.blockName == blockName)
{
ExecuteBlock(block);
}
}
}
/**
* Sends a message to this Flowchart only.
* Any block with a matching MessageReceived event handler will start executing.
*/
public virtual void SendFungusMessage(string messageName)
{
MessageReceived[] eventHandlers = GetComponentsInChildren<MessageReceived>();
foreach (MessageReceived eventHandler in eventHandlers)
{
eventHandler.OnSendFungusMessage(messageName);
}
}
/**
* Sends a message to all Flowchart objects in the current scene.
* Any block with a matching MessageReceived event handler will start executing.
*/
public static void BroadcastFungusMessage(string messageName)
public virtual bool ExecuteBlock(string blockName)
{
MessageReceived[] eventHandlers = GameObject.FindObjectsOfType<MessageReceived>();
foreach (MessageReceived eventHandler in eventHandlers)
{
eventHandler.OnSendFungusMessage(messageName);
}
Block block = null;
foreach (Block b in GetComponentsInChildren<Block>())
{
if (b.blockName == blockName)
{
block = b;
break;
}
}
if (block == null)
{
Debug.LogError("Block " + blockName + "does not exist");
return false;
}
return ExecuteBlock(block);
}
/**
* Start executing a specific child block in the flowchart.
* Execute a child block in the flowchart.
* The block must be in an idle state to be executed.
* This version provides extra options to control how the block is executed.
* Returns true if the Block started execution.
*/
public virtual bool ExecuteBlock(Block block, Action onComplete = null)
public virtual bool ExecuteBlock(Block block, int commandIndex = 0, Action onComplete = null)
{
// Block must be a component of the Flowchart game object
if (block == null ||
block.gameObject != gameObject)
{
return false;
}
if (block == null)
{
Debug.LogError("Block must not be null");
return false;
}
if (block.gameObject != gameObject)
{
Debug.LogError("Block must belong to the same gameobject as this Flowchart");
return false;
}
// Can't restart a running block, have to wait until it's idle again
if (block.IsExecuting())
@ -433,10 +422,10 @@ namespace Fungus
return false;
}
// Execute the first command in the command list
block.Execute(onComplete);
// Start executing the Block as a new coroutine
StartCoroutine(block.Execute(commandIndex, onComplete));
return true;
return true;
}
/**
@ -454,6 +443,32 @@ namespace Fungus
}
}
/**
* Sends a message to this Flowchart only.
* Any block with a matching MessageReceived event handler will start executing.
*/
public virtual void SendFungusMessage(string messageName)
{
MessageReceived[] eventHandlers = GetComponentsInChildren<MessageReceived>();
foreach (MessageReceived eventHandler in eventHandlers)
{
eventHandler.OnSendFungusMessage(messageName);
}
}
/**
* Sends a message to all Flowchart objects in the current scene.
* Any block with a matching MessageReceived event handler will start executing.
*/
public static void BroadcastFungusMessage(string messageName)
{
MessageReceived[] eventHandlers = GameObject.FindObjectsOfType<MessageReceived>();
foreach (MessageReceived eventHandler in eventHandlers)
{
eventHandler.OnSendFungusMessage(messageName);
}
}
/**
* Returns a new variable key that is guaranteed not to clash with any existing variable in the list.
*/
@ -590,6 +605,26 @@ namespace Fungus
}
}
/**
* Returns the variable with the specified key, or null if the key is not found.
* You will need to cast the returned variable to the correct sub-type.
* You can then access the variable's value using the Value property. e.g.
* BooleanVariable boolVar = flowchart.GetVariable("MyBool") as BooleanVariable;
* boolVar.Value = false;
*/
public Variable GetVariable(string key)
{
foreach (Variable variable in variables)
{
if (variable != null && variable.key == key)
{
return variable;
}
}
return null;
}
/**
* Returns the variable with the specified key, or null if the key is not found.
* You can then access the variable's value using the Value property. e.g.

2
Assets/Fungus/Narrative/Scripts/Commands/Say.cs

@ -99,7 +99,7 @@ namespace Fungus
string subbedText = flowchart.SubstituteVariables(displayText);
sayDialog.Say(subbedText, !extendPrevious, waitForClick, fadeWhenDone, voiceOverClip, stopVoiceover, delegate {
sayDialog.Say(subbedText, !extendPrevious, waitForClick, fadeWhenDone, stopVoiceover, voiceOverClip, delegate {
Continue();
});
}

10
Assets/Fungus/Narrative/Scripts/MenuDialog.cs

@ -13,8 +13,11 @@ namespace Fungus
// Currently active Menu Dialog used to display Menu options
public static MenuDialog activeMenuDialog;
protected Button[] cachedButtons;
protected Slider cachedSlider;
[NonSerialized]
public Button[] cachedButtons;
[NonSerialized]
public Slider cachedSlider;
public static MenuDialog GetMenuDialog()
{
@ -139,7 +142,7 @@ namespace Fungus
return addedOption;
}
protected virtual void HideSayDialog()
public virtual void HideSayDialog()
{
SayDialog sayDialog = SayDialog.GetSayDialog();
if (sayDialog != null)
@ -150,7 +153,6 @@ namespace Fungus
public virtual void ShowTimer(float duration, Block targetBlock)
{
if (cachedSlider != null)
{
cachedSlider.gameObject.SetActive(true);

10
Assets/Fungus/Narrative/Scripts/SayDialog.cs

@ -126,12 +126,12 @@ namespace Fungus
}
}
public virtual void Say(string text, bool clearPrevious, bool waitForInput, bool fadeWhenDone, AudioClip voiceOverClip, bool stopVoiceover, Action onComplete)
public virtual void Say(string text, bool clearPrevious, bool waitForInput, bool fadeWhenDone, bool stopVoiceover, AudioClip voiceOverClip, Action onComplete)
{
StartCoroutine(SayInternal(text, clearPrevious, waitForInput, fadeWhenDone, voiceOverClip, stopVoiceover, onComplete));
StartCoroutine(SayInternal(text, clearPrevious, waitForInput, fadeWhenDone, stopVoiceover, voiceOverClip, onComplete));
}
protected virtual IEnumerator SayInternal(string text, bool clearPrevious, bool waitForInput, bool fadeWhenDone, AudioClip voiceOverClip, bool stopVoiceover, Action onComplete)
public virtual IEnumerator SayInternal(string text, bool clearPrevious, bool waitForInput, bool fadeWhenDone, bool stopVoiceover, AudioClip voiceOverClip, Action onComplete)
{
Writer writer = GetWriter();
@ -144,6 +144,8 @@ namespace Fungus
}
}
gameObject.SetActive(true);
this.fadeWhenDone = fadeWhenDone;
// Voice over clip takes precedence over a character sound effect if provided
@ -158,8 +160,8 @@ namespace Fungus
{
soundEffectClip = speakingCharacter.soundEffect;
}
writer.Write(text, clearPrevious, waitForInput, stopVoiceover, soundEffectClip, onComplete);
yield return writer.Write(text, clearPrevious, waitForInput, stopVoiceover, soundEffectClip, onComplete);
}
protected virtual void LateUpdate()

414
Assets/Fungus/Thirdparty/CSVParser/CsvParser.cs vendored

@ -5,215 +5,215 @@ using System.Text;
namespace Ideafixxxer.CsvParser
{
public class CsvParser
{
private const char CommaCharacter = ',';
private const char QuoteCharacter = '"';
#region Nested types
private abstract class ParserState
{
public static readonly LineStartState LineStartState = new LineStartState();
public static readonly ValueStartState ValueStartState = new ValueStartState();
public static readonly ValueState ValueState = new ValueState();
public static readonly QuotedValueState QuotedValueState = new QuotedValueState();
public static readonly QuoteState QuoteState = new QuoteState();
public abstract ParserState AnyChar(char ch, ParserContext context);
public abstract ParserState Comma(ParserContext context);
public abstract ParserState Quote(ParserContext context);
public abstract ParserState EndOfLine(ParserContext context);
}
private class LineStartState : ParserState
{
public override ParserState AnyChar(char ch, ParserContext context)
{
context.AddChar(ch);
return ValueState;
}
public override ParserState Comma(ParserContext context)
{
context.AddValue();
return ValueStartState;
}
public override ParserState Quote(ParserContext context)
{
return QuotedValueState;
}
public override ParserState EndOfLine(ParserContext context)
{
context.AddLine();
return LineStartState;
}
}
private class ValueStartState : LineStartState
{
public override ParserState EndOfLine(ParserContext context)
{
context.AddValue();
context.AddLine();
return LineStartState;
}
}
private class ValueState : ParserState
{
public override ParserState AnyChar(char ch, ParserContext context)
{
context.AddChar(ch);
return ValueState;
}
public override ParserState Comma(ParserContext context)
{
context.AddValue();
return ValueStartState;
}
public override ParserState Quote(ParserContext context)
{
context.AddChar(QuoteCharacter);
return ValueState;
}
public override ParserState EndOfLine(ParserContext context)
{
context.AddValue();
context.AddLine();
return LineStartState;
}
}
private class QuotedValueState : ParserState
{
public override ParserState AnyChar(char ch, ParserContext context)
{
context.AddChar(ch);
return QuotedValueState;
}
public override ParserState Comma(ParserContext context)
{
context.AddChar(CommaCharacter);
return QuotedValueState;
}
public override ParserState Quote(ParserContext context)
{
return QuoteState;
}
public override ParserState EndOfLine(ParserContext context)
{
context.AddChar('\r');
context.AddChar('\n');
return QuotedValueState;
}
}
private class QuoteState : ParserState
{
public override ParserState AnyChar(char ch, ParserContext context)
{
//undefined, ignore "
context.AddChar(ch);
return QuotedValueState;
}
public override ParserState Comma(ParserContext context)
{
context.AddValue();
return ValueStartState;
}
public override ParserState Quote(ParserContext context)
{
context.AddChar(QuoteCharacter);
return QuotedValueState;
}
public override ParserState EndOfLine(ParserContext context)
{
context.AddValue();
context.AddLine();
return LineStartState;
}
}
private class ParserContext
{
private readonly StringBuilder _currentValue = new StringBuilder();
private readonly List<string[]> _lines = new List<string[]>();
private readonly List<string> _currentLine = new List<string>();
public void AddChar(char ch)
{
_currentValue.Append(ch);
}
public void AddValue()
{
_currentLine.Add(_currentValue.ToString());
_currentValue.Remove(0, _currentValue.Length);
}
public void AddLine()
{
_lines.Add(_currentLine.ToArray());
_currentLine.Clear();
}
public List<string[]> GetAllLines()
{
if (_currentValue.Length > 0)
{
AddValue();
}
if (_currentLine.Count > 0)
{
AddLine();
}
return _lines;
}
}
#endregion
public string[][] Parse(string csvData)
{
var context = new ParserContext();
public class CsvParser
{
private const char CommaCharacter = ',';
private const char QuoteCharacter = '"';
#region Nested types
private abstract class ParserState
{
public static readonly LineStartState LineStartState = new LineStartState();
public static readonly ValueStartState ValueStartState = new ValueStartState();
public static readonly ValueState ValueState = new ValueState();
public static readonly QuotedValueState QuotedValueState = new QuotedValueState();
public static readonly QuoteState QuoteState = new QuoteState();
public abstract ParserState AnyChar(char ch, ParserContext context);
public abstract ParserState Comma(ParserContext context);
public abstract ParserState Quote(ParserContext context);
public abstract ParserState EndOfLine(ParserContext context);
}
private class LineStartState : ParserState
{
public override ParserState AnyChar(char ch, ParserContext context)
{
context.AddChar(ch);
return ValueState;
}
public override ParserState Comma(ParserContext context)
{
context.AddValue();
return ValueStartState;
}
public override ParserState Quote(ParserContext context)
{
return QuotedValueState;
}
public override ParserState EndOfLine(ParserContext context)
{
context.AddLine();
return LineStartState;
}
}
private class ValueStartState : LineStartState
{
public override ParserState EndOfLine(ParserContext context)
{
context.AddValue();
context.AddLine();
return LineStartState;
}
}
private class ValueState : ParserState
{
public override ParserState AnyChar(char ch, ParserContext context)
{
context.AddChar(ch);
return ValueState;
}
public override ParserState Comma(ParserContext context)
{
context.AddValue();
return ValueStartState;
}
public override ParserState Quote(ParserContext context)
{
context.AddChar(QuoteCharacter);
return ValueState;
}
public override ParserState EndOfLine(ParserContext context)
{
context.AddValue();
context.AddLine();
return LineStartState;
}
}
private class QuotedValueState : ParserState
{
public override ParserState AnyChar(char ch, ParserContext context)
{
context.AddChar(ch);
return QuotedValueState;
}
public override ParserState Comma(ParserContext context)
{
context.AddChar(CommaCharacter);
return QuotedValueState;
}
public override ParserState Quote(ParserContext context)
{
return QuoteState;
}
public override ParserState EndOfLine(ParserContext context)
{
context.AddChar('\r');
context.AddChar('\n');
return QuotedValueState;
}
}
private class QuoteState : ParserState
{
public override ParserState AnyChar(char ch, ParserContext context)
{
//undefined, ignore "
context.AddChar(ch);
return QuotedValueState;
}
public override ParserState Comma(ParserContext context)
{
context.AddValue();
return ValueStartState;
}
public override ParserState Quote(ParserContext context)
{
context.AddChar(QuoteCharacter);
return QuotedValueState;
}
public override ParserState EndOfLine(ParserContext context)
{
context.AddValue();
context.AddLine();
return LineStartState;
}
}
private class ParserContext
{
private readonly StringBuilder _currentValue = new StringBuilder();
private readonly List<string[]> _lines = new List<string[]>();
private readonly List<string> _currentLine = new List<string>();
public void AddChar(char ch)
{
_currentValue.Append(ch);
}
public void AddValue()
{
_currentLine.Add(_currentValue.ToString());
_currentValue.Remove(0, _currentValue.Length);
}
public void AddLine()
{
_lines.Add(_currentLine.ToArray());
_currentLine.Clear();
}
public List<string[]> GetAllLines()
{
if (_currentValue.Length > 0)
{
AddValue();
}
if (_currentLine.Count > 0)
{
AddLine();
}
return _lines;
}
}
#endregion
public string[][] Parse(string csvData)
{
var context = new ParserContext();
// Handle both Windows and Mac line endings
string[] lines = csvData.Split(new string[] { "\r\n", "\n" }, StringSplitOptions.RemoveEmptyEntries);
ParserState currentState = ParserState.LineStartState;
foreach (string next in lines)
{
foreach (char ch in next)
{
switch (ch)
{
case CommaCharacter:
currentState = currentState.Comma(context);
break;
case QuoteCharacter:
currentState = currentState.Quote(context);
break;
default:
currentState = currentState.AnyChar(ch, context);
break;
}
}
currentState = currentState.EndOfLine(context);
}
List<string[]> allLines = context.GetAllLines();
return allLines.ToArray();
}
}
ParserState currentState = ParserState.LineStartState;
foreach (string next in lines)
{
foreach (char ch in next)
{
switch (ch)
{
case CommaCharacter:
currentState = currentState.Comma(context);
break;
case QuoteCharacter:
currentState = currentState.Quote(context);
break;
default:
currentState = currentState.AnyChar(ch, context);
break;
}
}
currentState = currentState.EndOfLine(context);
}
List<string[]> allLines = context.GetAllLines();
return allLines.ToArray();
}
}
}

8
Assets/Fungus/UI/Scripts/Writer.cs

@ -317,7 +317,7 @@ namespace Fungus
}
}
public virtual void Write(string content, bool clear, bool waitForInput, bool stopAudio, AudioClip audioClip, Action onComplete)
public virtual IEnumerator Write(string content, bool clear, bool waitForInput, bool stopAudio, AudioClip audioClip, Action onComplete)
{
if (clear)
{
@ -326,7 +326,7 @@ namespace Fungus
if (!HasTextObject())
{
return;
yield break;
}
// If this clip is null then WriterAudio will play the default sound effect (if any)
@ -341,7 +341,9 @@ namespace Fungus
TextTagParser tagParser = new TextTagParser();
List<TextTagParser.Token> tokens = tagParser.Tokenize(tokenText);
StartCoroutine(ProcessTokens(tokens, stopAudio, onComplete));
gameObject.SetActive(true);
yield return StartCoroutine(ProcessTokens(tokens, stopAudio, onComplete));
}
virtual protected bool CheckParamCount(List<string> paramList, int count)

38
Assets/Tests/Scripting/Scripting.unity

@ -3005,7 +3005,7 @@ MonoBehaviour:
targetComponentFullname: UnityEngine.Component[]
targetComponentText: Flowchart
targetMethod: ExecuteBlock
targetMethodText: 'ExecuteBlock (String, Int32, Action): Void'
targetMethodText: 'ExecuteBlock (String): Boolean'
methodParameters:
- objValue:
typeAssemblyname: System.String, mscorlib, Version=2.0.0.0, Culture=neutral,
@ -3024,43 +3024,9 @@ MonoBehaviour:
vector2Value: {x: 0, y: 0}
vector3Value: {x: 0, y: 0, z: 0}
variableKey:
- objValue:
typeAssemblyname: System.Int32, mscorlib, Version=2.0.0.0, Culture=neutral,
PublicKeyToken=b77a5c561934e089
typeFullname: System.Int32
intValue: 0
boolValue: 0
floatValue: 0
stringValue:
colorValue: {r: 0, g: 0, b: 0, a: 0}
gameObjectValue: {fileID: 0}
materialValue: {fileID: 0}
objectValue: {fileID: 0}
spriteValue: {fileID: 0}
textureValue: {fileID: 0}
vector2Value: {x: 0, y: 0}
vector3Value: {x: 0, y: 0, z: 0}
variableKey:
- objValue:
typeAssemblyname: System.Action, System.Core, Version=3.5.0.0, Culture=neutral,
PublicKeyToken=b77a5c561934e089
typeFullname: System.Action
intValue: 0
boolValue: 0
floatValue: 0
stringValue:
colorValue: {r: 0, g: 0, b: 0, a: 0}
gameObjectValue: {fileID: 0}
materialValue: {fileID: 0}
objectValue: {fileID: 0}
spriteValue: {fileID: 0}
textureValue: {fileID: 0}
vector2Value: {x: 0, y: 0}
vector3Value: {x: 0, y: 0, z: 0}
variableKey:
saveReturnValue: 0
returnValueVariableKey:
returnValueType: System.Void
returnValueType: System.Boolean
showInherited: 0
callMode: 0
--- !u!114 &1618689151

Loading…
Cancel
Save