diff --git a/Assets/Fungus/Scripts/Components/Flowchart.cs b/Assets/Fungus/Scripts/Components/Flowchart.cs index d56aae2e..11ec5096 100644 --- a/Assets/Fungus/Scripts/Components/Flowchart.cs +++ b/Assets/Fungus/Scripts/Components/Flowchart.cs @@ -18,6 +18,8 @@ namespace Fungus [ExecuteInEditMode] public class Flowchart : MonoBehaviour, ISubstitutionHandler { + public const string SubstituteVariableRegexString = "{\\$.*?}"; + [HideInInspector] [SerializeField] protected int version = 0; // Default to 0 to always trigger an update for older versions of Fungus. @@ -1223,7 +1225,7 @@ namespace Fungus sb.Append(input); // Instantiate the regular expression object. - Regex r = new Regex("{\\$.*?}"); + Regex r = new Regex(SubstituteVariableRegexString); bool changed = false; @@ -1274,7 +1276,7 @@ namespace Fungus public virtual bool SubstituteStrings(StringBuilder input) { // Instantiate the regular expression object. - Regex r = new Regex("{\\$.*?}"); + Regex r = new Regex(SubstituteVariableRegexString); bool modified = false; diff --git a/Assets/Fungus/Scripts/Components/Localization.cs b/Assets/Fungus/Scripts/Components/Localization.cs index 5a4b0d76..d492b7a8 100644 --- a/Assets/Fungus/Scripts/Components/Localization.cs +++ b/Assets/Fungus/Scripts/Components/Localization.cs @@ -560,7 +560,7 @@ namespace Fungus Init(); // Instantiate the regular expression object. - Regex r = new Regex("{\\$.*?}"); + Regex r = new Regex(Flowchart.SubstituteVariableRegexString); bool modified = false; diff --git a/Assets/Fungus/Scripts/Utils/ConversationManager.cs b/Assets/Fungus/Scripts/Utils/ConversationManager.cs index 431b7bad..1f00dbd9 100644 --- a/Assets/Fungus/Scripts/Utils/ConversationManager.cs +++ b/Assets/Fungus/Scripts/Utils/ConversationManager.cs @@ -14,6 +14,14 @@ namespace Fungus /// public class ConversationManager { + const string ConversationTextBodyRegex = @"((?[\w ""><.'-_]*?):)?(?.*)\r*(\n|$)"; + + public struct RawConversationItem + { + public string[] sayParams; + public string text; + } + protected struct ConversationItem { public string Text { get; set; } @@ -112,16 +120,13 @@ namespace Fungus return sayDialog; } - protected virtual List Parse(string conv) + public static void PreParse(string conv, System.Action itemAction) { //find SimpleScript say strings with portrait options //You can test regex matches here: http://regexstorm.net/tester - var sayRegex = new Regex(@"((?[\w ""><.'-_]*):)?(?.*)\r*(\n|$)"); + var sayRegex = new Regex(ConversationTextBodyRegex); MatchCollection sayMatches = sayRegex.Matches(conv); - var items = new List(sayMatches.Count); - - Character currentCharacter = null; for (int i = 0; i < sayMatches.Count; i++) { string text = sayMatches[i].Groups["text"].Value.Trim(); @@ -141,14 +146,39 @@ namespace Fungus { separateParams = Split(sayParams); } + else + { + separateParams = new string[0]; + } + + var item = new RawConversationItem() { sayParams = separateParams, text = text }; + + itemAction(item); + } + } + + public static List PreParse(string conv) + { + List retval = new List(); - var item = CreateConversationItem(separateParams, text, currentCharacter); + PreParse(conv, (ia) => { retval.Add(ia); }); + + return retval; + } + + protected virtual List Parse(string conv) + { + var items = new List(); + + Character currentCharacter = null; + PreParse(conv, (ia) => + { + var item = CreateConversationItem(ia.sayParams, ia.text, currentCharacter); // Previous speaking character is the default for next conversation item currentCharacter = item.Character; - items.Add(item); - } + }); return items; } diff --git a/Assets/Fungus/Scripts/Utils/TextTagParser.cs b/Assets/Fungus/Scripts/Utils/TextTagParser.cs index 36b36451..c785b451 100644 --- a/Assets/Fungus/Scripts/Utils/TextTagParser.cs +++ b/Assets/Fungus/Scripts/Utils/TextTagParser.cs @@ -12,6 +12,8 @@ namespace Fungus /// public static class TextTagParser { + const string TextTokenRegexString = @"\{.*?\}"; + private static void AddWordsToken(List tokenList, string words) { TextTagToken token = new TextTagToken(); @@ -235,8 +237,7 @@ namespace Fungus { List tokens = new List(); - string pattern = @"\{.*?\}"; - Regex myRegex = new Regex(pattern); + Regex myRegex = new Regex(TextTokenRegexString); Match m = myRegex.Match(storyText); // m is the first match diff --git a/Assets/Tests/StringSubstitution/Editor/FungusConversationParseTests.cs b/Assets/Tests/StringSubstitution/Editor/FungusConversationParseTests.cs new file mode 100644 index 00000000..a7e77045 --- /dev/null +++ b/Assets/Tests/StringSubstitution/Editor/FungusConversationParseTests.cs @@ -0,0 +1,69 @@ +using NUnit.Framework; +using System.Collections.Generic; + +public class FungusConversationParseTests +{ + private const string SimpleConv = +@"john bored left: Oh, so that's how you use the Conversation command. +sherlock eyeroll right nowait: Yes, well done John. {w=1.5} +You catch on quickly don't you? +sherlock >>>: +hide john ""offscreen left"": I sure do. + +-- This is a comment, it doesn't appear in the conversation +"; + private static readonly List SimpleConvRes = new List() + { + new Fungus.ConversationManager.RawConversationItem(){ sayParams = new string[]{ "john", "bored", "left" }, text = "Oh, so that's how you use the Conversation command."}, + new Fungus.ConversationManager.RawConversationItem(){ sayParams = new string[]{ "sherlock", "eyeroll", "right", "nowait" }, text = "Yes, well done John. {w=1.5}"}, + new Fungus.ConversationManager.RawConversationItem(){ sayParams = new string[]{ }, text = "You catch on quickly don't you?"}, + new Fungus.ConversationManager.RawConversationItem(){ sayParams = new string[]{ "sherlock", ">>>" }, text = ""}, + new Fungus.ConversationManager.RawConversationItem(){ sayParams = new string[]{ "hide", "john", "offscreen left" }, text = "I sure do."}, + }; + + [Test] + public void FungusConversationPreParseSimple() + { + var res = Fungus.ConversationManager.PreParse(SimpleConv); + ValueCompareRawConversationItemLists(res, SimpleConvRes); + } + + private void ValueCompareRawConversationItemLists(List lhs, List rhs) + { + Assert.AreEqual(lhs.Count, rhs.Count, "Different number of results found."); + + for (int i = 0; i < lhs.Count; i++) + { + Assert.AreEqual(lhs[i].text, rhs[i].text, "RawConItem " + i.ToString() + " has different text body."); + Assert.AreEqual(lhs[i].sayParams.Length, rhs[i].sayParams.Length, "RawConItem " + i.ToString() + " have differing say param counts"); + for (int j = 0; j < lhs[i].sayParams.Length; j++) + { + Assert.AreEqual(lhs[i].sayParams[j], rhs[i].sayParams[j], "RawConItem " + i.ToString() + " param: " + j.ToString() + " content"); + } + } + } + + private const string MultiColonConv = +@"sherlock left: Outragous! +john bashful: This is an overreaction Sherlock. +sherlock: Colon to direct attention to a list. Colon to emphasize connecton between independent phrases. +: To Buy: Eggs, Milk, Flour. +sherlock irate right: In this world, there are only two tragedies: one is not getting what one wants, and the other is getting it. +john smug:Love is blind: sometimes it keeps us from seeing the truth."; + private static readonly List MultiColonConvRes = new List() + { + new Fungus.ConversationManager.RawConversationItem(){ sayParams = new string[]{ "sherlock", "left" }, text = "Outragous!"}, + new Fungus.ConversationManager.RawConversationItem(){ sayParams = new string[]{ "john", "bashful" }, text = "This is an overreaction Sherlock."}, + new Fungus.ConversationManager.RawConversationItem(){ sayParams = new string[]{ "sherlock" }, text = "Colon to direct attention to a list. Colon to emphasize connecton between independent phrases."}, + new Fungus.ConversationManager.RawConversationItem(){ sayParams = new string[]{ }, text = "To Buy: Eggs, Milk, Flour."}, + new Fungus.ConversationManager.RawConversationItem(){ sayParams = new string[]{ "sherlock", "irate", "right" }, text = "In this world, there are only two tragedies: one is not getting what one wants, and the other is getting it."}, + new Fungus.ConversationManager.RawConversationItem(){ sayParams = new string[]{ "john", "smug" }, text = "Love is blind: sometimes it keeps us from seeing the truth."}, + }; + + [Test] + public void FungusConversationPreParseMultiColon() + { + var res = Fungus.ConversationManager.PreParse(MultiColonConv); + ValueCompareRawConversationItemLists(res, MultiColonConvRes); + } +} diff --git a/Assets/Tests/StringSubstitution/Editor/FungusConversationParseTests.cs.meta b/Assets/Tests/StringSubstitution/Editor/FungusConversationParseTests.cs.meta new file mode 100644 index 00000000..9987392a --- /dev/null +++ b/Assets/Tests/StringSubstitution/Editor/FungusConversationParseTests.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 12c18ec6bfbb6af4d935d98619790eb7 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: