Browse Source

Merge branch 'master' into UnityReorderable

master
desktop-maesty/steve 7 years ago
parent
commit
2a10661a39
  1. 9
      Assets/Fungus/Docs/CHANGELOG.txt
  2. 1
      Assets/Fungus/Scripts/Commands/Menu.cs
  3. 2
      Assets/Fungus/Scripts/Components/MenuDialog.cs
  4. 3
      Assets/Fungus/Scripts/Components/Writer.cs
  5. 4
      Assets/Fungus/Scripts/Editor/HierarchyIcons.cs
  6. 230
      Assets/Fungus/Scripts/Utils/TextVariationHandler.cs
  7. 11
      Assets/Fungus/Scripts/Utils/TextVariationHandler.cs.meta
  8. 8
      Assets/FungusExamples/VariationText.meta
  9. 1341
      Assets/FungusExamples/VariationText/TextVariation.unity
  10. 7
      Assets/FungusExamples/VariationText/TextVariation.unity.meta
  11. 8
      Assets/Tests/StringSubstitution/Editor.meta
  12. 114
      Assets/Tests/StringSubstitution/Editor/FungusTextVariationSelectionTests.cs
  13. 11
      Assets/Tests/StringSubstitution/Editor/FungusTextVariationSelectionTests.cs.meta
  14. 9
      Assets/UnityTestTools/IntegrationTestsFramework/TestRunner/Editor/IntegrationTestsRunnerWindow.cs
  15. 15
      Assets/UnityTestTools/IntegrationTestsFramework/TestRunner/Editor/PlatformRunner/PlayerSettingConfigurator.cs
  16. 2
      Docs/Doxyfile
  17. 9
      Docs/fungus_docs/change_log.md
  18. 39
      Packages/manifest.json

9
Assets/Fungus/Docs/CHANGELOG.txt

@ -2,6 +2,15 @@ Changelog {#changelog}
=========
[TOC]
v3.9.1 {#v3_9_1}
======
## Added
- Text Variation Handler: Adds Ink-style text variation in Say, Menu and Conversation commands. #695
## Fixed
- Fixed Reorderable List control errors in 2018.2. Compatible with 2017.4, 2018.1 2018.2 #697
v3.9.0 {#v3_9_0}
======

1
Assets/Fungus/Scripts/Commands/Menu.cs

@ -17,6 +17,7 @@ namespace Fungus
public class Menu : Command, ILocalizable
{
[Tooltip("Text to display on the menu button")]
[TextArea()]
[SerializeField] protected string text = "Option Text";
[Tooltip("Notes about the option text for other authors, localization, etc.")]

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}";

4
Assets/Fungus/Scripts/Editor/HierarchyIcons.cs

@ -31,7 +31,11 @@ namespace Fungus
{
initalHierarchyCheckFlag = true;
EditorApplication.hierarchyWindowItemOnGUI += HierarchyIconCallback;
#if UNITY_2018_1_OR_NEWER
EditorApplication.hierarchyChanged += HierarchyChanged;
#else
EditorApplication.hierarchyWindowChanged += HierarchyChanged;
#endif
}
//track all gameobjectIds that have flowcharts on them

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

@ -0,0 +1,230 @@
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.
///
/// Empty sections are allowed, such that [a||c], on second showing it will have 0 characters.
///
/// Supports nested sections, that are only evaluated if their parent element is chosen.
///
/// 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
{
public class Section
{
public VaryType type = VaryType.Sequence;
public enum VaryType
{
Sequence,
Cycle,
Once,
Random
}
public string entire = string.Empty;
public List<string> elements = new List<string>();
public string Select(ref int index)
{
switch (type)
{
case VaryType.Sequence:
index = UnityEngine.Mathf.Min(index, elements.Count - 1);
break;
case VaryType.Cycle:
index = index % elements.Count;
break;
case VaryType.Once:
//clamp to 1 more than options
index = UnityEngine.Mathf.Min(index, elements.Count);
break;
case VaryType.Random:
index = UnityEngine.Random.Range(0, elements.Count);
break;
default:
break;
}
if (index >= 0 && index < elements.Count)
return elements[index];
return string.Empty;
}
}
static Dictionary<int, int> hashedSections = new Dictionary<int, int>();
static public void ClearHistory()
{
hashedSections.Clear();
}
/// <summary>
/// Simple parser to extract depth matched [].
///
/// Such that a string of "[Hail and well met|Hello|[Good |]Morning] Traveler" will return
/// "[Hail and well met|Hello|[Good |]Morning]"
/// and string of "Hail and well met|Hello|[Good |]Morning"
/// will return [Good |]
/// </summary>
/// <param name="input"></param>
/// <param name="varyingSections"></param>
/// <returns></returns>
static public bool TokenizeVarySections(string input, List<Section> varyingSections)
{
varyingSections.Clear();
int currentDepth = 0;
int curStartIndex = 0;
int curPipeIndex = 0;
Section curSection = null;
for (int i = 0; i < input.Length; i++)
{
switch (input[i])
{
case '[':
if (currentDepth == 0)
{
curSection = new Section();
varyingSections.Add(curSection);
//determine type and skip control char
var typedIndicatingChar = input[i + 1];
switch (typedIndicatingChar)
{
case '~':
curSection.type = Section.VaryType.Random;
break;
case '&':
curSection.type = Section.VaryType.Cycle;
break;
case '!':
curSection.type = Section.VaryType.Once;
break;
default:
break;
}
//mark start
curStartIndex = i;
curPipeIndex = i + 1;
}
currentDepth++;
break;
case ']':
if (currentDepth == 1)
{
//extract, including the ]
curSection.entire = input.Substring(curStartIndex, i - curStartIndex + 1);
//close an element if we started one
if (curStartIndex != curPipeIndex - 1)
{
curSection.elements.Add(input.Substring(curPipeIndex, i - curPipeIndex));
}
//if has control var, clean first element
if(curSection.type != Section.VaryType.Sequence)
{
curSection.elements[0] = curSection.elements[0].Substring(1);
}
}
currentDepth--;
break;
case '|':
if (currentDepth == 1)
{
//split
curSection.elements.Add(input.Substring(curPipeIndex, i - curPipeIndex));
//over the | on the next one
curPipeIndex = i + 1;
}
break;
default:
break;
}
}
return varyingSections.Count > 0;
}
/// <summary>
/// Uses the results of a run of tokenisation to choose the appropriate elements
/// </summary>
/// <param name="input"></param>
/// <param name="parentHash">When called recursively, we pass down the current objects hash so as to
/// avoid similar sub /sub sub/ etc. variations</param>
/// <returns></returns>
static public string SelectVariations(string input, int parentHash = 0)
{
// Match the regular expression pattern against a text string.
List<Section> sections = new List<Section>();
bool foundSections = TokenizeVarySections(input, sections);
if (!foundSections)
return input;
StringBuilder sb = new StringBuilder();
sb.Length = 0;
sb.Append(input);
for (int i = 0; i < sections.Count; i++)
{
var curSection = sections[i];
string selected = string.Empty;
//fetched hashed value
int index = -1;
//as input and entire can be the same thing we need to shuffle these bits
//we use some xorshift style mixing
int inputHash = input.GetHashCode();
inputHash ^= inputHash << 13;
int curSecHash = curSection.entire.GetHashCode();
curSecHash ^= curSecHash >> 17;
int key = inputHash ^ curSecHash ^ parentHash;
int foundVal = 0;
if (hashedSections.TryGetValue(key, out foundVal))
{
index = foundVal;
}
index++;
selected = curSection.Select(ref index);
//update hashed value
hashedSections[key] = index;
//handle sub vary within selected section
selected = SelectVariations(selected, key);
//update with selecton
sb.Replace(curSection.entire, 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:

8
Assets/Tests/StringSubstitution/Editor.meta

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

114
Assets/Tests/StringSubstitution/Editor/FungusTextVariationSelectionTests.cs

@ -0,0 +1,114 @@
using UnityEngine;
using UnityEngine.TestTools;
using NUnit.Framework;
using System.Collections;
public class FungusTextVariationSelectionTests
{
[Test]
public void SimpleSequenceSelection()
{
Fungus.TextVariationHandler.ClearHistory();
string startingText = @"This is test [a|b|c]";
string startingTextA = @"This is test a";
string startingTextB = @"This is test b";
string startingTextC = @"This is test c";
string res = string.Empty;
res = Fungus.TextVariationHandler.SelectVariations(startingText);
Assert.AreEqual(res, startingTextA);
res = Fungus.TextVariationHandler.SelectVariations(startingText);
Assert.AreEqual(res, startingTextB);
res = Fungus.TextVariationHandler.SelectVariations(startingText);
Assert.AreEqual(res, startingTextC);
res = Fungus.TextVariationHandler.SelectVariations(startingText);
Assert.AreEqual(res, startingTextC);
}
[Test]
public void SimpleCycleSelection()
{
Fungus.TextVariationHandler.ClearHistory();
string startingText = @"This is test [&a|b|c]";
string startingTextA = @"This is test a";
string startingTextB = @"This is test b";
string startingTextC = @"This is test c";
string res = string.Empty;
res = Fungus.TextVariationHandler.SelectVariations(startingText);
Assert.AreEqual(res, startingTextA);
res = Fungus.TextVariationHandler.SelectVariations(startingText);
Assert.AreEqual(res, startingTextB);
res = Fungus.TextVariationHandler.SelectVariations(startingText);
Assert.AreEqual(res, startingTextC);
res = Fungus.TextVariationHandler.SelectVariations(startingText);
Assert.AreEqual(res, startingTextA);
res = Fungus.TextVariationHandler.SelectVariations(startingText);
Assert.AreEqual(res, startingTextB);
res = Fungus.TextVariationHandler.SelectVariations(startingText);
Assert.AreEqual(res, startingTextC);
}
[Test]
public void SimpleOnceSelection()
{
Fungus.TextVariationHandler.ClearHistory();
string startingText = @"This is test [!a|b|c]";
string startingTextA = @"This is test a";
string startingTextB = @"This is test b";
string startingTextC = @"This is test c";
string startingTextD = @"This is test ";
string res = string.Empty;
res = Fungus.TextVariationHandler.SelectVariations(startingText);
Assert.AreEqual(res, startingTextA);
res = Fungus.TextVariationHandler.SelectVariations(startingText);
Assert.AreEqual(res, startingTextB);
res = Fungus.TextVariationHandler.SelectVariations(startingText);
Assert.AreEqual(res, startingTextC);
res = Fungus.TextVariationHandler.SelectVariations(startingText);
Assert.AreEqual(res, startingTextD);
res = Fungus.TextVariationHandler.SelectVariations(startingText);
Assert.AreEqual(res, startingTextD);
}
[Test]
public void NestedSelection()
{
Fungus.TextVariationHandler.ClearHistory();
string startingText = @"This is test [a||sub [~a|b]|[!b|[~c|d]]]";
string startingTextA = @"This is test a";
string startingTextBlank = @"This is test ";
string startingTextSubA = @"This is test sub a";
string startingTextSubB = @"This is test sub b";
string startingTextB = @"This is test b";
string startingTextC = @"This is test c";
string startingTextD = @"This is test d";
string res = string.Empty;
res = Fungus.TextVariationHandler.SelectVariations(startingText);
Assert.AreEqual(res, startingTextA);
res = Fungus.TextVariationHandler.SelectVariations(startingText);
Assert.AreEqual(res, startingTextBlank);
res = Fungus.TextVariationHandler.SelectVariations(startingText);
if(res != startingTextSubA && res != startingTextSubB)
{
Assert.Fail();
}
res = Fungus.TextVariationHandler.SelectVariations(startingText);
Assert.AreEqual(res, startingTextB);
res = Fungus.TextVariationHandler.SelectVariations(startingText);
if (res != startingTextC && res != startingTextD)
{
Assert.Fail();
}
}
}

11
Assets/Tests/StringSubstitution/Editor/FungusTextVariationSelectionTests.cs.meta

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

9
Assets/UnityTestTools/IntegrationTestsFramework/TestRunner/Editor/IntegrationTestsRunnerWindow.cs

@ -59,8 +59,13 @@ namespace UnityTest
{
EditorApplication.hierarchyWindowItemOnGUI -= OnHierarchyWindowItemDraw;
EditorApplication.hierarchyWindowItemOnGUI += OnHierarchyWindowItemDraw;
#if UNITY_2018_1_OR_NEWER
EditorApplication.hierarchyChanged -= OnHierarchyChangeUpdate;
EditorApplication.hierarchyChanged += OnHierarchyChangeUpdate;
#else
EditorApplication.hierarchyWindowChanged -= OnHierarchyChangeUpdate;
EditorApplication.hierarchyWindowChanged += OnHierarchyChangeUpdate;
#endif
EditorApplication.update -= BackgroundSceneChangeWatch;
EditorApplication.update += BackgroundSceneChangeWatch;
#if UNITY_2017_2_OR_NEWER
@ -86,7 +91,11 @@ namespace UnityTest
{
EditorApplication.hierarchyWindowItemOnGUI -= OnHierarchyWindowItemDraw;
EditorApplication.update -= BackgroundSceneChangeWatch;
#if UNITY_2018_1_OR_NEWER
EditorApplication.hierarchyChanged -= OnHierarchyChangeUpdate;
#else
EditorApplication.hierarchyWindowChanged -= OnHierarchyChangeUpdate;
#endif
#if UNITY_2017_2_OR_NEWER
EditorApplication.playModeStateChanged -= OnPlaymodeStateChanged;
#else

15
Assets/UnityTestTools/IntegrationTestsFramework/TestRunner/Editor/PlatformRunner/PlayerSettingConfigurator.cs

@ -18,7 +18,12 @@ namespace UnityTest
private ResolutionDialogSetting m_DisplayResolutionDialog;
private bool m_RunInBackground;
#if UNITY_2018_1_OR_NEWER
private FullScreenMode m_FullScreen;
#else
private bool m_FullScreen;
#endif
private bool m_ResizableWindow;
private readonly List<string> m_TempFileList = new List<string>();
@ -34,9 +39,13 @@ namespace UnityTest
m_RunInBackground = PlayerSettings.runInBackground;
PlayerSettings.runInBackground = true;
#if UNITY_2018_1_OR_NEWER
m_FullScreen = PlayerSettings.fullScreenMode;
PlayerSettings.fullScreenMode = FullScreenMode.Windowed;
#else
m_FullScreen = PlayerSettings.defaultIsFullScreen;
PlayerSettings.defaultIsFullScreen = false;
#endif
m_ResizableWindow = PlayerSettings.resizableWindow;
PlayerSettings.resizableWindow = true;
@ -44,7 +53,11 @@ namespace UnityTest
public void RevertSettingsChanges()
{
#if UNITY_2018_1_OR_NEWER
PlayerSettings.fullScreenMode = m_FullScreen;
#else
PlayerSettings.defaultIsFullScreen = m_FullScreen;
#endif
PlayerSettings.runInBackground = m_RunInBackground;
PlayerSettings.displayResolutionDialog = m_DisplayResolutionDialog;
PlayerSettings.resizableWindow = m_ResizableWindow;

2
Docs/Doxyfile

@ -38,7 +38,7 @@ PROJECT_NAME = Fungus
# could be handy for archiving the generated documentation or if some version
# control system is used.
PROJECT_NUMBER = v3.9.0
PROJECT_NUMBER = v3.9.1
# Using the PROJECT_BRIEF tag one can provide an optional one line description
# for a project that appears at the top of each page and should give viewer a

9
Docs/fungus_docs/change_log.md

@ -2,6 +2,15 @@ Changelog {#changelog}
=========
[TOC]
v3.9.1 {#v3_9_1}
======
## Added
- Text Variation Handler: Adds Ink-style text variation in Say, Menu and Conversation commands. #695
## Fixed
- Fixed Reorderable List control errors in 2018.2. Compatible with 2017.4, 2018.1 2018.2 #697
v3.9.0 {#v3_9_0}
======

39
Packages/manifest.json

@ -1,4 +1,39 @@
{
"dependencies": {
}
"dependencies": {
"com.unity.ads": "2.0.8",
"com.unity.analytics": "2.0.16",
"com.unity.package-manager-ui": "1.9.11",
"com.unity.purchasing": "2.0.3",
"com.unity.textmeshpro": "1.2.4",
"com.unity.modules.ai": "1.0.0",
"com.unity.modules.animation": "1.0.0",
"com.unity.modules.assetbundle": "1.0.0",
"com.unity.modules.audio": "1.0.0",
"com.unity.modules.cloth": "1.0.0",
"com.unity.modules.director": "1.0.0",
"com.unity.modules.imageconversion": "1.0.0",
"com.unity.modules.imgui": "1.0.0",
"com.unity.modules.jsonserialize": "1.0.0",
"com.unity.modules.particlesystem": "1.0.0",
"com.unity.modules.physics": "1.0.0",
"com.unity.modules.physics2d": "1.0.0",
"com.unity.modules.screencapture": "1.0.0",
"com.unity.modules.terrain": "1.0.0",
"com.unity.modules.terrainphysics": "1.0.0",
"com.unity.modules.tilemap": "1.0.0",
"com.unity.modules.ui": "1.0.0",
"com.unity.modules.uielements": "1.0.0",
"com.unity.modules.umbra": "1.0.0",
"com.unity.modules.unityanalytics": "1.0.0",
"com.unity.modules.unitywebrequest": "1.0.0",
"com.unity.modules.unitywebrequestassetbundle": "1.0.0",
"com.unity.modules.unitywebrequestaudio": "1.0.0",
"com.unity.modules.unitywebrequesttexture": "1.0.0",
"com.unity.modules.unitywebrequestwww": "1.0.0",
"com.unity.modules.vehicles": "1.0.0",
"com.unity.modules.video": "1.0.0",
"com.unity.modules.vr": "1.0.0",
"com.unity.modules.wind": "1.0.0",
"com.unity.modules.xr": "1.0.0"
}
}

Loading…
Cancel
Save