Browse Source

Added Write command and new Text Tag Parser

Added new Fungus/UI module
Added initial UI tests
master
chrisgregan 10 years ago
parent
commit
ec35022fab
  1. 9
      Assets/Fungus/UI.meta
  2. 9
      Assets/Fungus/UI/Editor.meta
  3. 88
      Assets/Fungus/UI/Editor/WriteEditor.cs
  4. 12
      Assets/Fungus/UI/Editor/WriteEditor.cs.meta
  5. 9
      Assets/Fungus/UI/Scripts.meta
  6. 9
      Assets/Fungus/UI/Scripts/Commands.meta
  7. 109
      Assets/Fungus/UI/Scripts/Commands/Write.cs
  8. 12
      Assets/Fungus/UI/Scripts/Commands/Write.cs.meta
  9. 298
      Assets/Fungus/UI/Scripts/TextTagParser.cs
  10. 12
      Assets/Fungus/UI/Scripts/TextTagParser.cs.meta
  11. 528
      Assets/Fungus/UI/Scripts/Writer.cs
  12. 12
      Assets/Fungus/UI/Scripts/Writer.cs.meta
  13. 4
      Assets/Tests.meta
  14. 9
      Assets/Tests/UI.meta
  15. 9
      Assets/Tests/UI/Audio.meta
  16. BIN
      Assets/Tests/UI/Audio/Beep.wav
  17. 21
      Assets/Tests/UI/Audio/Beep.wav.meta
  18. 9
      Assets/Tests/UI/Editor.meta
  19. 206
      Assets/Tests/UI/Editor/TextTagParserTests.cs
  20. 12
      Assets/Tests/UI/Editor/TextTagParserTests.cs.meta
  21. 23
      Assets/Tests/UI/FakeWriterInput.cs
  22. 12
      Assets/Tests/UI/FakeWriterInput.cs.meta
  23. 9
      Assets/Tests/UI/Sprites.meta
  24. BIN
      Assets/Tests/UI/Sprites/RotationTest.psd
  25. 55
      Assets/Tests/UI/Sprites/RotationTest.psd.meta
  26. 9
      Assets/Tests/UI/TestFlags.cs
  27. 12
      Assets/Tests/UI/TestFlags.cs.meta
  28. 4520
      Assets/Tests/UI/TextTests.unity
  29. 8
      Assets/Tests/UI/TextTests.unity.meta

9
Assets/Fungus/UI.meta

@ -0,0 +1,9 @@
fileFormatVersion: 2
guid: 71839549e49ad422ba0be670a2d9e8f3
folderAsset: yes
timeCreated: 1435850993
licenseType: Free
DefaultImporter:
userData:
assetBundleName:
assetBundleVariant:

9
Assets/Fungus/UI/Editor.meta

@ -0,0 +1,9 @@
fileFormatVersion: 2
guid: 7ebd428fad0b74343aa1bf752f8f05a1
folderAsset: yes
timeCreated: 1438002256
licenseType: Free
DefaultImporter:
userData:
assetBundleName:
assetBundleVariant:

88
Assets/Fungus/UI/Editor/WriteEditor.cs

@ -0,0 +1,88 @@
using UnityEditor;
using UnityEditorInternal;
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
using Rotorz.ReorderableList;
namespace Fungus
{
[CustomEditor (typeof(Write))]
public class WriteEditor : CommandEditor
{
static public bool showTagHelp;
protected SerializedProperty textObjectProp;
protected SerializedProperty textProp;
protected SerializedProperty clearTextProp;
protected SerializedProperty textColorProp;
protected SerializedProperty setAlphaProp;
protected SerializedProperty setColorProp;
protected SerializedProperty waitUntilFinishedProp;
static public void DrawTagHelpLabel()
{
string tagsText = "";
tagsText += "\n";
tagsText += TextTagParser.GetTagHelp();
float pixelHeight = EditorStyles.miniLabel.CalcHeight(new GUIContent(tagsText), EditorGUIUtility.currentViewWidth);
EditorGUILayout.SelectableLabel(tagsText, GUI.skin.GetStyle("HelpBox"), GUILayout.MinHeight(pixelHeight));
}
protected virtual void OnEnable()
{
textObjectProp = serializedObject.FindProperty("textObject");
textProp = serializedObject.FindProperty("text");
clearTextProp = serializedObject.FindProperty("clearText");
textColorProp = serializedObject.FindProperty("textColor");
setAlphaProp = serializedObject.FindProperty("setAlpha");
setColorProp = serializedObject.FindProperty("setColor");
waitUntilFinishedProp = serializedObject.FindProperty("waitUntilFinished");
}
public override void DrawCommandGUI()
{
serializedObject.Update();
EditorGUILayout.PropertyField(textObjectProp);
EditorGUILayout.PropertyField(textProp);
EditorGUILayout.BeginHorizontal();
GUILayout.FlexibleSpace();
if (GUILayout.Button(new GUIContent("Text Tag Help", "View available tags"), new GUIStyle(EditorStyles.miniButton)))
{
showTagHelp = !showTagHelp;
}
EditorGUILayout.EndHorizontal();
if (showTagHelp)
{
DrawTagHelpLabel();
}
EditorGUILayout.PropertyField(clearTextProp);
EditorGUILayout.PropertyField(textColorProp);
switch ((Write.TextColor)textColorProp.enumValueIndex)
{
case Write.TextColor.Default:
break;
case Write.TextColor.SetVisible:
break;
case Write.TextColor.SetAlpha:
EditorGUILayout.PropertyField(setAlphaProp);
break;
case Write.TextColor.SetColor:
EditorGUILayout.PropertyField(setColorProp);
break;
}
EditorGUILayout.PropertyField(waitUntilFinishedProp);
serializedObject.ApplyModifiedProperties();
}
}
}

12
Assets/Fungus/UI/Editor/WriteEditor.cs.meta

@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: 208d7ec04cbeb4939ab57abf81810ced
timeCreated: 1438002269
licenseType: Free
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

9
Assets/Fungus/UI/Scripts.meta

@ -0,0 +1,9 @@
fileFormatVersion: 2
guid: 26c5ee956235e48f18c9a7d6ad86a3eb
folderAsset: yes
timeCreated: 1435851000
licenseType: Free
DefaultImporter:
userData:
assetBundleName:
assetBundleVariant:

9
Assets/Fungus/UI/Scripts/Commands.meta

@ -0,0 +1,9 @@
fileFormatVersion: 2
guid: a7a410254d340428085aaf0e66b494fd
folderAsset: yes
timeCreated: 1435851006
licenseType: Free
DefaultImporter:
userData:
assetBundleName:
assetBundleVariant:

109
Assets/Fungus/UI/Scripts/Commands/Write.cs

@ -0,0 +1,109 @@
using UnityEngine;
using UnityEngine.UI;
using System;
using System.Collections;
using UnityEngine.Serialization;
namespace Fungus
{
[CommandInfo("UI",
"Write",
"Writes content to a UI Text or Text Mesh object.")]
[AddComponentMenu("")]
public class Write : Command
{
[Tooltip("Text object to set text on. Text, Input Field and Text Mesh objects are supported.")]
public GameObject textObject;
[Tooltip("String value to assign to the text object")]
public StringData text;
public bool clearText = true;
public bool waitUntilFinished = true;
public enum TextColor
{
Default,
SetVisible,
SetAlpha,
SetColor
}
public TextColor textColor = TextColor.Default;
public FloatData setAlpha = new FloatData(1f);
public ColorData setColor = new ColorData(Color.white);
public override void OnEnter()
{
if (textObject == null)
{
Continue();
return;
}
Writer writer = FindWriter(textObject);
if (writer == null)
{
Continue();
return;
}
switch (textColor)
{
case TextColor.SetAlpha:
writer.SetTextAlpha(setAlpha);
break;
case TextColor.SetColor:
writer.SetTextColor(setColor);
break;
case TextColor.SetVisible:
writer.SetTextAlpha(1f);
break;
}
Flowchart flowchart = GetFlowchart();
string newText = flowchart.SubstituteVariables(text.Value);
if (!waitUntilFinished)
{
writer.Write(newText, clearText);
Continue();
}
else
{
writer.Write(newText, clearText, () => { Continue (); } );
}
}
public override string GetSummary()
{
if (textObject != null)
{
return textObject.name + " : " + text.Value;
}
return "Error: No text object selected";
}
public override Color GetButtonColor()
{
return new Color32(235, 191, 217, 255);
}
protected Writer FindWriter(GameObject textObject)
{
Writer writer = textObject.GetComponent<Writer>();
if (writer == null)
{
writer = textObject.AddComponent<Writer>() as Writer;
}
return writer;
}
}
}

12
Assets/Fungus/UI/Scripts/Commands/Write.cs.meta

@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: ad2261dbe44de43a980e6f7c77c88f7f
timeCreated: 1437682443
licenseType: Free
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

298
Assets/Fungus/UI/Scripts/TextTagParser.cs

@ -0,0 +1,298 @@
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
using System.Text.RegularExpressions;
namespace Fungus
{
public class TextTagParser
{
public enum TokenType
{
Invalid,
Words, // A string of words
BoldStart, // b
BoldEnd, // /b
ItalicStart, // i
ItalicEnd, // /i
ColorStart, // color=red
ColorEnd, // /color
Wait, // w, w=0.5
WaitForInputNoClear, // wi
WaitForInputAndClear, // wc
WaitOnPunctuationStart, // wp, wp=0.5
WaitOnPunctuationEnd, // /wp
Clear, // c
SpeedStart, // s, s=60
SpeedEnd, // /s
Exit, // x
Message, // m=MessageName
VerticalPunch, // {vpunch=0.5}
HorizontalPunch, // {hpunch=0.5}
Punch, // {shake=0.5}
Flash, // {flash=0.5}
Audio, // {audio=Sound}
AudioLoop, // {audioloop=Sound}
AudioPause, // {audiopause=Sound}
AudioStop // {audiostop=Sound}
}
public class Token
{
public TokenType type = TokenType.Invalid;
public string param = "";
}
public static string GetTagHelp()
{
return "" +
"\t{b} Bold Text {/b}\n" +
"\t{i} Italic Text {/i}\n" +
"\t{color=red} Color Text (color){/color}\n" +
"\n" +
"\t{s}, {s=60} Writing speed (chars per sec){/s}\n" +
"\t{w}, {w=0.5} Wait (seconds)\n" +
"\t{wi} Wait for input\n" +
"\t{wc} Wait for input and clear\n" +
"\t{wp}, {wp=0.5} Wait on punctuation (seconds){/wp}\n" +
"\t{c} Clear\n" +
"\t{x} Exit, advance to the next command without waiting for input\n" +
"\n" +
"\t{vpunch=0.5} Vertically punch screen (intensity)\n" +
"\t{hpunch=0.5} Horizontally punch screen (intensity)\n" +
"\t{shake=1} Shake screen (intensity)\n" +
"\t{shiver=1} Shiver screen (intensity)\n" +
"\t{flash=0.5} Flash screen (duration)\n" +
"\n" +
"\t{audio=AudioObjectName} Play Audio Once\n" +
"\t{audioloop=AudioObjectName} Play Audio Loop\n" +
"\t{audiopause=AudioObjectName} Pause Audio\n" +
"\t{audiostop=AudioObjectName} Stop Audio\n" +
"\n" +
"\t{m=MessageName} Broadcast message\n" +
"\t{$VarName} Substitute variable";
}
public virtual List<Token> Tokenize(string storyText)
{
List<Token> tokens = new List<Token>();
string pattern = @"\{.*?\}";
Regex myRegex = new Regex(pattern);
Match m = myRegex.Match(storyText); // m is the first match
int position = 0;
while (m.Success)
{
// Get bit leading up to tag
string preText = storyText.Substring(position, m.Index - position);
string tagText = m.Value;
if (preText != "")
{
AddWordsToken(tokens, preText);
}
AddTagToken(tokens, tagText);
position = m.Index + tagText.Length;
m = m.NextMatch();
}
if (position < storyText.Length)
{
string postText = storyText.Substring(position, storyText.Length - position);
if (postText.Length > 0)
{
AddWordsToken(tokens, postText);
}
}
// Remove all leading whitespace & newlines after a {c} or {wc} tag
// These characters are usually added for legibility when editing, but are not
// desireable when viewing the text in game.
bool trimLeading = false;
foreach (Token token in tokens)
{
if (trimLeading &&
token.type == TokenType.Words)
{
token.param.TrimStart(' ', '\t', '\r', '\n');
}
if (token.type == TokenType.Clear ||
token.type == TokenType.WaitForInputAndClear)
{
trimLeading = true;
}
else
{
trimLeading = false;
}
}
return tokens;
}
protected virtual void AddWordsToken(List<Token> tokenList, string words)
{
Token token = new Token();
token.type = TokenType.Words;
token.param = words;
tokenList.Add(token);
}
protected virtual void AddTagToken(List<Token> tokenList, string tagText)
{
if (tagText.Length < 3 ||
tagText.Substring(0,1) != "{" ||
tagText.Substring(tagText.Length - 1,1) != "}")
{
return;
}
string tag = tagText.Substring(1, tagText.Length - 2);
TokenType type = TokenType.Invalid;
string paramText = ExtractParameter(tag);
if (tag == "b")
{
type = TokenType.BoldStart;
}
else if (tag == "/b")
{
type = TokenType.BoldEnd;
}
else if (tag == "i")
{
type = TokenType.ItalicStart;
}
else if (tag == "/i")
{
type = TokenType.ItalicEnd;
}
else if (tag.StartsWith("color="))
{
type = TokenType.ColorStart;
}
else if (tag == "/color")
{
type = TokenType.ColorEnd;
}
else if (tag == "wi")
{
type = TokenType.WaitForInputNoClear;
}
if (tag == "wc")
{
type = TokenType.WaitForInputAndClear;
}
else if (tag.StartsWith("wp="))
{
type = TokenType.WaitOnPunctuationStart;
}
else if (tag == "wp")
{
type = TokenType.WaitOnPunctuationStart;
}
else if (tag == "/wp")
{
type = TokenType.WaitOnPunctuationEnd;
}
else if (tag.StartsWith("w="))
{
type = TokenType.Wait;
}
else if (tag == "w")
{
type = TokenType.Wait;
}
else if (tag == "c")
{
type = TokenType.Clear;
}
else if (tag.StartsWith("s="))
{
type = TokenType.SpeedStart;
}
else if (tag == "s")
{
type = TokenType.SpeedStart;
}
else if (tag == "/s")
{
type = TokenType.SpeedEnd;
}
else if (tag == "x")
{
type = TokenType.Exit;
}
else if (tag.StartsWith("m="))
{
type = TokenType.Message;
}
else if (tag.StartsWith("vpunch") ||
tag.StartsWith("vpunch="))
{
type = TokenType.VerticalPunch;
}
else if (tag.StartsWith("hpunch") ||
tag.StartsWith("hpunch="))
{
type = TokenType.HorizontalPunch;
}
else if (tag.StartsWith("punch") ||
tag.StartsWith("punch="))
{
type = TokenType.Punch;
}
else if (tag.StartsWith("flash") ||
tag.StartsWith("flash="))
{
type = TokenType.Flash;
}
else if (tag.StartsWith("audio="))
{
type = TokenType.Audio;
}
else if (tag.StartsWith("audioloop="))
{
type = TokenType.AudioLoop;
}
else if (tag.StartsWith("audiopause="))
{
type = TokenType.AudioPause;
}
else if (tag.StartsWith("audiostop="))
{
type = TokenType.AudioStop;
}
if (type != TokenType.Invalid)
{
Token token = new Token();
token.type = type;
token.param = paramText.Trim();
tokenList.Add(token);
}
else
{
Debug.LogWarning("Invalid text tag " + tag);
}
}
protected virtual string ExtractParameter(string input)
{
int index = input.IndexOf('=');
if (index == -1)
{
return "";
}
return input.Substring(index +1);
}
}
}

