Browse Source

TextVariationHandler selects sub sections of text within [|] following some simple rules and keeps a hashed history

- a la Ink
Writer and Menu make use of TextVariation
master
desktop-maesty/steve 6 years ago
parent
commit
6bf5d63891
  1. 2
      Assets/Fungus/Scripts/Components/MenuDialog.cs
  2. 3
      Assets/Fungus/Scripts/Components/Writer.cs
  3. 118
      Assets/Fungus/Scripts/Utils/TextVariationHandler.cs
  4. 11
      Assets/Fungus/Scripts/Utils/TextVariationHandler.cs.meta
  5. 8
      Assets/FungusExamples/VariationText.meta
  6. 1341
      Assets/FungusExamples/VariationText/TextVariation.unity
  7. 7
      Assets/FungusExamples/VariationText/TextVariation.unity.meta

2
Assets/Fungus/Scripts/Components/MenuDialog.cs

@ -318,6 +318,8 @@ namespace Fungus
Text textComponent = button.GetComponentInChildren<Text>();
if (textComponent != null)
{
text = TextVariationHandler.SelectVariations(text);
textComponent.text = text;
}
button.onClick.AddListener(action);

3
Assets/Fungus/Scripts/Components/Writer.cs

@ -928,7 +928,8 @@ namespace Fungus
// If this clip is null then WriterAudio will play the default sound effect (if any)
NotifyStart(audioClip);
string tokenText = content;
string tokenText = TextVariationHandler.SelectVariations(content);
if (waitForInput)
{
tokenText += "{wi}";

118
Assets/Fungus/Scripts/Utils/TextVariationHandler.cs

@ -0,0 +1,118 @@
using System.Collections.Generic;
using System.Text;
using System.Text.RegularExpressions;
namespace Fungus
{
/// <summary>
/// Handles replacing vary text segments. Keeps history of previous replacements to allow for ordered
/// sequence of variation. Inspired by https://github.com/inkle/ink/blob/master/Documentation/WritingWithInk.md#6-variable-text
///
/// [] mark the bounds of the vary section
/// | divide elements within the variation
///
/// Default behaviour is to show one element after another and hold the final element. Such that [a|b|c] will show
/// a the first time it is parsed, b the second and every subsequent time it will show c.
///
/// This behaviour can be modified with certain characters at the start of the [], eg. [&a|b|c];
/// - & does not hold the final element it wraps back around to the begining in a looping fashion
/// - ! does not hold the final element, it instead returns empty for the varying section
/// - ~ chooses a random element every time it is encountered
/// </summary>
public static class TextVariationHandler
{
static Dictionary<int, int> hashedSections = new Dictionary<int, int>();
static StringBuilder sb = new StringBuilder();
const string pattern = @"\[([^]]+?)\]";
static Regex r = new Regex(pattern);
private enum VaryType
{
Sequence,
Cycle,
Once,
Random
}
static public string SelectVariations(string input)
{
sb.Length = 0;
sb.Append(input);
// Match the regular expression pattern against a text string.
var results = r.Matches(input);
for (int i = 0; i < results.Count; i++)
{
Match match = results[i];
//determine type
VaryType t = VaryType.Sequence;
var typedIndicatingChar = match.Value[1];
switch (typedIndicatingChar)
{
case '~':
t = VaryType.Random;
break;
case '&':
t = VaryType.Cycle;
break;
case '!':
t = VaryType.Once;
break;
default:
break;
}
//explode and remove the control char
int startSubStrIndex = t != VaryType.Sequence ? 2 : 1;
int subStrLen = match.Value.Length - 1 - startSubStrIndex;
var exploded = match.Value.Substring(startSubStrIndex, subStrLen).Split('|');
string selected = string.Empty;
//fetched hashed value
int index = -1;
int key = input.GetHashCode() ^ match.Value.GetHashCode();
int foundVal = 0;
if(hashedSections.TryGetValue(key, out foundVal))
{
index = foundVal;
}
index++;
switch (t)
{
case VaryType.Sequence:
index = UnityEngine.Mathf.Min(index, exploded.Length - 1);
break;
case VaryType.Cycle:
index = index % exploded.Length;
break;
case VaryType.Once:
//clamp to 1 more than options
index = UnityEngine.Mathf.Min(index, exploded.Length);
break;
case VaryType.Random:
index = UnityEngine.Random.Range(0, exploded.Length - 1);
break;
default:
break;
}
//update hashed value
hashedSections[key] = index;
//selected updated if valid
if(index >=0 && index < exploded.Length)
selected = exploded[index];
sb.Replace(match.Value, selected);
}
return sb.ToString();
}
}
}

11
Assets/Fungus/Scripts/Utils/TextVariationHandler.cs.meta

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: eb68f617801367f4dbfcd7f01911d7eb
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

8
Assets/FungusExamples/VariationText.meta

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 8ed4c59893b9d8043bfb0fdb06ae6ff5
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

1341
Assets/FungusExamples/VariationText/TextVariation.unity

File diff suppressed because it is too large Load Diff

7
Assets/FungusExamples/VariationText/TextVariation.unity.meta

@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: 7472e7497ac4ef84b888b1393faf2a30
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
Loading…
Cancel
Save