12
Assets/Fungus/UI/Scripts/TextTagParser.cs.meta

@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: 6b519a23a7c0e4044b9b680230f51c4f
timeCreated: 1439546126
licenseType: Free
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

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

@ -0,0 +1,528 @@
using UnityEngine;
using UnityEngine.UI;
using System.Collections;
using System.Collections.Generic;
using System;
namespace Fungus
{
public class Writer : MonoBehaviour
{
public float writingSpeed = 60;
public float punctuationPause = 0.25f;
public Color hiddenTextColor = new Color(1,1,1,0);
public bool writeWholeWords = false;
protected float currentWritingSpeed;
protected float currentPunctuationPause;
protected Text textUI;
protected InputField inputField;
protected TextMesh textMesh;
protected bool boldActive = false;
protected bool italicActive = false;
protected bool colorActive = false;
protected string colorText = "";
protected bool inputFlag;
public string text
{
get
{
if (textUI != null)
{
return textUI.text;
}
else if (inputField != null)
{
return inputField.text;
}
else if (textMesh != null)
{
return textMesh.text;
}
return "";
}
set
{
if (textUI != null)
{
textUI.text = value;
}
else if (inputField != null)
{
inputField.text = value;
}
else if (textMesh != null)
{
textMesh.text = value;
}
}
}
protected virtual void Awake()
{
textUI = GetComponent<Text>();
inputField = GetComponent<InputField>();
textMesh = GetComponent<TextMesh>();
}
public virtual bool HasTextObject()
{
return (textUI != null || inputField != null || textMesh != null);
}
public virtual bool SupportsRichText()
{
if (textUI != null)
{
return textUI.supportRichText;
}
if (inputField != null)
{
return false;
}
if (textMesh != null)
{
return textMesh.richText;
}
return false;
}
protected virtual string OpenMarkup()
{
string tagText = "";
if (SupportsRichText())
{
if (colorActive)
{
tagText += "<color=" + colorText + ">";
}
if (boldActive)
{
tagText += "<b>";
}
if (italicActive)
{
tagText += "<i>";
}
}
return tagText;
}
protected virtual string CloseMarkup()
{
string closeText = "";
if (SupportsRichText())
{
if (italicActive)
{
closeText += "</i>";
}
if (boldActive)
{
closeText += "</b>";
}
if (colorActive)
{
closeText += "</color>";
}
}
return closeText;
}
protected virtual void Update()
{
if (Input.anyKeyDown)
{
SetInputFlag();
}
}
public virtual void SetTextColor(Color textColor)
{
if (textUI != null)
{
textUI.color = textColor;
}
else if (inputField != null)
{
if (inputField.textComponent != null)
{
inputField.textComponent.color = textColor;
}
}
else if (textMesh != null)
{
textMesh.color = textColor;
}
}
public virtual void SetTextAlpha(float textAlpha)
{
if (textUI != null)
{
Color tempColor = textUI.color;
tempColor.a = textAlpha;
textUI.color = tempColor;
}
else if (inputField != null)
{
if (inputField.textComponent != null)
{
Color tempColor = inputField.textComponent.color;
tempColor.a = textAlpha;
inputField.textComponent.color = tempColor;
}
}
else if (textMesh != null)
{
Color tempColor = textMesh.color;
tempColor.a = textAlpha;
textMesh.color = tempColor;
}
}
public virtual void Write(string content, bool clear, Action onComplete = null)
{
if (clear)
{
this.text = "";
}
if (!HasTextObject())
{
return;
}
TextTagParser tagParser = new TextTagParser();
List<TextTagParser.Token> tokens = tagParser.Tokenize(content);
StartCoroutine(ProcessTokens(tokens, onComplete));
}
protected virtual IEnumerator ProcessTokens(List<TextTagParser.Token> tokens, Action onComplete)
{
text = "";
// Reset control members
boldActive = false;
italicActive = false;
colorActive = false;
colorText = "";
currentPunctuationPause = punctuationPause;
currentWritingSpeed = writingSpeed;
foreach (TextTagParser.Token token in tokens)
{
switch (token.type)
{
case TextTagParser.TokenType.Words:
yield return StartCoroutine(DoWords(token.param));
break;
case TextTagParser.TokenType.BoldStart:
boldActive = true;
break;
case TextTagParser.TokenType.BoldEnd:
boldActive = false;
break;
case TextTagParser.TokenType.ItalicStart:
italicActive = true;
break;
case TextTagParser.TokenType.ItalicEnd:
italicActive = false;
break;
case TextTagParser.TokenType.ColorStart:
colorActive = true;
colorText = token.param;
break;
case TextTagParser.TokenType.ColorEnd:
colorActive = false;
break;
case TextTagParser.TokenType.Wait:
yield return StartCoroutine(DoWait(token.param));
break;
case TextTagParser.TokenType.WaitForInputNoClear:
yield return StartCoroutine(DoWaitForInput(false));
break;
case TextTagParser.TokenType.WaitForInputAndClear:
yield return StartCoroutine(DoWaitForInput(true));
break;
case TextTagParser.TokenType.WaitOnPunctuationStart:
if (!Single.TryParse(token.param, out currentPunctuationPause))
{
currentPunctuationPause = punctuationPause;
}
break;
case TextTagParser.TokenType.WaitOnPunctuationEnd:
currentPunctuationPause = punctuationPause;
break;
case TextTagParser.TokenType.Clear:
text = "";
break;
case TextTagParser.TokenType.SpeedStart:
if (!Single.TryParse(token.param, out currentWritingSpeed))
{
currentWritingSpeed = writingSpeed;
}
break;
case TextTagParser.TokenType.SpeedEnd:
currentWritingSpeed = writingSpeed;
break;
case TextTagParser.TokenType.Exit:
yield break;
case TextTagParser.TokenType.Message:
Flowchart.BroadcastFungusMessage(token.param);
break;
case TextTagParser.TokenType.VerticalPunch:
float vintensity;
if (!Single.TryParse(token.param, out vintensity))
{
vintensity = 10f;
}
Punch(new Vector3(0, vintensity, 0), 0.5f);
break;
case TextTagParser.TokenType.HorizontalPunch:
float hintensity;
if (!Single.TryParse(token.param, out hintensity))
{
hintensity = 10f;
}
Punch(new Vector3(hintensity, 0, 0), 0.5f);
break;
case TextTagParser.TokenType.Punch:
float intensity;
if (!Single.TryParse(token.param, out intensity))
{
intensity = 10f;
}
Punch(new Vector3(intensity, intensity, 0), 0.5f);
break;
case TextTagParser.TokenType.Flash:
float flashDuration;
if (!Single.TryParse(token.param, out flashDuration))
{
flashDuration = 0.2f;
}
Flash(flashDuration);
break;
case TextTagParser.TokenType.Audio:
{
AudioSource audioSource = FindAudio(token.param);
if (audioSource != null)
{
audioSource.PlayOneShot(audioSource.clip);
}
}
break;
case TextTagParser.TokenType.AudioLoop:
{
AudioSource audioSource = FindAudio(token.param);
if (audioSource != null)
{
audioSource.Play();
audioSource.loop = true;
}
}
break;
case TextTagParser.TokenType.AudioPause:
{
AudioSource audioSource = FindAudio(token.param);
if (audioSource != null)
{
audioSource.Pause();
}
}
break;
case TextTagParser.TokenType.AudioStop:
{
AudioSource audioSource = FindAudio(token.param);
if (audioSource != null)
{
audioSource.Stop();
}
}
break;
}
inputFlag = false;
}
if (onComplete != null)
{
onComplete();
}
}
protected virtual IEnumerator DoWords(string param)
{
string startText = text;
string openText = OpenMarkup();
string closeText = CloseMarkup();
float timeAccumulator = Time.deltaTime;
Color32 c = hiddenTextColor;
string hiddenColor = String.Format("#{0:X2}{1:X2}{2:X2}{3:X2}", c.r, c.g, c.b, c.a);
for (int i = 0; i < param.Length; ++i)
{
string left = "";
string right = "";
if (writeWholeWords)
{
// Look ahead to find next whitespace or end of string
for (int j = i; j < param.Length; ++j)
{
if (Char.IsWhiteSpace(param[j]) ||
j == param.Length - 1)
{
left = param.Substring(0, j + 1);
right = param.Substring(j + 1, param.Length - j - 1);
break;
}
}
}
else
{
left = param.Substring(0, i + 1);
right = param.Substring(i + 1);
}
string tempText = startText + openText + left + closeText;
// Make right hand side text invisible
if (right.Length > 0)
{
tempText += "<color=" + hiddenColor + ">" + right + "</color>";
}
text = tempText;
if (left.Length > 0 &&
IsPunctuation(left.Substring(left.Length - 1)[0]))
{
yield return new WaitForSeconds(currentPunctuationPause);
}
if (currentWritingSpeed > 0f)
{
if (timeAccumulator > 0f)
{
timeAccumulator -= 1f / currentWritingSpeed;
}
else
{
yield return new WaitForSeconds(1f / currentWritingSpeed);
}
}
}
}
public virtual void SetInputFlag()
{
inputFlag = true;
}
public virtual string GetTagHelp()
{
return "";
}
protected virtual IEnumerator DoWait(string param)
{
float duration = 1f;
if (!Single.TryParse(param, out duration))
{
duration = 1f;
}
yield return new WaitForSeconds(duration);
}
protected virtual IEnumerator DoWaitForInput(bool clear)
{
while (!inputFlag)
{
yield return null;
}
inputFlag = false;
if (clear)
{
textUI.text = "";
}
}
protected virtual bool IsPunctuation(char character)
{
return character == '.' ||
character == '?' ||
character == '!' ||
character == ',' ||
character == ':' ||
character == ';' ||
character == ')';
}
protected virtual void Punch(Vector3 axis, float time)
{
iTween.ShakePosition(this.gameObject, axis, time);
}
protected virtual void Flash(float duration)
{
CameraController cameraController = CameraController.GetInstance();
cameraController.screenFadeTexture = CameraController.CreateColorTexture(new Color(1f,1f,1f,1f), 32, 32);
cameraController.Fade(1f, duration, delegate {
cameraController.screenFadeTexture = CameraController.CreateColorTexture(new Color(1f,1f,1f,1f), 32, 32);
cameraController.Fade(0f, duration, null);
});
}
protected virtual AudioSource FindAudio(string audioObjectName)
{
GameObject go = GameObject.Find(audioObjectName);
if (go == null)
{
return null;
}
return go.GetComponent<AudioSource>();
}
}
}

12
Assets/Fungus/UI/Scripts/Writer.cs.meta

@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: a676940fce6344af1a70043b089a6c14
timeCreated: 1437427397
licenseType: Free
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

4
Assets/Tests.meta

@ -1,7 +1,7 @@
fileFormatVersion: 2 fileFormatVersion: 2
guid: 3d918473a457f402f958b5d4dcad242d guid: f23bed438013a47438010dafdc996ae4
folderAsset: yes folderAsset: yes
timeCreated: 1438859813 timeCreated: 1437397391
licenseType: Free licenseType: Free
DefaultImporter: DefaultImporter:
userData: userData:

9
Assets/Tests/UI.meta

@ -0,0 +1,9 @@
fileFormatVersion: 2
guid: f204ed91830f24eb086dca53a4ecac22
folderAsset: yes
timeCreated: 1439480503
licenseType: Free
DefaultImporter:
userData:
assetBundleName:
assetBundleVariant:

9
Assets/Tests/UI/Audio.meta

@ -0,0 +1,9 @@
fileFormatVersion: 2
guid: ed7d38898531446fca43d7ff3d9a5c35
folderAsset: yes
timeCreated: 1437657363
licenseType: Free
DefaultImporter:
userData:
assetBundleName:
assetBundleVariant:

BIN
Assets/Tests/UI/Audio/Beep.wav

Binary file not shown.

21
Assets/Tests/UI/Audio/Beep.wav.meta

@ -0,0 +1,21 @@
fileFormatVersion: 2
guid: 58cb220e0c6c34a1280967cdc9271d68
timeCreated: 1437657437
licenseType: Free
AudioImporter:
serializedVersion: 6
defaultSettings:
loadType: 0
sampleRateSetting: 0
sampleRateOverride: 44100
compressionFormat: 1
quality: 1
conversionMode: 0
platformSettingOverrides: {}
forceToMono: 0
preloadAudioData: 1
loadInBackground: 0
3D: 1
userData:
assetBundleName:
assetBundleVariant:

9
Assets/Tests/UI/Editor.meta

@ -0,0 +1,9 @@
fileFormatVersion: 2
guid: 27691b3c5e5044c968559d92599fae5e
folderAsset: yes
timeCreated: 1437398356
licenseType: Free
DefaultImporter:
userData:
assetBundleName:
assetBundleVariant:

206
Assets/Tests/UI/Editor/TextTagParserTests.cs

@ -0,0 +1,206 @@
using System;
using System.Collections.Generic;
using NUnit.Framework;
using UnityEngine;
using Fungus;
[TestFixture]
public class TextTagParserTests
{
[Test]
public void TextTagParser_Parser()
{
var textTagParser = new TextTagParser();
// Parse an example string, generate correct sequence of tags
List<TextTagParser.Token> tokens = textTagParser.Tokenize("Words " +
"{b}bold test{/b}" +
"{i}italic test{/i}" +
"{color=red}color test{/color}" +
"{w}{w=0.5}" +
"{wi}{wc}" +
"{wp}{wp=0.5}{/wp}" +
"{c}" +
"{s}{s=60}{/s}" +
"{x}{m=Message}" +
"{vpunch=0.5}" +
"{hpunch=0.5}" +
"{punch=0.5}" +
"{flash=0.5}" +
"{audio=Sound}" +
"{audioloop=Sound}" +
"{audiopause=Sound}" +
"{audiostop=Sound}");
int i = 0;
Assert.That(tokens[i].type == TextTagParser.TokenType.Words);
Assert.That(tokens[i].param == "Words ");
i++;
Assert.That(tokens[i].type == TextTagParser.TokenType.BoldStart);
Assert.That(tokens[i].param == "");
i++;
Assert.That(tokens[i].type == TextTagParser.TokenType.Words);
Assert.That(tokens[i].param == "bold test");
i++;
Assert.That(tokens[i].type == TextTagParser.TokenType.BoldEnd);
Assert.That(tokens[i].param == "");
i++;
Assert.That(tokens[i].type == TextTagParser.TokenType.ItalicStart);
Assert.That(tokens[i].param == "");
i++;
Assert.That(tokens[i].type == TextTagParser.TokenType.Words);
Assert.That(tokens[i].param == "italic test");
i++;
Assert.That(tokens[i].type == TextTagParser.TokenType.ItalicEnd);
Assert.That(tokens[i].param == "");
i++;
Assert.That(tokens[i].type == TextTagParser.TokenType.ColorStart);
Assert.That(tokens[i].param == "red");
i++;
Assert.That(tokens[i].type == TextTagParser.TokenType.Words);
Assert.That(tokens[i].param == "color test");
i++;
Assert.That(tokens[i].type == TextTagParser.TokenType.ColorEnd);
Assert.That(tokens[i].param == "");
i++;
Assert.That(tokens[i].type == TextTagParser.TokenType.Wait);
Assert.That(tokens[i].param == "");
i++;
Assert.That(tokens[i].type == TextTagParser.TokenType.Wait);
Assert.That(tokens[i].param == "0.5");
i++;
Assert.That(tokens[i].type == TextTagParser.TokenType.WaitForInputNoClear);
Assert.That(tokens[i].param == "");
i++;
Assert.That(tokens[i].type == TextTagParser.TokenType.WaitForInputAndClear);
Assert.That(tokens[i].param == "");
i++;
Assert.That(tokens[i].type == TextTagParser.TokenType.WaitOnPunctuationStart);
Assert.That(tokens[i].param == "");
i++;
Assert.That(tokens[i].type == TextTagParser.TokenType.WaitOnPunctuationStart);
Assert.That(tokens[i].param == "0.5");
i++;
Assert.That(tokens[i].type == TextTagParser.TokenType.WaitOnPunctuationEnd);
Assert.That(tokens[i].param == "");
i++;
Assert.That(tokens[i].type == TextTagParser.TokenType.Clear);
Assert.That(tokens[i].param == "");
i++;
Assert.That(tokens[i].type == TextTagParser.TokenType.SpeedStart);
Assert.That(tokens[i].param == "");
i++;
Assert.That(tokens[i].type == TextTagParser.TokenType.SpeedStart);
Assert.That(tokens[i].param == "60");
i++;
Assert.That(tokens[i].type == TextTagParser.TokenType.SpeedEnd);
Assert.That(tokens[i].param == "");
i++;
Assert.That(tokens[i].type == TextTagParser.TokenType.Exit);
Assert.That(tokens[i].param == "");
i++;
Assert.That(tokens[i].type == TextTagParser.TokenType.Message);
Assert.That(tokens[i].param == "Message");
i++;
Assert.That(tokens[i].type == TextTagParser.TokenType.VerticalPunch);
Assert.That(tokens[i].param == "0.5");
i++;
Assert.That(tokens[i].type == TextTagParser.TokenType.HorizontalPunch);
Assert.That(tokens[i].param == "0.5");
i++;
Assert.That(tokens[i].type == TextTagParser.TokenType.Punch);
Assert.That(tokens[i].param == "0.5");
i++;
Assert.That(tokens[i].type == TextTagParser.TokenType.Flash);
Assert.That(tokens[i].param == "0.5");
i++;
Assert.That(tokens[i].type == TextTagParser.TokenType.Audio);
Assert.That(tokens[i].param == "Sound");
i++;
Assert.That(tokens[i].type == TextTagParser.TokenType.AudioLoop);
Assert.That(tokens[i].param == "Sound");
i++;
Assert.That(tokens[i].type == TextTagParser.TokenType.AudioPause);
Assert.That(tokens[i].param == "Sound");
i++;
Assert.That(tokens[i].type == TextTagParser.TokenType.AudioStop);
Assert.That(tokens[i].param == "Sound");
Assert.That(tokens.Count == 31);
}
[Test]
public void TextTagParser_AudioWaitBug()
{
var textTagParser = new TextTagParser();
// Parse an example string, generate correct sequence of tags
List<TextTagParser.Token> tokens = textTagParser.Tokenize("Play sound{audio=BeepSound}{w=1} Play loop{audioloop=BeepSound}{w=3} Stop{audiostop=BeepSound}");
int i = 0;
Assert.That(tokens[i].type == TextTagParser.TokenType.Words);
Assert.That(tokens[i].param == "Play sound");
i++;
Assert.That(tokens[i].type == TextTagParser.TokenType.Audio);
Assert.That(tokens[i].param == "BeepSound");
i++;
Assert.That(tokens[i].type == TextTagParser.TokenType.Wait);
Assert.That(tokens[i].param == "1");
i++;
Assert.That(tokens[i].type == TextTagParser.TokenType.Words);
Assert.That(tokens[i].param == " Play loop");
i++;
Assert.That(tokens[i].type == TextTagParser.TokenType.AudioLoop);
Assert.That(tokens[i].param == "BeepSound");
i++;
Assert.That(tokens[i].type == TextTagParser.TokenType.Wait);
Assert.That(tokens[i].param == "3");
i++;
Assert.That(tokens[i].type == TextTagParser.TokenType.Words);
Assert.That(tokens[i].param == " Stop");
i++;
Assert.That(tokens[i].type == TextTagParser.TokenType.AudioStop);
Assert.That(tokens[i].param == "BeepSound");
Assert.That(tokens.Count == 8);
}
}

12
Assets/Tests/UI/Editor/TextTagParserTests.cs.meta

@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: a9cea7ad00f8a4d8aa33b09722792171
timeCreated: 1436968375
licenseType: Free
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

23
Assets/Tests/UI/FakeWriterInput.cs

@ -0,0 +1,23 @@
using UnityEngine;
using System.Collections;
namespace Fungus
{
public class FakeWriterInput : MonoBehaviour
{
public float delay;
void Start ()
{
Invoke("DoFakeInput", delay);
}
void DoFakeInput()
{
Writer writer = GetComponent<Writer>();
writer.SetInputFlag();
}
}
}

12
Assets/Tests/UI/FakeWriterInput.cs.meta

@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: 21440b2111dd24f8e95aa8fc983c53dd
timeCreated: 1437489220
licenseType: Free
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

9
Assets/Tests/UI/Sprites.meta

@ -0,0 +1,9 @@
fileFormatVersion: 2
guid: f7526ee6ce9194a858b35171b9173bdc
folderAsset: yes
timeCreated: 1438162230
licenseType: Free
DefaultImporter:
userData:
assetBundleName:
assetBundleVariant:

BIN
Assets/Tests/UI/Sprites/RotationTest.psd

Binary file not shown.

55
Assets/Tests/UI/Sprites/RotationTest.psd.meta

@ -0,0 +1,55 @@
fileFormatVersion: 2
guid: 81391c336c8a84b67991d7cc40d8d192
timeCreated: 1438335040
licenseType: Free
TextureImporter:
fileIDToRecycleName: {}
serializedVersion: 2
mipmaps:
mipMapMode: 0
enableMipMap: 1
linearTexture: 0
correctGamma: 0
fadeOut: 0
borderMipMap: 0
mipMapFadeDistanceStart: 1
mipMapFadeDistanceEnd: 3
bumpmap:
convertToNormalMap: 0
externalNormalMap: 0
heightScale: .25
normalMapFilter: 0
isReadable: 0
grayScaleToAlpha: 0
generateCubemap: 0
cubemapConvolution: 0
cubemapConvolutionSteps: 8
cubemapConvolutionExponent: 1.5
seamlessCubemap: 0
textureFormat: -1
maxTextureSize: 2048
textureSettings:
filterMode: -1
aniso: -1
mipBias: -1
wrapMode: 1
nPOTScale: 0
lightmap: 0
rGBM: 0
compressionQuality: 50
spriteMode: 1
spriteExtrude: 1
spriteMeshType: 1
alignment: 0
spritePivot: {x: .5, y: .5}
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
spritePixelsToUnits: 100
alphaIsTransparency: 1
textureType: 8
buildTargetSettings: []
spriteSheet:
sprites: []
spritePackingTag:
userData:
assetBundleName:
assetBundleVariant:

9
Assets/Tests/UI/TestFlags.cs

@ -0,0 +1,9 @@
using UnityEngine;
using System.Collections;
public class TestFlags : MonoBehaviour
{
public bool messageReceived { get; set; }
public bool writeCommandsFinished { get; set; }
}

12
Assets/Tests/UI/TestFlags.cs.meta

@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: a3043c63f002347b9b36c07403fffaa7
timeCreated: 1437997441
licenseType: Free
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

4520
Assets/Tests/UI/TextTests.unity

File diff suppressed because it is too large Load Diff

8
Assets/Tests/UI/TextTests.unity.meta

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: f2c5f868588ec472eac0c38ba9de391f
timeCreated: 1439548235
licenseType: Free
DefaultImporter:
userData:
assetBundleName:
assetBundleVariant:
Loading…
Cancel
Save