added yarn spinner package
This commit is contained in:
@@ -0,0 +1 @@
|
||||
Text Animator for Yarn Spinner is distributed under the terms of the Unity Asset Store Terms of Service and End User License Agreement, which is available here: https://unity.com/legal/as-terms.
|
||||
@@ -0,0 +1,14 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 43e0407e7e32e48a1ad5d779df956458
|
||||
TextScriptImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
AssetOrigin:
|
||||
serializedVersion: 1
|
||||
productId: 267061
|
||||
packageName: Yarn Spinner+ for Unity, the friendly dialogue and narrative tool
|
||||
packageVersion: 3.2.8
|
||||
assetPath: Packages/dev.yarnspinner.unity.addons.textanimator/LICENSE.md
|
||||
uploadId: 968678
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 35a8b2b68857e4506ad2ed5108fe11b8
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
+47
@@ -0,0 +1,47 @@
|
||||
/*
|
||||
Text Animator for Yarn Spinner is licensed to you under the terms found in the file LICENSE.md.
|
||||
*/
|
||||
|
||||
#nullable enable
|
||||
namespace Yarn.Unity.Addons.TextAnimatorIntegration
|
||||
{
|
||||
using System.Collections;
|
||||
using UnityEngine;
|
||||
#if YS_USE_TEXT_ANIMATOR_2
|
||||
using Febucci.UI.Core;
|
||||
using Febucci.UI.Core.Parsing;
|
||||
using Febucci.UI.Actions;
|
||||
|
||||
[System.Serializable]
|
||||
public class ActionMarkupAction : ActionScriptableBase
|
||||
{
|
||||
private TextAnimatorYarnTypewriter? ytw;
|
||||
public override IEnumerator DoAction(ActionMarker action, TypewriterCore typewriter, TypingInfo typingInfo)
|
||||
{
|
||||
if (ytw == null)
|
||||
{
|
||||
ytw = typewriter.GetComponentInParent<TextAnimatorYarnTypewriter>();
|
||||
}
|
||||
|
||||
if (ytw != null)
|
||||
{
|
||||
ytw.StartMarkup(action.index);
|
||||
|
||||
while (!ytw.ActionMarkupFinishedProcessing)
|
||||
{
|
||||
yield return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#else
|
||||
using ActionScriptableBase = UnityEngine.ScriptableObject;
|
||||
public class ActionMarkupAction : ActionScriptableBase
|
||||
{
|
||||
#pragma warning disable CS8618
|
||||
public string TagID => tagID;
|
||||
public string tagID;
|
||||
#pragma warning restore CS8618
|
||||
}
|
||||
#endif
|
||||
}
|
||||
+18
@@ -0,0 +1,18 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 92124a891cda04bf9a84ebd300c4ec16
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
AssetOrigin:
|
||||
serializedVersion: 1
|
||||
productId: 267061
|
||||
packageName: Yarn Spinner+ for Unity, the friendly dialogue and narrative tool
|
||||
packageVersion: 3.2.8
|
||||
assetPath: Packages/dev.yarnspinner.unity.addons.textanimator/Scripts/ActionMarkupAction.cs
|
||||
uploadId: 968678
|
||||
+8
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 35e4f4da531bc49359e2558b33e94a2f
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
+70
@@ -0,0 +1,70 @@
|
||||
/*
|
||||
Text Animator for Yarn Spinner is licensed to you under the terms found in the file LICENSE.md.
|
||||
*/
|
||||
|
||||
#if YS_USE_TEXT_ANIMATOR_2 || YS_USE_TEXT_ANIMATOR_3
|
||||
#define USE_TEXT_ANIMATOR
|
||||
#endif
|
||||
|
||||
namespace Yarn.Unity.Addons.TextAnimatorIntegration.Editor
|
||||
{
|
||||
#nullable enable
|
||||
#if USE_TEXT_ANIMATOR
|
||||
using UnityEngine;
|
||||
using UnityEditor;
|
||||
using UnityEngine.EventSystems;
|
||||
|
||||
// Literally copy-pasted from YS, just with a different menuitem and guid
|
||||
public static class CreateTextAnimatorDialogueRunnerMenuItem
|
||||
{
|
||||
// gonna have to change this so that it uses a different guid for each one
|
||||
// which sucks but oh well
|
||||
#if YS_USE_TEXT_ANIMATOR_3
|
||||
const string DialogueRunnerPrefabGUID = "cd09801223b5f4504a921d33ef1ff98c";
|
||||
#elif YS_USE_TEXT_ANIMATOR_2
|
||||
const string DialogueRunnerPrefabGUID = "eeb327a65c4bc4376ae432ce641f04af";
|
||||
#endif
|
||||
|
||||
/// <summary>
|
||||
/// Instantiates the Dialogue System prefab in the currently active scene,
|
||||
/// and returns the created <see cref="DialogueRunner"/>.
|
||||
/// </summary>
|
||||
/// <returns>A newly created <see cref="DialogueRunner"/>.</returns>
|
||||
/// <exception cref="System.InvalidOperationException">Thrown when the
|
||||
/// Dialogue System prefab cannot be found in the Yarn Spinner
|
||||
/// package.</exception>
|
||||
[MenuItem("GameObject/Yarn Spinner/Dialogue System with Text Animator")]
|
||||
public static DialogueRunner CreateDialogueRunner()
|
||||
{
|
||||
string assetPath = AssetDatabase.GUIDToAssetPath(DialogueRunnerPrefabGUID);
|
||||
var prefabAsset = AssetDatabase.LoadAssetAtPath<GameObject>(assetPath);
|
||||
|
||||
if (prefabAsset == null)
|
||||
{
|
||||
throw new System.InvalidOperationException(
|
||||
$"Can't create a new Dialogue System: Can't find the prefab to create a Dialogue System from."
|
||||
);
|
||||
}
|
||||
|
||||
var instantiatedPrefab = (GameObject)PrefabUtility.InstantiatePrefab(prefabAsset);
|
||||
|
||||
#if UNITY_2023_1_OR_NEWER
|
||||
var eventSystems = Object.FindObjectsByType<EventSystem>(FindObjectsSortMode.None);
|
||||
#else
|
||||
var eventSystems = Object.FindObjectsOfType<EventSystem>();
|
||||
#endif
|
||||
|
||||
if (eventSystems.Length > 1)
|
||||
{
|
||||
// At least one other event system is present in the scene. Turn off
|
||||
// the one that came with the prefab - it's not needed.
|
||||
var instantiatedEventSystem = instantiatedPrefab.GetComponentInChildren<EventSystem>();
|
||||
|
||||
instantiatedEventSystem.gameObject.SetActive(false);
|
||||
}
|
||||
|
||||
return instantiatedPrefab.GetComponent<DialogueRunner>();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
+9
@@ -0,0 +1,9 @@
|
||||
fileFormatVersion: 2
|
||||
guid: ff74191f08b6d4d5488de8f2e633dfd4
|
||||
AssetOrigin:
|
||||
serializedVersion: 1
|
||||
productId: 267061
|
||||
packageName: Yarn Spinner+ for Unity, the friendly dialogue and narrative tool
|
||||
packageVersion: 3.2.8
|
||||
assetPath: Packages/dev.yarnspinner.unity.addons.textanimator/Scripts/Editor/CreateTextAnimatorDialogueRunnerMenuItem.cs
|
||||
uploadId: 968678
|
||||
+6
@@ -0,0 +1,6 @@
|
||||
<engine:UXML xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:engine="UnityEngine.UIElements" xmlns:editor="UnityEditor.UIElements" noNamespaceSchemaLocation="../../../../UIElementsSchema/UIElements.xsd" editor-extension-mode="False">
|
||||
<Style src="project://database/Packages/dev.yarnspinner.unity.addons.textanimator/Scripts/Editor/TextAnimatorConfigurationWindow.uss?fileID=7433441132597879392&guid=e52662955dcee47bbbe24c3602e61bf7&type=3#TextAnimatorConfigurationWindow" />
|
||||
<engine:Label text="Text Animator for Unity is installed and Yarn Spinner is correctly configured to use it." style="white-space: normal; -unity-text-align: upper-left; margin-bottom: 4px; flex-wrap: wrap; margin-left: 4px;" />
|
||||
<engine:Label text="The default Yarn Spinner action has not been registered with Text Animator yet. Depending on your setup this may not be an issue, if you want to register it you can here. Otherwise each typewriter will need to ensure their own action is registered." name="definedLabel" style="white-space: normal; -unity-text-align: upper-left; margin-left: 4px;" />
|
||||
<engine:Button text="Register action" name="definedButton" style="margin-left: 8px; margin-right: 8px;" />
|
||||
</engine:UXML>
|
||||
+17
@@ -0,0 +1,17 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 02d739c3d6bb545fdb6d4bf14bf07822
|
||||
ScriptedImporter:
|
||||
internalIDToNameTable: []
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
script: {fileID: 13804, guid: 0000000000000000e000000000000000, type: 0}
|
||||
AssetOrigin:
|
||||
serializedVersion: 1
|
||||
productId: 267061
|
||||
packageName: Yarn Spinner+ for Unity, the friendly dialogue and narrative tool
|
||||
packageVersion: 3.2.8
|
||||
assetPath: Packages/dev.yarnspinner.unity.addons.textanimator/Scripts/Editor/InstalledAndDefinedElement.uxml
|
||||
uploadId: 968678
|
||||
+7
@@ -0,0 +1,7 @@
|
||||
<engine:UXML xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:engine="UnityEngine.UIElements" xmlns:editor="UnityEditor.UIElements" noNamespaceSchemaLocation="../../../../UIElementsSchema/UIElements.xsd" editor-extension-mode="False">
|
||||
<Style src="project://database/Packages/dev.yarnspinner.unity.addons.textanimator/Scripts/Editor/TextAnimatorConfigurationWindow.uss?fileID=7433441132597879392&guid=e52662955dcee47bbbe24c3602e61bf7&type=3#TextAnimatorConfigurationWindow" />
|
||||
<engine:Label text="Text Animator for Unity is installed but the scripting defines we use are not configured." style="overflow: visible; flex-wrap: nowrap; white-space: normal; padding-bottom: 8px; margin-bottom: 4px;" />
|
||||
<engine:Label text="This will add the necessary scripting defines to the following build targets:" style="overflow: visible; flex-wrap: nowrap; white-space: normal;" />
|
||||
<engine:VisualElement name="scriptingToggleContainer" style="flex-grow: 1;" />
|
||||
<engine:Button text="Add Scripting Defines" name="scriptingButton" style="margin-left: 8px; margin-right: 8px;" />
|
||||
</engine:UXML>
|
||||
+17
@@ -0,0 +1,17 @@
|
||||
fileFormatVersion: 2
|
||||
guid: b2fe556531a6644c0b405d6482d9de4f
|
||||
ScriptedImporter:
|
||||
internalIDToNameTable: []
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
script: {fileID: 13804, guid: 0000000000000000e000000000000000, type: 0}
|
||||
AssetOrigin:
|
||||
serializedVersion: 1
|
||||
productId: 267061
|
||||
packageName: Yarn Spinner+ for Unity, the friendly dialogue and narrative tool
|
||||
packageVersion: 3.2.8
|
||||
assetPath: Packages/dev.yarnspinner.unity.addons.textanimator/Scripts/Editor/InstalledAndNotDefinedElement.uxml
|
||||
uploadId: 968678
|
||||
+5
@@ -0,0 +1,5 @@
|
||||
<engine:UXML xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:engine="UnityEngine.UIElements" xmlns:editor="UnityEditor.UIElements" noNamespaceSchemaLocation="../../../../UIElementsSchema/UIElements.xsd" editor-extension-mode="False">
|
||||
<Style src="project://database/Packages/dev.yarnspinner.unity.addons.textanimator/Scripts/Editor/TextAnimatorConfigurationWindow.uss?fileID=7433441132597879392&guid=e52662955dcee47bbbe24c3602e61bf7&type=3#TextAnimatorConfigurationWindow" />
|
||||
<engine:Label text="Text Animator for Unity is not installed. You will need to install it before you can use it with Yarn Spinner." style="white-space: normal; margin-left: 4px; flex-wrap: wrap;" />
|
||||
<engine:Button text="Get Text Animator for Unity" name="notInstalledButton" style="margin-left: 8px; margin-right: 8px; margin-bottom: 4px;" />
|
||||
</engine:UXML>
|
||||
+17
@@ -0,0 +1,17 @@
|
||||
fileFormatVersion: 2
|
||||
guid: c39c92b7ce46b46329bda933bb30f5fc
|
||||
ScriptedImporter:
|
||||
internalIDToNameTable: []
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
script: {fileID: 13804, guid: 0000000000000000e000000000000000, type: 0}
|
||||
AssetOrigin:
|
||||
serializedVersion: 1
|
||||
productId: 267061
|
||||
packageName: Yarn Spinner+ for Unity, the friendly dialogue and narrative tool
|
||||
packageVersion: 3.2.8
|
||||
assetPath: Packages/dev.yarnspinner.unity.addons.textanimator/Scripts/Editor/NotInstalledElement.uxml
|
||||
uploadId: 968678
|
||||
+551
@@ -0,0 +1,551 @@
|
||||
/*
|
||||
Text Animator for Yarn Spinner is licensed to you under the terms found in the file LICENSE.md.
|
||||
*/
|
||||
|
||||
#if YS_USE_TEXT_ANIMATOR_2 || YS_USE_TEXT_ANIMATOR_3
|
||||
#define USE_TEXT_ANIMATOR
|
||||
#endif
|
||||
|
||||
#nullable enable
|
||||
|
||||
namespace Yarn.Unity.Addons.TextAnimatorIntegration.Editor
|
||||
{
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UIElements;
|
||||
using UnityEditor.Build;
|
||||
using System.Collections.Generic;
|
||||
using System.Reflection;
|
||||
using System.Linq;
|
||||
|
||||
#if YS_USE_TEXT_ANIMATOR_2
|
||||
using Febucci.UI;
|
||||
using ActionScriptableBase = Febucci.UI.Actions.ActionScriptableBase;
|
||||
#elif YS_USE_TEXT_ANIMATOR_3
|
||||
using Febucci.TextAnimatorForUnity;
|
||||
using ActionScriptableBase = Febucci.TextAnimatorForUnity.Actions.Core.ActionScriptableBase;
|
||||
#else
|
||||
using ActionScriptableBase = UnityEngine.ScriptableObject;
|
||||
#endif
|
||||
|
||||
public class TextAnimatorConfigurationWindow : EditorWindow
|
||||
{
|
||||
private const string YSTA2Define = "YS_USE_TEXT_ANIMATOR_2";
|
||||
private const string YSTA3Define = "YS_USE_TEXT_ANIMATOR_3";
|
||||
|
||||
private const string TextAnimatorV2SettingsType = "Febucci.UI.TextAnimatorSettings";
|
||||
private const string TextAnimatorV3SettingsType = "Febucci.TextAnimatorForUnity.TextAnimatorSettings";
|
||||
|
||||
private const string TextAnimatorSettingsName = "TextAnimatorSettings";
|
||||
private const string TextAnimatorPageURL = "https://www.febucci.com/tools/text-animator-unity";
|
||||
private const string installedAndNotDefinedUXMLGuid = "b2fe556531a6644c0b405d6482d9de4f";
|
||||
private const string notInstalledUXMLGuid = "c39c92b7ce46b46329bda933bb30f5fc";
|
||||
private const string InstalledAndDefinedUXMLGuid = "02d739c3d6bb545fdb6d4bf14bf07822";
|
||||
|
||||
private const string TextAnimatorRunnerPrefabGuidV2 = "eeb327a65c4bc4376ae432ce641f04af";
|
||||
private const string TextAnimatorRunnerPrefabGuidV3 = "cd09801223b5f4504a921d33ef1ff98c";
|
||||
|
||||
private const string TextAnimatorRunnerPackageGuidV2 = "5a3687d8c4744405692bd44867d6ac58";
|
||||
private const string TextAnimatorRunnerPackageGuidV3 = "014e0ab0fc9ca4cd69ce3203bfe646f9";
|
||||
|
||||
// this is a terrible hack but seems to work
|
||||
// it will get all the possible build targets for whatever version of unity the package is installed in
|
||||
// this works because unity has kindly defined a whole bunch of public static build targets already
|
||||
// would be nicer to be able to go like `NamedBuildTarget.All` and have it return a list of them, but oh well
|
||||
private static List<NamedBuildTarget> AllBuildTargets
|
||||
{
|
||||
get
|
||||
{
|
||||
var targets = new List<NamedBuildTarget>();
|
||||
|
||||
// we have this because there are a few targets (like CloudRendering) that are redirected to a different target
|
||||
// and these change on a unity version basis so we can't just manually ignore them like we do with Unknown
|
||||
// so instead if we have run into a build target with a resolved name that we've already seen we ignore it
|
||||
var names = new HashSet<string>();
|
||||
|
||||
var fields = typeof(NamedBuildTarget).GetFields(BindingFlags.Public | BindingFlags.Static);
|
||||
foreach (var field in fields)
|
||||
{
|
||||
// so turns out weird things can happen when trying to set or get defines on unknown
|
||||
// plus it doesn't really mean anything so why bother, let's just skip it
|
||||
if (field.Name == "Unknown")
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
// if it isn't a NamedBuildTarget we ignore it
|
||||
if (field.FieldType == typeof(NamedBuildTarget))
|
||||
{
|
||||
var t = (NamedBuildTarget)field.GetValue(null);
|
||||
|
||||
// Stadia is deprecated and will throw an error if we
|
||||
// attempt to use it; ignore it
|
||||
if (t.TargetName == "Stadia")
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (names.Add(t.TargetName))
|
||||
{
|
||||
targets.Add(t);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return targets;
|
||||
}
|
||||
}
|
||||
|
||||
// Because we don't know if TextAnimator is installed we can't really safely add the scripting define
|
||||
// So this property does a check looking for the TextAnimator global settings in the resources folder
|
||||
// if we find something with it's name we then check if the name of the type is what we'd expect
|
||||
// this isn't perfect but seems to work pretty well and is mostly robust to change
|
||||
private bool IsTextAnimatorInstalled
|
||||
{
|
||||
get
|
||||
{
|
||||
var resources = Resources.LoadAll(TextAnimatorSettingsName);
|
||||
foreach (var resource in resources)
|
||||
{
|
||||
if (resource.GetType().ToString().EndsWith(TextAnimatorV2SettingsType))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else if (resource.GetType().ToString().EndsWith(TextAnimatorV3SettingsType))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private bool IsTextAnimatorV2Installed
|
||||
{
|
||||
get
|
||||
{
|
||||
var resources = Resources.LoadAll(TextAnimatorSettingsName);
|
||||
foreach (var resource in resources)
|
||||
{
|
||||
if (resource.GetType().ToString().EndsWith(TextAnimatorV2SettingsType))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private bool IsTextAnimatorV3Installed
|
||||
{
|
||||
get
|
||||
{
|
||||
var resources = Resources.LoadAll(TextAnimatorSettingsName);
|
||||
foreach (var resource in resources)
|
||||
{
|
||||
if (resource.GetType().ToString().EndsWith(TextAnimatorV3SettingsType))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private string? ScriptingDefine
|
||||
{
|
||||
get
|
||||
{
|
||||
if (IsTextAnimatorV2Installed)
|
||||
{
|
||||
return YSTA2Define;
|
||||
}
|
||||
else if (IsTextAnimatorV3Installed)
|
||||
{
|
||||
return YSTA3Define;
|
||||
}
|
||||
else
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void AddDefines(Dictionary<string, bool> filters)
|
||||
{
|
||||
var definitionSymbol = ScriptingDefine;
|
||||
if (string.IsNullOrEmpty(definitionSymbol))
|
||||
{
|
||||
Debug.LogWarning("Was unable to determine the valid scripting define for this version of Text Animator. Cannot add the necessary defines.");
|
||||
return;
|
||||
}
|
||||
foreach (var target in AllBuildTargets)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (filters.TryGetValue(target.TargetName, out var value))
|
||||
{
|
||||
if (value == false)
|
||||
{
|
||||
Debug.Log($"skipping {target.TargetName}");
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
PlayerSettings.GetScriptingDefineSymbols(target, out var defines);
|
||||
if (defines.Contains(definitionSymbol))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
else
|
||||
{
|
||||
var allSymbols = defines.ToList();
|
||||
allSymbols.Add(definitionSymbol);
|
||||
PlayerSettings.SetScriptingDefineSymbols(target, allSymbols.ToArray());
|
||||
}
|
||||
}
|
||||
catch (System.ArgumentException)
|
||||
{
|
||||
Debug.LogWarning($"{target.TargetName} is not supported");
|
||||
continue;
|
||||
}
|
||||
}
|
||||
this.Close();
|
||||
}
|
||||
|
||||
private enum InstallationState
|
||||
{
|
||||
InstalledAndDefined, InstalledAndNotDefined, NotInstalledAndNotDefined, NotInstalledAndDefined,
|
||||
}
|
||||
|
||||
private InstallationState installationState
|
||||
{
|
||||
get
|
||||
{
|
||||
#if USE_TEXT_ANIMATOR
|
||||
if (IsTextAnimatorInstalled)
|
||||
{
|
||||
return InstallationState.InstalledAndDefined;
|
||||
}
|
||||
return InstallationState.NotInstalledAndDefined;
|
||||
#else
|
||||
if (IsTextAnimatorInstalled)
|
||||
{
|
||||
return InstallationState.InstalledAndNotDefined;
|
||||
}
|
||||
return InstallationState.NotInstalledAndNotDefined;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
[SerializeField]
|
||||
private VisualTreeAsset? m_VisualTreeAsset = default;
|
||||
|
||||
[MenuItem("Window/Yarn Spinner/Text Animator Integration Configuration")]
|
||||
public static void OpenWindow()
|
||||
{
|
||||
TextAnimatorConfigurationWindow window = GetWindow<TextAnimatorConfigurationWindow>(true, "Yarn Spinner Text Animator Configuration", true);
|
||||
|
||||
var height = 438;
|
||||
|
||||
switch (window.installationState)
|
||||
{
|
||||
case InstallationState.NotInstalledAndDefined:
|
||||
goto case InstallationState.NotInstalledAndNotDefined;
|
||||
case InstallationState.NotInstalledAndNotDefined:
|
||||
height += 54;
|
||||
break;
|
||||
case InstallationState.InstalledAndDefined:
|
||||
if (TextAnimationActionState.DefaultActionIsRegistered() == TextAnimationActionState.RegistrationResult.NotRegistered)
|
||||
{
|
||||
height += 99;
|
||||
}
|
||||
else
|
||||
{
|
||||
height += 19;
|
||||
}
|
||||
break;
|
||||
case InstallationState.InstalledAndNotDefined:
|
||||
height += 63 + AllBuildTargets.Count * 19;
|
||||
break;
|
||||
}
|
||||
|
||||
window.minSize = new Vector2(512, height);
|
||||
window.maxSize = window.minSize;
|
||||
window.Show();
|
||||
}
|
||||
|
||||
public void CreateGUI()
|
||||
{
|
||||
VisualElement root = rootVisualElement;
|
||||
|
||||
if (m_VisualTreeAsset == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var installation = installationState;
|
||||
string activeContainerGUID = installation switch
|
||||
{
|
||||
InstallationState.InstalledAndDefined => InstalledAndDefinedUXMLGuid,
|
||||
InstallationState.InstalledAndNotDefined => installedAndNotDefinedUXMLGuid,
|
||||
_ => notInstalledUXMLGuid,
|
||||
};
|
||||
|
||||
// Instantiate UXML
|
||||
VisualElement labelFromUXML = m_VisualTreeAsset.Instantiate();
|
||||
root.Add(labelFromUXML);
|
||||
|
||||
root.Q<TemplateContainer>().style.flexGrow = 1;
|
||||
|
||||
var tree = AssetDatabase.LoadAssetAtPath<VisualTreeAsset>(AssetDatabase.GUIDToAssetPath(activeContainerGUID));
|
||||
if (tree == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
var container = tree.CloneTree();
|
||||
root.Add(container);
|
||||
|
||||
switch (installation)
|
||||
{
|
||||
case InstallationState.InstalledAndDefined:
|
||||
CreateInstalledAndDefinedGUI(container);
|
||||
break;
|
||||
|
||||
case InstallationState.InstalledAndNotDefined:
|
||||
CreateInstalledAndNotDefinedGUI(container);
|
||||
break;
|
||||
|
||||
case InstallationState.NotInstalledAndDefined:
|
||||
goto case InstallationState.NotInstalledAndNotDefined;
|
||||
case InstallationState.NotInstalledAndNotDefined:
|
||||
CreateNotInstalledGUI(container);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
public void CreateInstalledAndNotDefinedGUI(VisualElement root)
|
||||
{
|
||||
var container = root.Q<VisualElement>("scriptingToggleContainer");
|
||||
if (container == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var button = root.Q<Button>("scriptingButton");
|
||||
if (button == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
Dictionary<string, bool> targetValues = new();
|
||||
foreach (var target in AllBuildTargets)
|
||||
{
|
||||
targetValues.Add(target.TargetName, true);
|
||||
|
||||
var targetName = target.TargetName;
|
||||
Toggle toogle = new Toggle(targetName);
|
||||
|
||||
toogle.name = targetName;
|
||||
toogle.style.marginLeft = 20;
|
||||
|
||||
toogle.SetValueWithoutNotify(true);
|
||||
container.Add(toogle);
|
||||
|
||||
toogle.RegisterValueChangedCallback((evt) =>
|
||||
{
|
||||
if (evt.currentTarget is not Toggle t)
|
||||
{
|
||||
return;
|
||||
}
|
||||
targetValues[t.name] = evt.newValue;
|
||||
});
|
||||
}
|
||||
|
||||
button.clicked += () =>
|
||||
{
|
||||
ExtractTextAnimatorPackage();
|
||||
AddDefines(targetValues);
|
||||
};
|
||||
}
|
||||
|
||||
private bool GetAssetExists(string guid)
|
||||
{
|
||||
return string.IsNullOrEmpty(AssetDatabase.GUIDToAssetPath(guid)) == false;
|
||||
}
|
||||
|
||||
#pragma warning disable IDE0051 // Private member is unused
|
||||
private bool ExtractPackageIfAssetNotPresent(string assetGUID, string packageGUID)
|
||||
{
|
||||
AssetDatabase.Refresh();
|
||||
if (GetAssetExists(assetGUID))
|
||||
{
|
||||
// The runner prefab already exists. Nothing left to do.
|
||||
Debug.Log("Not unpacking Text Animator for Yarn Spinner assets, because it's already in the project.");
|
||||
return false;
|
||||
}
|
||||
|
||||
var pathToPackage = AssetDatabase.GUIDToAssetPath(packageGUID);
|
||||
|
||||
if (pathToPackage == string.Empty)
|
||||
{
|
||||
Debug.LogError($"Failed to find the Text Animator for Yarn Spinner package file to extract!");
|
||||
return false;
|
||||
}
|
||||
|
||||
Debug.Log("Importing package.");
|
||||
AssetDatabase.ImportPackage(pathToPackage, false);
|
||||
|
||||
return true;
|
||||
}
|
||||
#pragma warning disable
|
||||
|
||||
private void ExtractTextAnimatorPackage()
|
||||
{
|
||||
if (IsTextAnimatorV2Installed)
|
||||
{
|
||||
ExtractPackageIfAssetNotPresent(TextAnimatorRunnerPrefabGuidV2, TextAnimatorRunnerPackageGuidV2);
|
||||
}
|
||||
else if (IsTextAnimatorV3Installed)
|
||||
{
|
||||
ExtractPackageIfAssetNotPresent(TextAnimatorRunnerPrefabGuidV3, TextAnimatorRunnerPackageGuidV3);
|
||||
}
|
||||
else
|
||||
{
|
||||
EditorUtility.DisplayDialog(
|
||||
"Unknown Version of TextAnimator",
|
||||
"We aren't able to detect which version of Text Animator you have installed. " +
|
||||
"This means we can't complete the installation. Please contact Yarn Spinner support for help.",
|
||||
"Close");
|
||||
}
|
||||
}
|
||||
|
||||
public void CreateInstalledAndDefinedGUI(VisualElement root)
|
||||
{
|
||||
// at this point we are fine to continue but might as well offer to see if the default action can be registered and do it
|
||||
var message = root.Q<Label>("definedLabel");
|
||||
var button = root.Q<Button>("definedButton");
|
||||
if (message == null || button == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (TextAnimationActionState.DefaultActionIsRegistered() == TextAnimationActionState.RegistrationResult.NotRegistered)
|
||||
{
|
||||
message.style.display = DisplayStyle.Flex;
|
||||
button.style.display = DisplayStyle.Flex;
|
||||
button.clicked += () =>
|
||||
{
|
||||
this.Close();
|
||||
TextAnimationActionState.RegisterDefaultAction();
|
||||
};
|
||||
}
|
||||
else
|
||||
{
|
||||
message.style.display = DisplayStyle.None;
|
||||
button.style.display = DisplayStyle.None;
|
||||
}
|
||||
}
|
||||
public void CreateNotInstalledGUI(VisualElement root)
|
||||
{
|
||||
// basically get the button
|
||||
// hook up the call
|
||||
var button = root.Q<Button>("notInstalledButton");
|
||||
if (button == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
button.clicked += GetTextAnimator;
|
||||
}
|
||||
|
||||
private void GetTextAnimator()
|
||||
{
|
||||
this.Close();
|
||||
Application.OpenURL(TextAnimatorConfigurationWindow.TextAnimatorPageURL);
|
||||
}
|
||||
}
|
||||
|
||||
class TextAnimationActionState
|
||||
{
|
||||
internal enum RegistrationResult
|
||||
{
|
||||
NotRegistered, Registered, ExistingRegistration, UnableToResolve,
|
||||
}
|
||||
|
||||
#if YS_USE_TEXT_ANIMATOR_2
|
||||
const string defaultActionGUID = "797c9181a760b4946ab39cc7d835909f";
|
||||
|
||||
internal static RegistrationResult IsActionRegistered(ActionScriptableBase action)
|
||||
{
|
||||
foreach (var registeredAction in TextAnimatorSettings.Instance.actions.defaultDatabase.Data)
|
||||
{
|
||||
if (registeredAction == null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
if (action.TagID == registeredAction.TagID)
|
||||
{
|
||||
if (action.GetType() == registeredAction.GetType())
|
||||
{
|
||||
return RegistrationResult.Registered;
|
||||
}
|
||||
return RegistrationResult.ExistingRegistration;
|
||||
}
|
||||
}
|
||||
return RegistrationResult.NotRegistered;
|
||||
}
|
||||
internal static RegistrationResult DefaultActionIsRegistered()
|
||||
{
|
||||
ActionMarkupAction? value;
|
||||
|
||||
var path = AssetDatabase.GUIDToAssetPath(defaultActionGUID);
|
||||
if (string.IsNullOrEmpty(path))
|
||||
{
|
||||
return RegistrationResult.UnableToResolve;
|
||||
}
|
||||
|
||||
value = AssetDatabase.LoadAssetAtPath<ActionMarkupAction>(path);
|
||||
if (value == null)
|
||||
{
|
||||
return RegistrationResult.UnableToResolve;
|
||||
}
|
||||
return IsActionRegistered(value);
|
||||
}
|
||||
internal static void RegisterDefaultAction()
|
||||
{
|
||||
ActionMarkupAction? value;
|
||||
|
||||
var path = AssetDatabase.GUIDToAssetPath(defaultActionGUID);
|
||||
if (string.IsNullOrEmpty(path))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
value = AssetDatabase.LoadAssetAtPath<ActionMarkupAction>(path);
|
||||
if (value == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
TextAnimatorSettings.Instance.actions.defaultDatabase.Add(value);
|
||||
}
|
||||
internal static void RegisterAction(ActionScriptableBase action)
|
||||
{
|
||||
TextAnimatorSettings.Instance.actions.defaultDatabase.Add(action);
|
||||
}
|
||||
#elif YS_USE_TEXT_ANIMATOR_3
|
||||
// in TA3 we have a custom typewriter so don't need to worry about the registration
|
||||
// so we can just say it's registered and otherwise move on with our life
|
||||
internal static RegistrationResult DefaultActionIsRegistered()
|
||||
{
|
||||
return RegistrationResult.Registered;
|
||||
}
|
||||
internal static void RegisterDefaultAction()
|
||||
{
|
||||
return;
|
||||
}
|
||||
#else
|
||||
internal static RegistrationResult DefaultActionIsRegistered() { return RegistrationResult.UnableToResolve; }
|
||||
internal static void RegisterDefaultAction() { return; }
|
||||
#endif
|
||||
}
|
||||
}
|
||||
+20
@@ -0,0 +1,20 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 68ffb26081e84448faf47d2dec707c3b
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences:
|
||||
- m_VisualTreeAsset: {fileID: 9197481963319205126, guid: b04973c1fd259487ebb3a4e5292b0c47,
|
||||
type: 3}
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
AssetOrigin:
|
||||
serializedVersion: 1
|
||||
productId: 267061
|
||||
packageName: Yarn Spinner+ for Unity, the friendly dialogue and narrative tool
|
||||
packageVersion: 3.2.8
|
||||
assetPath: Packages/dev.yarnspinner.unity.addons.textanimator/Scripts/Editor/TextAnimatorConfigurationWindow.cs
|
||||
uploadId: 968678
|
||||
+5
@@ -0,0 +1,5 @@
|
||||
.custom-label {
|
||||
font-size: 20px;
|
||||
-unity-font-style: bold;
|
||||
color: rgb(68, 138, 255);
|
||||
}
|
||||
+18
@@ -0,0 +1,18 @@
|
||||
fileFormatVersion: 2
|
||||
guid: e52662955dcee47bbbe24c3602e61bf7
|
||||
ScriptedImporter:
|
||||
internalIDToNameTable: []
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
script: {fileID: 12385, guid: 0000000000000000e000000000000000, type: 0}
|
||||
disableValidation: 0
|
||||
AssetOrigin:
|
||||
serializedVersion: 1
|
||||
productId: 267061
|
||||
packageName: Yarn Spinner+ for Unity, the friendly dialogue and narrative tool
|
||||
packageVersion: 3.2.8
|
||||
assetPath: Packages/dev.yarnspinner.unity.addons.textanimator/Scripts/Editor/TextAnimatorConfigurationWindow.uss
|
||||
uploadId: 968678
|
||||
+5
@@ -0,0 +1,5 @@
|
||||
<engine:UXML xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:engine="UnityEngine.UIElements" xmlns:editor="UnityEditor.UIElements" noNamespaceSchemaLocation="../../../../UIElementsSchema/UIElements.xsd" editor-extension-mode="False">
|
||||
<Style src="project://database/Packages/dev.yarnspinner.unity.addons.textanimator/Scripts/Editor/TextAnimatorConfigurationWindow.uss?fileID=7433441132597879392&guid=e52662955dcee47bbbe24c3602e61bf7&type=3#TextAnimatorConfigurationWindow" />
|
||||
<engine:VisualElement style="flex-grow: 1; background-image: url("project://database/Packages/dev.yarnspinner.unity.addons.textanimator/Scripts/Editor/banner.jpg?fileID=21300000&guid=a4bc00c6001e94d6d85534ee24530d57&type=3#banner"); min-width: 315px; min-height: 250px; background-position-x: center 0; background-position-y: center 0; -unity-background-scale-mode: scale-to-fit; flex-direction: column;" />
|
||||
<engine:Label text="Text Animator for Unity is a 3rd Party asset for creating gorgeous text effects." style="white-space: normal; margin-top: 2px; flex-wrap: wrap; -unity-text-align: upper-center; margin-bottom: 4px;" />
|
||||
</engine:UXML>
|
||||
+17
@@ -0,0 +1,17 @@
|
||||
fileFormatVersion: 2
|
||||
guid: b04973c1fd259487ebb3a4e5292b0c47
|
||||
ScriptedImporter:
|
||||
internalIDToNameTable: []
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
script: {fileID: 13804, guid: 0000000000000000e000000000000000, type: 0}
|
||||
AssetOrigin:
|
||||
serializedVersion: 1
|
||||
productId: 267061
|
||||
packageName: Yarn Spinner+ for Unity, the friendly dialogue and narrative tool
|
||||
packageVersion: 3.2.8
|
||||
assetPath: Packages/dev.yarnspinner.unity.addons.textanimator/Scripts/Editor/TextAnimatorConfigurationWindow.uxml
|
||||
uploadId: 968678
|
||||
+80
@@ -0,0 +1,80 @@
|
||||
using UnityEngine;
|
||||
using UnityEditor;
|
||||
using Yarn.Unity.Addons.TextAnimatorIntegration;
|
||||
using Yarn.Unity.Editor;
|
||||
using Yarn.Unity.Addons.TextAnimatorIntegration.Editor;
|
||||
|
||||
namespace Yarn.Unity.Addons.TextAnimatorIntegration
|
||||
{
|
||||
|
||||
#if YS_USE_TEXT_ANIMATOR_2
|
||||
[CustomEditor(typeof(TextAnimatorYarnTypewriter))]
|
||||
public class TextAnimatorTypewriterEditor : YarnEditor
|
||||
{
|
||||
public override void OnInspectorGUI()
|
||||
{
|
||||
DrawDefaultInspector();
|
||||
|
||||
var value = target as TextAnimatorYarnTypewriter;
|
||||
if (value == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (value.insertionAction == null)
|
||||
{
|
||||
if (value.tagMode != TagMode.TextAnimatorOnlyTags)
|
||||
{
|
||||
EditorGUILayout.HelpBox($"The tag mode is set to be {value.tagMode}, but {nameof(value.insertionAction)} is null. You must have an action configured to use this tag mode.", MessageType.Warning);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
var tagID = value.insertionAction.TagID ?? "NULL";
|
||||
var registrationStatus = TextAnimationActionState.IsActionRegistered(value.insertionAction);
|
||||
|
||||
switch (registrationStatus)
|
||||
{
|
||||
case TextAnimationActionState.RegistrationResult.ExistingRegistration:
|
||||
if (value.tagMode != TagMode.TextAnimatorOnlyTags)
|
||||
{
|
||||
EditorGUILayout.HelpBox($"There already exists a Text Animator action registered with tag id: \"{tagID}\". You must only have a single action registered for this tag.", MessageType.Warning);
|
||||
}
|
||||
break;
|
||||
|
||||
case TextAnimationActionState.RegistrationResult.NotRegistered:
|
||||
if (value.tagMode == TagMode.TextAnimatorOnlyTags)
|
||||
{
|
||||
break;
|
||||
}
|
||||
EditorGUILayout.HelpBox($"The tag mode is set to be {value.tagMode}, but {nameof(value.insertionAction)} is not registered with Text Animator. You must register the action to use this mode.", MessageType.Info);
|
||||
if (GUILayout.Button("Register action"))
|
||||
{
|
||||
TextAnimationActionState.RegisterAction(value.insertionAction);
|
||||
}
|
||||
break;
|
||||
|
||||
case TextAnimationActionState.RegistrationResult.Registered:
|
||||
if (value.tagMode == TagMode.TextAnimatorOnlyTags)
|
||||
{
|
||||
EditorGUILayout.HelpBox($"You have registered a Yarn Spinner action tag with Text Animator. This won't cause issues but is indicative of a configuration issue.", MessageType.Info);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
#elif !YS_USE_TEXT_ANIMATOR_3
|
||||
[CustomEditor(typeof(TextAnimatorYarnTypewriter))]
|
||||
public class TextAnimatorTypewriterEditor : UnityEditor.Editor
|
||||
{
|
||||
public override void OnInspectorGUI()
|
||||
{
|
||||
EditorGUILayout.HelpBox($"This package requires configuration before it can be used.", MessageType.Error);
|
||||
if (GUILayout.Button("Open Configuration Window"))
|
||||
{
|
||||
TextAnimatorConfigurationWindow.OpenWindow();
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
+18
@@ -0,0 +1,18 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 75189881bc69a4f5da9a141b5624bc34
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
AssetOrigin:
|
||||
serializedVersion: 1
|
||||
productId: 267061
|
||||
packageName: Yarn Spinner+ for Unity, the friendly dialogue and narrative tool
|
||||
packageVersion: 3.2.8
|
||||
assetPath: Packages/dev.yarnspinner.unity.addons.textanimator/Scripts/Editor/TextAnimatorTypewriterEditor.cs
|
||||
uploadId: 968678
|
||||
+23
@@ -0,0 +1,23 @@
|
||||
{
|
||||
"name": "YarnSpinner.Addons.TextAnimatorIntegration.Editor",
|
||||
"rootNamespace": "",
|
||||
"references": [
|
||||
"GUID:1e113d3b5d77bc04eab508251483e8ff",
|
||||
"GUID:e539678cf69674b418d82e89c16a9753",
|
||||
"GUID:34aa492b82754644eac2f903cd496268",
|
||||
"GUID:44199294ed9884553846d30d420ad69a",
|
||||
"GUID:3a299c53e4c683b4eb4a04c9ad9e648f",
|
||||
"UniTask"
|
||||
],
|
||||
"includePlatforms": [
|
||||
"Editor"
|
||||
],
|
||||
"excludePlatforms": [],
|
||||
"allowUnsafeCode": false,
|
||||
"overrideReferences": false,
|
||||
"precompiledReferences": [],
|
||||
"autoReferenced": true,
|
||||
"defineConstraints": [],
|
||||
"versionDefines": [],
|
||||
"noEngineReferences": false
|
||||
}
|
||||
+14
@@ -0,0 +1,14 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 33fdf84cdc6e643f8867a62469ab5024
|
||||
AssemblyDefinitionImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
AssetOrigin:
|
||||
serializedVersion: 1
|
||||
productId: 267061
|
||||
packageName: Yarn Spinner+ for Unity, the friendly dialogue and narrative tool
|
||||
packageVersion: 3.2.8
|
||||
assetPath: Packages/dev.yarnspinner.unity.addons.textanimator/Scripts/Editor/YarnSpinner.Addons.TextAnimatorIntegration.Editor.asmdef
|
||||
uploadId: 968678
|
||||
BIN
Binary file not shown.
|
After Width: | Height: | Size: 576 KiB |
+124
@@ -0,0 +1,124 @@
|
||||
fileFormatVersion: 2
|
||||
guid: a4bc00c6001e94d6d85534ee24530d57
|
||||
TextureImporter:
|
||||
internalIDToNameTable: []
|
||||
externalObjects: {}
|
||||
serializedVersion: 13
|
||||
mipmaps:
|
||||
mipMapMode: 0
|
||||
enableMipMap: 0
|
||||
sRGBTexture: 1
|
||||
linearTexture: 0
|
||||
fadeOut: 0
|
||||
borderMipMap: 0
|
||||
mipMapsPreserveCoverage: 0
|
||||
alphaTestReferenceValue: 0.5
|
||||
mipMapFadeDistanceStart: 1
|
||||
mipMapFadeDistanceEnd: 3
|
||||
bumpmap:
|
||||
convertToNormalMap: 0
|
||||
externalNormalMap: 0
|
||||
heightScale: 0.25
|
||||
normalMapFilter: 0
|
||||
flipGreenChannel: 0
|
||||
isReadable: 0
|
||||
streamingMipmaps: 0
|
||||
streamingMipmapsPriority: 0
|
||||
vTOnly: 0
|
||||
ignoreMipmapLimit: 0
|
||||
grayScaleToAlpha: 0
|
||||
generateCubemap: 6
|
||||
cubemapConvolution: 0
|
||||
seamlessCubemap: 0
|
||||
textureFormat: 1
|
||||
maxTextureSize: 2048
|
||||
textureSettings:
|
||||
serializedVersion: 2
|
||||
filterMode: 1
|
||||
aniso: 1
|
||||
mipBias: 0
|
||||
wrapU: 1
|
||||
wrapV: 1
|
||||
wrapW: 0
|
||||
nPOTScale: 0
|
||||
lightmap: 0
|
||||
compressionQuality: 50
|
||||
spriteMode: 1
|
||||
spriteExtrude: 1
|
||||
spriteMeshType: 0
|
||||
alignment: 0
|
||||
spritePivot: {x: 0.5, y: 0.5}
|
||||
spritePixelsToUnits: 1
|
||||
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
|
||||
spriteGenerateFallbackPhysicsShape: 1
|
||||
alphaUsage: 1
|
||||
alphaIsTransparency: 1
|
||||
spriteTessellationDetail: -1
|
||||
textureType: 8
|
||||
textureShape: 1
|
||||
singleChannelComponent: 0
|
||||
flipbookRows: 1
|
||||
flipbookColumns: 1
|
||||
maxTextureSizeSet: 0
|
||||
compressionQualitySet: 0
|
||||
textureFormatSet: 0
|
||||
ignorePngGamma: 0
|
||||
applyGammaDecoding: 0
|
||||
swizzle: 50462976
|
||||
cookieLightType: 0
|
||||
platformSettings:
|
||||
- serializedVersion: 4
|
||||
buildTarget: DefaultTexturePlatform
|
||||
maxTextureSize: 2048
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
ignorePlatformSupport: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
forceMaximumCompressionQuality_BC6H_BC7: 0
|
||||
- serializedVersion: 4
|
||||
buildTarget: Standalone
|
||||
maxTextureSize: 2048
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
ignorePlatformSupport: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
forceMaximumCompressionQuality_BC6H_BC7: 0
|
||||
spriteSheet:
|
||||
serializedVersion: 2
|
||||
sprites: []
|
||||
outline: []
|
||||
customData:
|
||||
physicsShape: []
|
||||
bones: []
|
||||
spriteID: 5e97eb03825dee720800000000000000
|
||||
internalID: 0
|
||||
vertices: []
|
||||
indices:
|
||||
edges: []
|
||||
weights: []
|
||||
secondaryTextures: []
|
||||
spriteCustomMetadata:
|
||||
entries: []
|
||||
nameFileIdTable: {}
|
||||
mipmapLimitGroupName:
|
||||
pSDRemoveMatte: 0
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
AssetOrigin:
|
||||
serializedVersion: 1
|
||||
productId: 267061
|
||||
packageName: Yarn Spinner+ for Unity, the friendly dialogue and narrative tool
|
||||
packageVersion: 3.2.8
|
||||
assetPath: Packages/dev.yarnspinner.unity.addons.textanimator/Scripts/Editor/banner.jpg
|
||||
uploadId: 968678
|
||||
+93
@@ -0,0 +1,93 @@
|
||||
/*
|
||||
Text Animator for Yarn Spinner is licensed to you under the terms found in the file LICENSE.md.
|
||||
*/
|
||||
|
||||
#if YS_USE_TEXT_ANIMATOR_2 || YS_USE_TEXT_ANIMATOR_3
|
||||
#define USE_TEXT_ANIMATOR
|
||||
#endif
|
||||
|
||||
namespace Yarn.Unity.Addons.TextAnimatorIntegration
|
||||
{
|
||||
using UnityEngine;
|
||||
|
||||
#if UNITY_EDITOR
|
||||
using UnityEditor;
|
||||
|
||||
public class ExampleVersionChecker : MonoBehaviour
|
||||
{
|
||||
[Range(2, 3)]
|
||||
[SerializeField]
|
||||
internal int version = 0;
|
||||
void Start()
|
||||
{
|
||||
ValidateVersion(version);
|
||||
}
|
||||
public void ValidateVersion(int supportedVersion)
|
||||
{
|
||||
#if YS_USE_TEXT_ANIMATOR_2
|
||||
var expectedVersion = 2;
|
||||
#elif YS_USE_TEXT_ANIMATOR_3
|
||||
var expectedVersion = 3;
|
||||
#endif
|
||||
|
||||
#if USE_TEXT_ANIMATOR
|
||||
if (supportedVersion != expectedVersion)
|
||||
{
|
||||
if (EditorUtility.DisplayDialog("Unable to continue", $"This example was created for Text Animator v{supportedVersion}, it will not work.", "Exit Play mode"))
|
||||
{
|
||||
EditorApplication.ExitPlaymode();
|
||||
}
|
||||
}
|
||||
#else
|
||||
if (EditorUtility.DisplayDialog("Unable to continue", "This example requires Text Animator installed and configured, it will not work.", "Exit Play mode"))
|
||||
{
|
||||
EditorApplication.ExitPlaymode();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void OnValidate()
|
||||
{
|
||||
// have this set like this so after the example scene has been made it is annoying to change.
|
||||
// Is only designed to stop casual changes.
|
||||
// to change this set the flags to be HideFlags.None
|
||||
|
||||
this.hideFlags = HideFlags.NotEditable;
|
||||
}
|
||||
}
|
||||
|
||||
[CustomEditor(typeof(ExampleVersionChecker))]
|
||||
public class ExampleVersionCheckerEditor : UnityEditor.Editor
|
||||
{
|
||||
public override void OnInspectorGUI()
|
||||
{
|
||||
DrawDefaultInspector();
|
||||
var value = target as ExampleVersionChecker;
|
||||
if (value == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
#if YS_USE_TEXT_ANIMATOR_2
|
||||
if (value.version != 2)
|
||||
{
|
||||
EditorGUILayout.HelpBox($"This example was created for Text Animator version 2. It WILL not work correctly.", MessageType.Error);
|
||||
}
|
||||
#elif YS_USE_TEXT_ANIMATOR_3
|
||||
if (value.version != 3)
|
||||
{
|
||||
EditorGUILayout.HelpBox($"This example was created for Text Animator version 3. It WILL not work correctly.", MessageType.Error);
|
||||
}
|
||||
#else
|
||||
EditorGUILayout.HelpBox($"This example requires Text Animator installed and configured. It WILL not work correctly.", MessageType.Error);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
#else // UNITY_EDITOR
|
||||
public class ExampleVersionChecker : MonoBehaviour
|
||||
{
|
||||
// This class is only used in the editor, so we'll replace it with an
|
||||
// empty class (to prevent Unity going 'hey there's no class with this
|
||||
// guid!')
|
||||
}
|
||||
#endif
|
||||
}
|
||||
+9
@@ -0,0 +1,9 @@
|
||||
fileFormatVersion: 2
|
||||
guid: e4bedaf9f38a8445aa8761ad8c7f25e4
|
||||
AssetOrigin:
|
||||
serializedVersion: 1
|
||||
productId: 267061
|
||||
packageName: Yarn Spinner+ for Unity, the friendly dialogue and narrative tool
|
||||
packageVersion: 3.2.8
|
||||
assetPath: Packages/dev.yarnspinner.unity.addons.textanimator/Scripts/ExampleVersionChecker.cs
|
||||
uploadId: 968678
|
||||
+60
@@ -0,0 +1,60 @@
|
||||
/*
|
||||
Text Animator for Yarn Spinner is licensed to you under the terms found in the file LICENSE.md.
|
||||
*/
|
||||
|
||||
namespace Yarn.Unity.Addons.TextAnimatorIntegration
|
||||
{
|
||||
#nullable enable
|
||||
using System.Text;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
using Yarn.Unity;
|
||||
using Yarn.Markup;
|
||||
|
||||
/// <summary>
|
||||
/// This object exists to allow multiple Text Animator contexts to exist simultaneously but still have Yarn markup be converted into Text Animator form.
|
||||
/// Without this object because each Typewriter does it themselves you get a collision of multiple objects attempting to provide replacements for the same markup.
|
||||
/// </summary>
|
||||
public class SharedTextAnimatorMarkupReplacementProcessor : MonoBehaviour, IAttributeMarkerProcessor
|
||||
{
|
||||
#if YS_USE_TEXT_ANIMATOR_3
|
||||
// Start is called once before the first execution of Update after the MonoBehaviour is created
|
||||
void Start()
|
||||
{
|
||||
var runner = DialogueRunner.FindRunner(this);
|
||||
|
||||
if (runner == null)
|
||||
{
|
||||
Debug.LogWarning("Was unable to find a dialogue runner to register the Text Animator replacement markup upon.");
|
||||
return;
|
||||
}
|
||||
foreach (var tag in TextAnimatorMarkupManager.AllTags())
|
||||
{
|
||||
runner.LineProvider.RegisterMarkerProcessor(tag, this);
|
||||
}
|
||||
}
|
||||
|
||||
public ReplacementMarkerResult ProcessReplacementMarker(MarkupAttribute marker, StringBuilder childBuilder, List<MarkupAttribute> childAttributes, string localeCode)
|
||||
{
|
||||
int invisibleCharacters = 0;
|
||||
|
||||
if (TextAnimatorMarkupManager.ConvertedForm(marker, out var front, out var back))
|
||||
{
|
||||
childBuilder.Insert(0, front);
|
||||
invisibleCharacters = front.Length;
|
||||
if (marker.Length > 0)
|
||||
{
|
||||
childBuilder.Append(back);
|
||||
invisibleCharacters += back.Length;
|
||||
}
|
||||
}
|
||||
return new ReplacementMarkerResult(invisibleCharacters);
|
||||
}
|
||||
#else
|
||||
public ReplacementMarkerResult ProcessReplacementMarker(MarkupAttribute marker, StringBuilder childBuilder, List<MarkupAttribute> childAttributes, string localeCode)
|
||||
{
|
||||
throw new System.InvalidOperationException("This object cannot exist without Text Animator 3 being installed and correctly configured!");
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
+9
@@ -0,0 +1,9 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 022b92e95b0fe4992998988bad36690b
|
||||
AssetOrigin:
|
||||
serializedVersion: 1
|
||||
productId: 267061
|
||||
packageName: Yarn Spinner+ for Unity, the friendly dialogue and narrative tool
|
||||
packageVersion: 3.2.8
|
||||
assetPath: Packages/dev.yarnspinner.unity.addons.textanimator/Scripts/SharedTextAnimatorMarkupReplacementProcessor.cs
|
||||
uploadId: 968678
|
||||
+249
@@ -0,0 +1,249 @@
|
||||
/*
|
||||
Text Animator for Yarn Spinner is licensed to you under the terms found in the file LICENSE.md.
|
||||
*/
|
||||
|
||||
#if YS_USE_TEXT_ANIMATOR_2 || YS_USE_TEXT_ANIMATOR_3
|
||||
#define USE_TEXT_ANIMATOR
|
||||
#endif
|
||||
|
||||
namespace Yarn.Unity.Addons.TextAnimatorIntegration
|
||||
{
|
||||
#nullable enable
|
||||
using Yarn.Markup;
|
||||
|
||||
public partial class TextAnimatorMarkupManager
|
||||
{
|
||||
#if USE_TEXT_ANIMATOR
|
||||
private enum MarkupType
|
||||
{
|
||||
Unknown, Behaviour, Action, Appearances,
|
||||
}
|
||||
|
||||
private const string disappearanceAttributeKey = "disappearance";
|
||||
private const string typeAttributeKey = "type";
|
||||
private const string trimAttributeKey = "trimwhitespace";
|
||||
private const string behaviourValue = "behaviour";
|
||||
private const string actionValue = "action";
|
||||
private const string appearanceValue = "appearance";
|
||||
|
||||
// how do I handle playback parameters (aka <wave once> sorta things?), I think we just ignore that and in the docs go something like:
|
||||
// "if you have very complex ones we suggest creating them as a palette markup which already handles direct replacement"
|
||||
|
||||
// converts a Yarn Spinner marker into Text Animator form
|
||||
public static bool ConvertedForm(MarkupAttribute attribute, out string frontReplacement, out string backReplacement)
|
||||
{
|
||||
MarkupType markupType = MarkupType.Unknown;
|
||||
if (attribute.TryGetProperty(typeAttributeKey, out string? result))
|
||||
{
|
||||
switch (result.ToLower())
|
||||
{
|
||||
case behaviourValue:
|
||||
markupType = MarkupType.Behaviour;
|
||||
break;
|
||||
case actionValue:
|
||||
markupType = MarkupType.Action;
|
||||
break;
|
||||
case appearanceValue:
|
||||
markupType = MarkupType.Appearances;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
char opening = default;
|
||||
char closing = default;
|
||||
switch (markupType)
|
||||
{
|
||||
case MarkupType.Behaviour:
|
||||
{
|
||||
if (IsBehaviourTag(attribute.Name))
|
||||
{
|
||||
opening = TextAnimatorMarkupManager.OpeningBehavioursBracket;
|
||||
closing = TextAnimatorMarkupManager.ClosingBehavioursBracket;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case MarkupType.Action:
|
||||
{
|
||||
if (IsActionTag(attribute.Name))
|
||||
{
|
||||
opening = TextAnimatorMarkupManager.OpeningActionsBracket;
|
||||
closing = TextAnimatorMarkupManager.ClosingActionsBracket;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case MarkupType.Appearances:
|
||||
{
|
||||
if (IsAppearanceTag(attribute.Name))
|
||||
{
|
||||
opening = TextAnimatorMarkupManager.OpeningAppearancesBracket;
|
||||
closing = TextAnimatorMarkupManager.ClosingAppearancesBracket;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case MarkupType.Unknown:
|
||||
{
|
||||
// we don't know what it is
|
||||
// so we are gonna check them all, one by one
|
||||
// but first we'll check to see if we have done this before for this tag
|
||||
if (cachedAttributeTypes.TryGetValue(attribute.Name, out var tuple))
|
||||
{
|
||||
opening = tuple.start;
|
||||
closing = tuple.end;
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (IsBehaviourTag(attribute.Name))
|
||||
{
|
||||
opening = TextAnimatorMarkupManager.OpeningBehavioursBracket;
|
||||
closing = TextAnimatorMarkupManager.ClosingBehavioursBracket;
|
||||
cachedAttributeTypes.TryAdd(attribute.Name, (opening, closing));
|
||||
break;
|
||||
}
|
||||
if (IsActionTag(attribute.Name))
|
||||
{
|
||||
opening = TextAnimatorMarkupManager.OpeningActionsBracket;
|
||||
closing = TextAnimatorMarkupManager.ClosingActionsBracket;
|
||||
cachedAttributeTypes.TryAdd(attribute.Name, (opening, closing));
|
||||
break;
|
||||
}
|
||||
if (IsAppearanceTag(attribute.Name))
|
||||
{
|
||||
opening = TextAnimatorMarkupManager.OpeningAppearancesBracket;
|
||||
closing = TextAnimatorMarkupManager.ClosingAppearancesBracket;
|
||||
cachedAttributeTypes.TryAdd(attribute.Name, (opening, closing));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// if we got here then we didn't find it
|
||||
// give up here
|
||||
frontReplacement = string.Empty;
|
||||
backReplacement = string.Empty;
|
||||
return false;
|
||||
}
|
||||
default:
|
||||
frontReplacement = string.Empty;
|
||||
backReplacement = string.Empty;
|
||||
return false;
|
||||
}
|
||||
|
||||
var conversion = ConvertMarkupIntoTextAnimatorTag(attribute, opening, closing);
|
||||
if (!string.IsNullOrWhiteSpace(conversion.Item1) && !string.IsNullOrWhiteSpace(conversion.Item2))
|
||||
{
|
||||
frontReplacement = conversion.Item1;
|
||||
backReplacement = conversion.Item2;
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
frontReplacement = string.Empty;
|
||||
backReplacement = string.Empty;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private static (string?, string?) ConvertMarkupIntoTextAnimatorTag(MarkupAttribute attribute, char openingSymbol, char closingSymbol)
|
||||
{
|
||||
System.Text.StringBuilder stringBuilder = new();
|
||||
stringBuilder.Append(openingSymbol);
|
||||
|
||||
string closing = $"{openingSymbol}/{attribute.Name}{closingSymbol}";
|
||||
|
||||
// ok so if it is a disappearance then we need to special case that right now
|
||||
// because we want {#tag} and not {tag} in that case
|
||||
if (attribute.TryGetProperty(disappearanceAttributeKey, out bool disappear))
|
||||
{
|
||||
if (disappear)
|
||||
{
|
||||
stringBuilder.Append(DisappearanceSymbol);
|
||||
closing = $"{openingSymbol}/{DisappearanceSymbol}{attribute.Name}{closingSymbol}";
|
||||
}
|
||||
}
|
||||
stringBuilder.Append(attribute.Name);
|
||||
|
||||
// ok so this is gonna be a bit jank
|
||||
// because if we have a self-property we NEED to handle that first
|
||||
// then otherwise we can do the rest
|
||||
if (attribute.Properties.Count > 0)
|
||||
{
|
||||
if (attribute.Properties.TryGetValue(attribute.Name, out var value))
|
||||
{
|
||||
switch (value.Type)
|
||||
{
|
||||
case MarkupValueType.Integer:
|
||||
stringBuilder.Append("=");
|
||||
stringBuilder.Append(value.IntegerValue);
|
||||
break;
|
||||
case MarkupValueType.Float:
|
||||
stringBuilder.Append("=");
|
||||
stringBuilder.Append(value.FloatValue);
|
||||
break;
|
||||
case MarkupValueType.String:
|
||||
stringBuilder.Append("=");
|
||||
stringBuilder.Append(value.StringValue);
|
||||
break;
|
||||
case MarkupValueType.Bool:
|
||||
stringBuilder.Append("=");
|
||||
stringBuilder.Append(value.BoolValue ? "1" : "0");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// ok now we need to do the next bit which is the properties
|
||||
foreach (var property in attribute.Properties)
|
||||
{
|
||||
// there are four properties we ignore, self, type, whitespace, and disapperance
|
||||
// all of these are already handled or not relevant to us
|
||||
if (property.Key == attribute.Name)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
if (property.Key == trimAttributeKey)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
if (property.Key == disappearanceAttributeKey)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
if (property.Key == typeAttributeKey)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
switch (property.Value.Type)
|
||||
{
|
||||
case MarkupValueType.Integer:
|
||||
stringBuilder.Append(" ");
|
||||
stringBuilder.Append(property.Key);
|
||||
stringBuilder.Append("=");
|
||||
stringBuilder.Append(property.Value.IntegerValue);
|
||||
break;
|
||||
case MarkupValueType.Float:
|
||||
stringBuilder.Append(" ");
|
||||
stringBuilder.Append(property.Key);
|
||||
stringBuilder.Append("=");
|
||||
stringBuilder.Append(property.Value.FloatValue);
|
||||
break;
|
||||
case MarkupValueType.String:
|
||||
stringBuilder.Append(" ");
|
||||
stringBuilder.Append(property.Key);
|
||||
stringBuilder.Append("=");
|
||||
stringBuilder.Append(property.Value.StringValue);
|
||||
break;
|
||||
case MarkupValueType.Bool:
|
||||
stringBuilder.Append(" ");
|
||||
stringBuilder.Append(property.Key);
|
||||
stringBuilder.Append("=");
|
||||
stringBuilder.Append(property.Value.BoolValue ? "1" : "0");
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
var front = stringBuilder.Append(closingSymbol).ToString();
|
||||
return (front, closing);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
+18
@@ -0,0 +1,18 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 0434e130b589842d488bd865f7435ae9
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
AssetOrigin:
|
||||
serializedVersion: 1
|
||||
productId: 267061
|
||||
packageName: Yarn Spinner+ for Unity, the friendly dialogue and narrative tool
|
||||
packageVersion: 3.2.8
|
||||
assetPath: Packages/dev.yarnspinner.unity.addons.textanimator/Scripts/TextAnimatorMarkupManager.cs
|
||||
uploadId: 968678
|
||||
+111
@@ -0,0 +1,111 @@
|
||||
/*
|
||||
Text Animator for Yarn Spinner is licensed to you under the terms found in the file LICENSE.md.
|
||||
*/
|
||||
|
||||
namespace Yarn.Unity.Addons.TextAnimatorIntegration
|
||||
{
|
||||
#nullable enable
|
||||
using Yarn.Markup;
|
||||
using System.Collections.Generic;
|
||||
#if YS_USE_TEXT_ANIMATOR_2
|
||||
using Febucci.UI;
|
||||
#endif
|
||||
|
||||
public partial class TextAnimatorMarkupManager
|
||||
{
|
||||
#if YS_USE_TEXT_ANIMATOR_2
|
||||
public static char OpeningActionsBracket => TextAnimatorSettings.Instance.actions.openingSymbol;
|
||||
public static char ClosingActionsBracket => TextAnimatorSettings.Instance.actions.closingSymbol;
|
||||
public static char OpeningAppearancesBracket => TextAnimatorSettings.Instance.appearances.openingSymbol;
|
||||
public static char ClosingAppearancesBracket => TextAnimatorSettings.Instance.appearances.closingSymbol;
|
||||
public static char DisappearanceSymbol => TextAnimatorSettings.Instance.disappearancesMiddleSymbol;
|
||||
public static char OpeningBehavioursBracket => TextAnimatorSettings.Instance.behaviors.openingSymbol;
|
||||
public static char ClosingBehavioursBracket => TextAnimatorSettings.Instance.behaviors.closingSymbol;
|
||||
|
||||
public static bool IsTextAnimatorTag(string tagID)
|
||||
{
|
||||
if (tagID == "notype")
|
||||
{
|
||||
return true;
|
||||
}
|
||||
if (TextAnimatorSettings.Instance.actions.defaultDatabase.ContainsKey(tagID))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
if (TextAnimatorSettings.Instance.behaviors.defaultDatabase.ContainsKey(tagID))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
if (TextAnimatorSettings.Instance.appearances.defaultDatabase.ContainsKey(tagID))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public static HashSet<string> AllTags()
|
||||
{
|
||||
HashSet<string> tags = new();
|
||||
|
||||
foreach (var action in TextAnimatorSettings.Instance.actions.defaultDatabase.Data)
|
||||
{
|
||||
if (action == null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
if (string.IsNullOrEmpty(action.TagID))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
tags.Add(action.TagID);
|
||||
}
|
||||
foreach (var behaviors in TextAnimatorSettings.Instance.behaviors.defaultDatabase.Data)
|
||||
{
|
||||
if (behaviors == null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
if (string.IsNullOrEmpty(behaviors.TagID))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
tags.Add(behaviors.TagID);
|
||||
}
|
||||
foreach (var appearance in TextAnimatorSettings.Instance.appearances.defaultDatabase.Data)
|
||||
{
|
||||
if (appearance == null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
if (string.IsNullOrEmpty(appearance.TagID))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
tags.Add(appearance.TagID);
|
||||
}
|
||||
tags.Add("notype");
|
||||
|
||||
return tags;
|
||||
}
|
||||
|
||||
private static bool IsBehaviourTag(string tagID)
|
||||
{
|
||||
return TextAnimatorSettings.Instance.behaviors.defaultDatabase.ContainsKey(tagID);
|
||||
}
|
||||
private static bool IsActionTag(string tagID)
|
||||
{
|
||||
return TextAnimatorSettings.Instance.actions.defaultDatabase.ContainsKey(tagID);
|
||||
}
|
||||
private static bool IsAppearanceTag(string tagID)
|
||||
{
|
||||
return TextAnimatorSettings.Instance.appearances.defaultDatabase.ContainsKey(tagID);
|
||||
}
|
||||
|
||||
private static Dictionary<string, (char start, char end)> cachedAttributeTypes = new()
|
||||
{
|
||||
{"notype", ('<', '>') },
|
||||
};
|
||||
#endif
|
||||
}
|
||||
}
|
||||
+9
@@ -0,0 +1,9 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 28fe7fba654914103b39d5974bd21da4
|
||||
AssetOrigin:
|
||||
serializedVersion: 1
|
||||
productId: 267061
|
||||
packageName: Yarn Spinner+ for Unity, the friendly dialogue and narrative tool
|
||||
packageVersion: 3.2.8
|
||||
assetPath: Packages/dev.yarnspinner.unity.addons.textanimator/Scripts/TextAnimatorMarkupManager_v2.cs
|
||||
uploadId: 968678
|
||||
+73
@@ -0,0 +1,73 @@
|
||||
/*
|
||||
Text Animator for Yarn Spinner is licensed to you under the terms found in the file LICENSE.md.
|
||||
*/
|
||||
|
||||
namespace Yarn.Unity.Addons.TextAnimatorIntegration
|
||||
{
|
||||
#nullable enable
|
||||
using Yarn.Markup;
|
||||
using System.Collections.Generic;
|
||||
#if YS_USE_TEXT_ANIMATOR_3
|
||||
using Febucci.TextAnimatorForUnity;
|
||||
#endif
|
||||
|
||||
public partial class TextAnimatorMarkupManager
|
||||
{
|
||||
#if YS_USE_TEXT_ANIMATOR_3
|
||||
public static char OpeningActionsBracket => '<';
|
||||
public static char ClosingActionsBracket => '>';
|
||||
public static char OpeningAppearancesBracket => TextAnimatorSettings.Instance.Settings.parsingAppearances.openingBracket;
|
||||
public static char ClosingAppearancesBracket => TextAnimatorSettings.Instance.Settings.parsingAppearances.closingBracket;
|
||||
public static char DisappearanceSymbol => TextAnimatorSettings.Instance.Settings.parsingDisappearances.middleSymbol;
|
||||
public static char OpeningBehavioursBracket => TextAnimatorSettings.Instance.Settings.parsingBehaviors.openingBracket;
|
||||
public static char ClosingBehavioursBracket => TextAnimatorSettings.Instance.Settings.parsingBehaviors.closingBracket;
|
||||
|
||||
public static bool IsTextAnimatorTag(string tagID)
|
||||
{
|
||||
if (tagID == "notype")
|
||||
{
|
||||
return true;
|
||||
}
|
||||
if (TextAnimatorSettings.Instance.Settings.GlobalActionsDatabase.Database.ContainsKey(tagID))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
if (TextAnimatorSettings.Instance.Settings.GlobalEffectsDatabase.Database.ContainsKey(tagID))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public static HashSet<string> AllTags()
|
||||
{
|
||||
HashSet<string> tags = new();
|
||||
|
||||
tags.UnionWith(TextAnimatorSettings.Instance.Settings.GlobalActionsDatabase.Database.Keys);
|
||||
tags.UnionWith(TextAnimatorSettings.Instance.Settings.GlobalEffectsDatabase.Database.Keys);
|
||||
tags.Add("notype");
|
||||
|
||||
return tags;
|
||||
}
|
||||
|
||||
private static bool IsBehaviourTag(string tagID)
|
||||
{
|
||||
return TextAnimatorSettings.Instance.Settings.GlobalEffectsDatabase.Database.ContainsKey(tagID);
|
||||
}
|
||||
private static bool IsActionTag(string tagID)
|
||||
{
|
||||
return TextAnimatorSettings.Instance.Settings.GlobalActionsDatabase.Database.ContainsKey(tagID);
|
||||
}
|
||||
private static bool IsAppearanceTag(string tagID)
|
||||
{
|
||||
return TextAnimatorSettings.Instance.Settings.GlobalEffectsDatabase.Database.ContainsKey(tagID);
|
||||
}
|
||||
|
||||
private static Dictionary<string, (char start, char end)> cachedAttributeTypes = new()
|
||||
{
|
||||
{"notype", ('<', '>') },
|
||||
};
|
||||
#endif
|
||||
}
|
||||
}
|
||||
+9
@@ -0,0 +1,9 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 6e44de3f910b7417a812372a78eae38e
|
||||
AssetOrigin:
|
||||
serializedVersion: 1
|
||||
productId: 267061
|
||||
packageName: Yarn Spinner+ for Unity, the friendly dialogue and narrative tool
|
||||
packageVersion: 3.2.8
|
||||
assetPath: Packages/dev.yarnspinner.unity.addons.textanimator/Scripts/TextAnimatorMarkupManager_v3.cs
|
||||
uploadId: 968678
|
||||
+94
@@ -0,0 +1,94 @@
|
||||
/*
|
||||
Text Animator for Yarn Spinner is licensed to you under the terms found in the file LICENSE.md.
|
||||
*/
|
||||
|
||||
#if YS_USE_TEXT_ANIMATOR_2 || YS_USE_TEXT_ANIMATOR_3
|
||||
#define USE_TEXT_ANIMATOR
|
||||
#endif
|
||||
|
||||
#nullable enable
|
||||
|
||||
namespace Yarn.Unity.Addons.TextAnimatorIntegration
|
||||
{
|
||||
using System.Threading;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
using Yarn.Unity;
|
||||
using Yarn.Markup;
|
||||
#if UNITY_EDITOR
|
||||
using UnityEditor;
|
||||
using Yarn.Unity.Editor;
|
||||
#endif
|
||||
#if !USE_TEXT_ANIMATOR
|
||||
using TextAnimator_TMP = UnityEngine.Object;
|
||||
using TypewriterCore = UnityEngine.Object;
|
||||
#endif
|
||||
|
||||
public enum TagMode
|
||||
{
|
||||
YarnOnlyTags, TextAnimatorOnlyTags, DefaultYarnMarkup,
|
||||
}
|
||||
|
||||
#if !USE_TEXT_ANIMATOR
|
||||
// This only exists if Text Animator isn't installed
|
||||
// in which case it doesn't really do anything except make sure the serialised references aren't lost
|
||||
// this means it also has the references for both versions of Text Animator
|
||||
public class TextAnimatorYarnTypewriter : MonoBehaviour, IAsyncTypewriter, IAttributeMarkerProcessor
|
||||
{
|
||||
|
||||
#pragma warning disable CS8618
|
||||
[HideInInspector] public List<IActionMarkupHandler> ActionMarkupHandlers { get; set; }
|
||||
#pragma warning restore CS8618
|
||||
|
||||
public TextAnimator_TMP? Animator;
|
||||
|
||||
public TypewriterCore? Typewriter;
|
||||
|
||||
[SerializeField] internal TagMode tagMode = TagMode.DefaultYarnMarkup;
|
||||
|
||||
public ActionMarkupAction? insertionAction;
|
||||
|
||||
#pragma warning disable CS8618
|
||||
[SerializeField] private List<string> actionTags;
|
||||
#pragma warning restore CS8618
|
||||
public bool ActionMarkupFinishedProcessing => false;
|
||||
|
||||
public YarnTask RunTypewriter(MarkupParseResult line, CancellationToken cancellationToken)
|
||||
{
|
||||
throw new System.NotImplementedException();
|
||||
}
|
||||
|
||||
public void PrepareForContent(MarkupParseResult line)
|
||||
{
|
||||
throw new System.NotImplementedException();
|
||||
}
|
||||
|
||||
public void ContentWillDismiss()
|
||||
{
|
||||
throw new System.NotImplementedException();
|
||||
}
|
||||
|
||||
public ReplacementMarkerResult ProcessReplacementMarker(MarkupAttribute marker, System.Text.StringBuilder childBuilder, List<MarkupAttribute> childAttributes, string localeCode)
|
||||
{
|
||||
throw new System.NotImplementedException();
|
||||
}
|
||||
public void CancelMarkupProcessing()
|
||||
{
|
||||
throw new System.NotImplementedException();
|
||||
}
|
||||
public void StartMarkup(int index)
|
||||
{
|
||||
throw new System.NotImplementedException();
|
||||
}
|
||||
|
||||
public void ContentDidDismiss()
|
||||
{
|
||||
throw new System.NotImplementedException();
|
||||
}
|
||||
|
||||
public TMPro.TMP_Text? TextElement { get => throw new System.NotImplementedException(); set => throw new System.NotImplementedException(); }
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
}
|
||||
+9
@@ -0,0 +1,9 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 26ef910a7482f4ce9bbf4cd80ef5e3c5
|
||||
AssetOrigin:
|
||||
serializedVersion: 1
|
||||
productId: 267061
|
||||
packageName: Yarn Spinner+ for Unity, the friendly dialogue and narrative tool
|
||||
packageVersion: 3.2.8
|
||||
assetPath: Packages/dev.yarnspinner.unity.addons.textanimator/Scripts/TextAnimatorYarnTypewriter.cs
|
||||
uploadId: 968678
|
||||
+361
@@ -0,0 +1,361 @@
|
||||
/*
|
||||
Text Animator for Yarn Spinner is licensed to you under the terms found in the file LICENSE.md.
|
||||
*/
|
||||
|
||||
#if YS_USE_TEXT_ANIMATOR_2 || YS_USE_TEXT_ANIMATOR_3
|
||||
#define USE_TEXT_ANIMATOR
|
||||
#endif
|
||||
|
||||
namespace Yarn.Unity.Addons.TextAnimatorIntegration
|
||||
{
|
||||
using System.Collections.Generic;
|
||||
using System.Threading;
|
||||
using UnityEngine;
|
||||
using Yarn.Unity;
|
||||
using Yarn.Markup;
|
||||
using Yarn.Unity.Attributes;
|
||||
|
||||
#if YS_USE_TEXT_ANIMATOR_2
|
||||
using Febucci.UI;
|
||||
using Febucci.UI.Core;
|
||||
#else
|
||||
using TextAnimator_TMP = UnityEngine.Object;
|
||||
using TypewriterCore = UnityEngine.Object;
|
||||
#endif
|
||||
|
||||
#nullable enable
|
||||
|
||||
#if YS_USE_TEXT_ANIMATOR_2
|
||||
public class TextAnimatorYarnTypewriter : MonoBehaviour, IAsyncTypewriter, IAttributeMarkerProcessor
|
||||
{
|
||||
[HideInInspector] public List<IActionMarkupHandler> ActionMarkupHandlers { get; set; } = new();
|
||||
|
||||
[Group("Text Animator")]
|
||||
public TextAnimator_TMP? Animator;
|
||||
|
||||
[Group("Text Animator")]
|
||||
public TypewriterCore? Typewriter;
|
||||
|
||||
[Group("Tags")]
|
||||
[SerializeField] public TagMode tagMode = TagMode.DefaultYarnMarkup;
|
||||
|
||||
[Group("Tags")]
|
||||
[HideIf(nameof(tagMode), TagMode.TextAnimatorOnlyTags)]
|
||||
public ActionMarkupAction? insertionAction;
|
||||
|
||||
[Group("Tags")]
|
||||
[ShowIf(nameof(tagMode), TagMode.DefaultYarnMarkup)]
|
||||
[SerializeField] private List<string> actionTags = new();
|
||||
private YarnTaskCompletionSource? typewriterComplete;
|
||||
private CancellationToken? currentContentCancellationToken;
|
||||
private MarkupParseResult? currentContent;
|
||||
private YarnTaskCompletionSource? markupHandlersProcessingCompletionSource;
|
||||
|
||||
/// <summary>
|
||||
/// Indicates to the typewriter that it should prepare for displaying a new line.
|
||||
/// </summary>
|
||||
/// <param name="lineText">The line that will be shown.</param>
|
||||
public void PrepareForContent(MarkupParseResult lineText)
|
||||
{
|
||||
if (ActionMarkupHandlers == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
if (Animator == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
foreach (var handler in ActionMarkupHandlers)
|
||||
{
|
||||
handler.OnPrepareForLine(lineText, Animator.TMProComponent);
|
||||
}
|
||||
|
||||
switch (tagMode)
|
||||
{
|
||||
case TagMode.TextAnimatorOnlyTags:
|
||||
this.Animator.SetText(lineText.Text, hideText: true);
|
||||
break;
|
||||
case TagMode.YarnOnlyTags:
|
||||
{
|
||||
var text = ProcessTagModeYarn(lineText);
|
||||
if (text == null)
|
||||
{
|
||||
this.Animator.SetText(lineText.Text, hideText: true);
|
||||
}
|
||||
else
|
||||
{
|
||||
this.Animator.SetText(text, hideText: true);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case TagMode.DefaultYarnMarkup:
|
||||
{
|
||||
this.Animator.SetText(lineText.Text, hideText: true);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Start()
|
||||
{
|
||||
var runner = DialogueRunner.FindRunner(this);
|
||||
if (runner != null)
|
||||
{
|
||||
if (tagMode == TagMode.TextAnimatorOnlyTags)
|
||||
{
|
||||
return;
|
||||
}
|
||||
foreach (var tag in TextAnimatorMarkupManager.AllTags())
|
||||
{
|
||||
runner.LineProvider.RegisterMarkerProcessor(tag, this);
|
||||
}
|
||||
|
||||
if (tagMode == TagMode.DefaultYarnMarkup)
|
||||
{
|
||||
HashSet<string> tags = new HashSet<string>(actionTags);
|
||||
foreach (var tag in tags)
|
||||
{
|
||||
runner.LineProvider.RegisterMarkerProcessor(tag, this);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// This method can be thought of as a supersized replacement markup system
|
||||
// it adds a Text Animator action (defaults to <y>) at every character in the line
|
||||
// as it walks down the line inserting this potential pauses if it encounters markup that is a Text Animator tag it will instead convert this from Yarn Spinner markup to Text Animator tag form
|
||||
// and then continue
|
||||
private string? ProcessTagModeYarn(MarkupParseResult lineText)
|
||||
{
|
||||
if (insertionAction == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
var insert = $"{TextAnimatorMarkupManager.OpeningActionsBracket}{insertionAction.TagID}{TextAnimatorMarkupManager.ClosingActionsBracket}";
|
||||
System.Text.StringBuilder stringBuilder = new();
|
||||
for (int i = 0; i < lineText.Text.Length; i++)
|
||||
{
|
||||
stringBuilder.Append(insert);
|
||||
foreach (var attribute in lineText.Attributes)
|
||||
{
|
||||
if (TextAnimatorMarkupManager.IsTextAnimatorTag(attribute.Name))
|
||||
{
|
||||
if (attribute.Position == i || (attribute.Position + attribute.Length == i))
|
||||
{
|
||||
if (TextAnimatorMarkupManager.ConvertedForm(attribute, out var front, out var back))
|
||||
{
|
||||
// we are at the start
|
||||
if (attribute.Position == i)
|
||||
{
|
||||
stringBuilder.Append(front);
|
||||
}
|
||||
else
|
||||
{
|
||||
stringBuilder.Append(back);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
var character = lineText.Text[i];
|
||||
stringBuilder.Append(character);
|
||||
}
|
||||
return stringBuilder.ToString();
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Indicates to the typewriter that the user interface elements necessary for
|
||||
/// showing the the line screen have finished appearing.
|
||||
/// </summary>
|
||||
/// <param name="text"></param>
|
||||
public void OnLineDisplayBegin(MarkupParseResult text)
|
||||
{
|
||||
if (ActionMarkupHandlers == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
if (Animator == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
foreach (var handler in ActionMarkupHandlers)
|
||||
{
|
||||
handler.OnLineDisplayBegin(text, Animator.TMProComponent);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Indicates to the typewriter that the user interface elements
|
||||
/// necessary for showing the line are about to disappear.
|
||||
/// </summary>
|
||||
public void ContentWillDismiss()
|
||||
{
|
||||
if (ActionMarkupHandlers == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
foreach (var handler in ActionMarkupHandlers)
|
||||
{
|
||||
handler.OnLineWillDismiss();
|
||||
}
|
||||
}
|
||||
|
||||
public void ContentDidDismiss()
|
||||
{
|
||||
Typewriter.SkipTypewriter();
|
||||
}
|
||||
public TMPro.TMP_Text? TextElement { get; set; }
|
||||
|
||||
public async YarnTask RunTypewriter(MarkupParseResult line, CancellationToken cancellationToken)
|
||||
{
|
||||
if (ActionMarkupHandlers == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
if (Animator == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
if (Typewriter == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
currentContent = line;
|
||||
currentContentCancellationToken = cancellationToken;
|
||||
|
||||
// Let every markup handler know that display is about to begin
|
||||
foreach (var markupHandler in ActionMarkupHandlers)
|
||||
{
|
||||
markupHandler.OnLineDisplayBegin(line, Animator.TMProComponent);
|
||||
}
|
||||
|
||||
// Create a completion source that we'll complete when TextAnimator tells us
|
||||
// that the typewriter has finished
|
||||
typewriterComplete = new YarnTaskCompletionSource();
|
||||
|
||||
var registration = cancellationToken.Register(() =>
|
||||
{
|
||||
// If our cancellation token is tripped, the user wants us to hurry
|
||||
// up our delivery. Tell TextAnimator to skip the rest of the
|
||||
// presentation.
|
||||
Typewriter.SkipTypewriter();
|
||||
});
|
||||
|
||||
// We want to be notified when each character appears.
|
||||
Typewriter.onTextShowed.AddListener(OnTypewriterComplete);
|
||||
|
||||
// Start the typewriter and wait for it to finish
|
||||
Typewriter.StartShowingText();
|
||||
await typewriterComplete.Task;
|
||||
|
||||
// Clean up
|
||||
Typewriter.onTextShowed.RemoveListener(OnTypewriterComplete);
|
||||
registration.Dispose();
|
||||
typewriterComplete = null;
|
||||
currentContent = null;
|
||||
currentContentCancellationToken = null;
|
||||
|
||||
// Notify our action markup handlers that the line is done
|
||||
foreach (var markupHandler in ActionMarkupHandlers)
|
||||
{
|
||||
markupHandler.OnLineDisplayComplete();
|
||||
}
|
||||
}
|
||||
|
||||
private async YarnTask ProcessActionMarkup(int index, MarkupParseResult content, IReadOnlyList<IActionMarkupHandler> actionMarkupHandlers, CancellationToken token)
|
||||
{
|
||||
// should also link the token to markupHandlersProcessingCompletionSource
|
||||
foreach (var processor in actionMarkupHandlers)
|
||||
{
|
||||
await processor.OnCharacterWillAppear(index, content, token);
|
||||
}
|
||||
markupHandlersProcessingCompletionSource?.TrySetResult();
|
||||
}
|
||||
|
||||
public void CancelMarkupProcessing()
|
||||
{
|
||||
markupHandlersProcessingCompletionSource?.TrySetCanceled();
|
||||
}
|
||||
|
||||
private void OnTypewriterComplete()
|
||||
{
|
||||
// The TextAnimator typewriter has finished showing all of its text.
|
||||
// Notify that we're done.
|
||||
typewriterComplete?.TrySetResult();
|
||||
}
|
||||
|
||||
public bool ActionMarkupFinishedProcessing
|
||||
{
|
||||
get
|
||||
{
|
||||
return markupHandlersProcessingCompletionSource == null || markupHandlersProcessingCompletionSource.Task.IsCompleted();
|
||||
}
|
||||
}
|
||||
|
||||
public void StartMarkup(int index)
|
||||
{
|
||||
if (ActionMarkupHandlers == null || ActionMarkupHandlers.Count == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
if (!currentContent.HasValue)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
markupHandlersProcessingCompletionSource = new YarnTaskCompletionSource();
|
||||
|
||||
var token = this.currentContentCancellationToken ?? this.destroyCancellationToken;
|
||||
ProcessActionMarkup(index, currentContent.Value, ActionMarkupHandlers, token).Forget();
|
||||
}
|
||||
|
||||
public ReplacementMarkerResult ProcessReplacementMarker(MarkupAttribute marker, System.Text.StringBuilder childBuilder, List<MarkupAttribute> childAttributes, string localeCode)
|
||||
{
|
||||
int invisibleCharacters = 0;
|
||||
if (tagMode == TagMode.DefaultYarnMarkup)
|
||||
{
|
||||
if (TextAnimatorMarkupManager.ConvertedForm(marker, out var front, out var back))
|
||||
{
|
||||
childBuilder.Insert(0, front);
|
||||
invisibleCharacters = front.Length;
|
||||
if (marker.Length > 0)
|
||||
{
|
||||
childBuilder.Append(back);
|
||||
invisibleCharacters += back.Length;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// here we are doing a bit of a hack, we are adding an action tag into the string at the point of the markup (<y> by default)
|
||||
// and then adding the attribute back in, that way it can still be processed just fine at runtime using the <y> marker when hit by Text Animator
|
||||
// in combination with the above which converts Yarn Spinner markup into Text Animator tags a line such as
|
||||
// Hello here is a line that [rainb]mixes and matches Yarn[pause=1000 /] and Text Animator[/rain] markup systems!
|
||||
// would become:
|
||||
// Hello here is a line that <rainb>mixes and matches Yarn<y> and Text Animator</rainb> markup systems!
|
||||
// and when the <y> is hit by the Text Animator typewriter it will call out to our system which will forward onto pause
|
||||
|
||||
if (insertionAction != null)
|
||||
{
|
||||
childBuilder.Insert(0, $"{TextAnimatorMarkupManager.OpeningActionsBracket}{insertionAction.TagID}{TextAnimatorMarkupManager.ClosingActionsBracket}");
|
||||
}
|
||||
childAttributes.Add(marker);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// we aren't in the minimal mode
|
||||
// so we don't want to swap out the content but have them just be normal markers
|
||||
childAttributes.Add(marker);
|
||||
}
|
||||
return new ReplacementMarkerResult(invisibleCharacters);
|
||||
}
|
||||
}
|
||||
#elif YS_USE_TEXT_ANIMATOR_3
|
||||
public class NullTextAnimatorYarnTypewriter : MonoBehaviour { }
|
||||
#endif
|
||||
}
|
||||
+18
@@ -0,0 +1,18 @@
|
||||
fileFormatVersion: 2
|
||||
guid: a5c5bc8be957c4b339e2814347bf7d0a
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
AssetOrigin:
|
||||
serializedVersion: 1
|
||||
productId: 267061
|
||||
packageName: Yarn Spinner+ for Unity, the friendly dialogue and narrative tool
|
||||
packageVersion: 3.2.8
|
||||
assetPath: Packages/dev.yarnspinner.unity.addons.textanimator/Scripts/TextAnimatorYarnTypewriter_v2.cs
|
||||
uploadId: 968678
|
||||
+288
@@ -0,0 +1,288 @@
|
||||
/*
|
||||
Text Animator for Yarn Spinner is licensed to you under the terms found in the file LICENSE.md.
|
||||
*/
|
||||
|
||||
namespace Yarn.Unity.Addons.TextAnimatorIntegration
|
||||
{
|
||||
#nullable enable
|
||||
#if YS_USE_TEXT_ANIMATOR_3
|
||||
using UnityEngine;
|
||||
using Yarn.Unity;
|
||||
using Yarn.Markup;
|
||||
using Febucci.TextAnimatorCore.Typing;
|
||||
using Febucci.TextAnimatorCore.Text;
|
||||
using Febucci.TextAnimatorForUnity;
|
||||
using System.Threading;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
public class TextAnimatorYarnTypewriter : TypewriterComponent, IAsyncTypewriter, IAttributeMarkerProcessor
|
||||
{
|
||||
public Febucci.TextAnimatorForUnity.TextMeshPro.TextAnimator_TMP? Animator;
|
||||
|
||||
// IAttributeMarkerProcessor required elements
|
||||
[HideInInspector] public List<IActionMarkupHandler> ActionMarkupHandlers { get; set; } = new();
|
||||
|
||||
// holds the current line being presented, or null otherwise
|
||||
private MarkupParseResult? currentContent;
|
||||
// the current cancellation token given to us by the dialogue presenter
|
||||
// this will be cancelled if the line is declared as needing to hurry up or be skipped
|
||||
private CancellationToken currentContentPresentationCancellationToken = CancellationToken.None;
|
||||
// the completion source for the overall typewriting of the line
|
||||
private YarnTaskCompletionSource? currentContentPresentation;
|
||||
// the completion source for the overall typewriting of the current character being typewritten
|
||||
private YarnTaskCompletionSource? currentCharacterProgressSource;
|
||||
// the completion source for any markup processors (if necessary) for the current character
|
||||
private YarnTaskCompletionSource? currentCharacterMarkupProgress;
|
||||
// keeps track of the index of the last character we correctly finished processing
|
||||
private int lastProcessedCharacterIndex = -1;
|
||||
|
||||
// this is a lot of different pieces the idea being that when a line comes in we will need to have a fresh currentContentPresentation created for that line
|
||||
// then for each character as they typewrite along down the line we will create a new currentCharacterProgressSource for that specific character
|
||||
// then for that character when they hit any markup we make a new currentCharacterMarkupProgress to hold that being done
|
||||
// once markup finishes currentCharacterMarkupProgress and currentCharacterProgressSource will get completed
|
||||
// which will make the typewriter advance to the next character
|
||||
// eventually then currentContentPresentation finishes up and that frees up the await call in RunTypewriter
|
||||
|
||||
void Start()
|
||||
{
|
||||
// if we can find a SharedTextAnimatorMarkupReplacementProcessor we can safely assume that it is handling the processing of replacing the TA markup
|
||||
// otherwise it's on us to do it
|
||||
if (!GameObject.FindAnyObjectByType<SharedTextAnimatorMarkupReplacementProcessor>())
|
||||
{
|
||||
var runner = DialogueRunner.FindRunner(this);
|
||||
if (runner != null)
|
||||
{
|
||||
foreach (var tag in TextAnimatorMarkupManager.AllTags())
|
||||
{
|
||||
runner.LineProvider.RegisterMarkerProcessor(tag, this);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Debug.LogWarning($"{name} is expecting to have to register itself as the object handling Text Animator markup but was unable to find a Dialogue Runner!");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void PrepareForContent(MarkupParseResult line)
|
||||
{
|
||||
if (ActionMarkupHandlers == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
if (Animator == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
foreach (var handler in ActionMarkupHandlers)
|
||||
{
|
||||
handler.OnPrepareForLine(line, Animator.TMProComponent);
|
||||
}
|
||||
|
||||
this.ShowText(line.Text);
|
||||
}
|
||||
|
||||
public async YarnTask RunTypewriter(MarkupParseResult line, CancellationToken cancellationToken)
|
||||
{
|
||||
if (currentContentPresentation != null)
|
||||
{
|
||||
currentContentPresentation.TrySetCanceled();
|
||||
}
|
||||
if (Animator == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// Let every markup handler know that display is about to begin
|
||||
foreach (var markupHandler in ActionMarkupHandlers)
|
||||
{
|
||||
markupHandler.OnLineDisplayBegin(line, Animator.TMProComponent);
|
||||
}
|
||||
|
||||
currentContentPresentation = new YarnTaskCompletionSource();
|
||||
cancellationToken.Register(() =>
|
||||
{
|
||||
currentContentPresentation?.TrySetCanceled();
|
||||
});
|
||||
|
||||
lastProcessedCharacterIndex = -1;
|
||||
currentCharacterProgressSource?.TrySetResult();
|
||||
currentCharacterProgressSource = null;
|
||||
currentContent = line;
|
||||
currentContentPresentationCancellationToken = cancellationToken;
|
||||
currentCharacterProgressSource = new();
|
||||
cancellationToken.Register(() =>
|
||||
{
|
||||
currentCharacterProgressSource?.TrySetCanceled();
|
||||
});
|
||||
this.StartShowingText();
|
||||
|
||||
try
|
||||
{
|
||||
await currentContentPresentation.Task;
|
||||
}
|
||||
catch (System.OperationCanceledException)
|
||||
{
|
||||
this.SkipTypewriter();
|
||||
|
||||
// run every markup from the last index we processed
|
||||
// this ensure that if there is any markup that wasn't hit due to the hurrying up it still gets a chance to do anything it NEEDS to do
|
||||
// because they are given a pre-cancelled token they will ideally finish instantly
|
||||
// we do this character by character instead of all at once to avoid a situation where one piece of markup changes something that impacts a later event
|
||||
// especially if it is changing poses or positions of game objects
|
||||
if (lastProcessedCharacterIndex != -1)
|
||||
{
|
||||
for (int i = lastProcessedCharacterIndex; i < Animator.textWithoutAnyTag.Length; i++)
|
||||
{
|
||||
List<YarnTask> cancelledActions = new();
|
||||
foreach (var processor in ActionMarkupHandlers)
|
||||
{
|
||||
cancelledActions.Add(processor.OnCharacterWillAppear(i, currentContent.Value, cancellationToken));
|
||||
}
|
||||
await YarnTask.WhenAll(cancelledActions);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Notify our action markup handlers that the line is done
|
||||
foreach (var markupHandler in ActionMarkupHandlers)
|
||||
{
|
||||
markupHandler.OnLineDisplayComplete();
|
||||
}
|
||||
|
||||
// do final cleanup
|
||||
currentCharacterProgressSource?.TrySetResult();
|
||||
currentCharacterProgressSource = null;
|
||||
currentContentPresentationCancellationToken = CancellationToken.None;
|
||||
currentContentPresentation?.TrySetResult();
|
||||
currentContentPresentation = null;
|
||||
currentContent = null;
|
||||
}
|
||||
|
||||
public void ContentWillDismiss()
|
||||
{
|
||||
if (ActionMarkupHandlers != null)
|
||||
{
|
||||
foreach (var handler in ActionMarkupHandlers)
|
||||
{
|
||||
handler.OnLineWillDismiss();
|
||||
}
|
||||
}
|
||||
this.ShowText(string.Empty);
|
||||
}
|
||||
|
||||
public ReplacementMarkerResult ProcessReplacementMarker(MarkupAttribute marker, StringBuilder childBuilder, List<MarkupAttribute> childAttributes, string localeCode)
|
||||
{
|
||||
int invisibleCharacters = 0;
|
||||
|
||||
if (TextAnimatorMarkupManager.ConvertedForm(marker, out var front, out var back))
|
||||
{
|
||||
childBuilder.Insert(0, front);
|
||||
invisibleCharacters = front.Length;
|
||||
if (marker.Length > 0)
|
||||
{
|
||||
childBuilder.Append(back);
|
||||
invisibleCharacters += back.Length;
|
||||
}
|
||||
}
|
||||
return new ReplacementMarkerResult(invisibleCharacters);
|
||||
}
|
||||
|
||||
protected override ActionStatus OnBeforeShowingCharacter(CharacterData character)
|
||||
{
|
||||
// I am not sure if I am triggering this correctly, it seems to want to typewrite on first frame
|
||||
// so for now I am just gonna tell it to chill out and wait until there is something to show
|
||||
if (currentContentPresentation == null)
|
||||
{
|
||||
return ActionStatus.Running;
|
||||
}
|
||||
|
||||
if (currentCharacterProgressSource == null)
|
||||
{
|
||||
Debug.LogWarning($"Attempting to calculate delay for character {character.index} but {nameof(currentCharacterProgressSource)} is null, we cannot determine if we have paused for the right duration.");
|
||||
|
||||
return base.OnBeforeShowingCharacter(character);
|
||||
}
|
||||
|
||||
if (currentCharacterProgressSource.Task.IsCompleted())
|
||||
{
|
||||
return base.OnBeforeShowingCharacter(character);
|
||||
}
|
||||
|
||||
// fire off the task
|
||||
RunActionMarkup(character.index).Forget();
|
||||
|
||||
return ActionStatus.Running;
|
||||
}
|
||||
protected override ActionStatus OnAfterWaitingCharacter(CharacterData character)
|
||||
{
|
||||
// the character has been presented which means it is time to advance
|
||||
// so we flag this as done (if not already done) and refresh it
|
||||
currentCharacterProgressSource?.TrySetResult();
|
||||
currentCharacterProgressSource = new();
|
||||
currentContentPresentationCancellationToken.Register(() =>
|
||||
{
|
||||
currentCharacterProgressSource?.TrySetCanceled();
|
||||
});
|
||||
|
||||
// need to check if this is the last character
|
||||
// if it is we also want to finish off the entire line presentation
|
||||
if (currentContentPresentation != null && Animator != null)
|
||||
{
|
||||
if (character.index == Animator.textWithoutAnyTag.Length -1)
|
||||
{
|
||||
currentContentPresentation?.TrySetResult();
|
||||
}
|
||||
}
|
||||
lastProcessedCharacterIndex = character.index;
|
||||
|
||||
return ActionStatus.Finished;
|
||||
}
|
||||
|
||||
private async YarnTask RunActionMarkup(int index)
|
||||
{
|
||||
if (!currentContent.HasValue)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (currentCharacterProgressSource == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// if we aren't null that means we have a task already in progress for presenting the markup
|
||||
// because this method might get called every frame we want to ensure that doesn't happen
|
||||
// so we capture and move over it
|
||||
if (currentCharacterMarkupProgress != null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
currentCharacterMarkupProgress = new();
|
||||
currentContentPresentationCancellationToken.Register(() =>
|
||||
{
|
||||
currentCharacterMarkupProgress?.TrySetCanceled();
|
||||
});
|
||||
|
||||
foreach (var processor in ActionMarkupHandlers)
|
||||
{
|
||||
await processor.OnCharacterWillAppear(index, currentContent.Value, currentContentPresentationCancellationToken);
|
||||
}
|
||||
currentCharacterProgressSource.TrySetResult();
|
||||
currentCharacterMarkupProgress.TrySetResult();
|
||||
currentCharacterMarkupProgress = null;
|
||||
}
|
||||
|
||||
public void ContentDidDismiss()
|
||||
{
|
||||
this.ShowText(string.Empty);
|
||||
}
|
||||
|
||||
public TMPro.TMP_Text? TextElement { get; set; }
|
||||
}
|
||||
#elif YS_USE_TEXT_ANIMATOR_2
|
||||
public class NullTextAnimatorYarnTypewriter : UnityEngine.MonoBehaviour {}
|
||||
#endif
|
||||
}
|
||||
+9
@@ -0,0 +1,9 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 9c2c859ff89524cb4b0efeeb772dfd10
|
||||
AssetOrigin:
|
||||
serializedVersion: 1
|
||||
productId: 267061
|
||||
packageName: Yarn Spinner+ for Unity, the friendly dialogue and narrative tool
|
||||
packageVersion: 3.2.8
|
||||
assetPath: Packages/dev.yarnspinner.unity.addons.textanimator/Scripts/TextAnimatorYarnTypewriter_v3.cs
|
||||
uploadId: 968678
|
||||
+33
@@ -0,0 +1,33 @@
|
||||
{
|
||||
"name": "YarnSpinner.Addons.TextAnimatorIntegration",
|
||||
"rootNamespace": "",
|
||||
"references": [
|
||||
"GUID:6055be8ebefd69e48b49212b09b47b2f",
|
||||
"GUID:75469ad4d38634e559750d17036d5f7c",
|
||||
"GUID:34aa492b82754644eac2f903cd496268",
|
||||
"GUID:1e113d3b5d77bc04eab508251483e8ff",
|
||||
"GUID:e539678cf69674b418d82e89c16a9753",
|
||||
"GUID:3a299c53e4c683b4eb4a04c9ad9e648f",
|
||||
"UniTask"
|
||||
],
|
||||
"includePlatforms": [],
|
||||
"excludePlatforms": [],
|
||||
"allowUnsafeCode": false,
|
||||
"overrideReferences": false,
|
||||
"precompiledReferences": [],
|
||||
"autoReferenced": true,
|
||||
"defineConstraints": [],
|
||||
"versionDefines": [
|
||||
{
|
||||
"name": "com.unity.inputsystem",
|
||||
"expression": "1.0.0",
|
||||
"define": "USE_INPUTSYSTEM"
|
||||
},
|
||||
{
|
||||
"name": "com.unity.ugui",
|
||||
"expression": "2",
|
||||
"define": "USE_TMP"
|
||||
}
|
||||
],
|
||||
"noEngineReferences": false
|
||||
}
|
||||
+14
@@ -0,0 +1,14 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 44199294ed9884553846d30d420ad69a
|
||||
AssemblyDefinitionImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
AssetOrigin:
|
||||
serializedVersion: 1
|
||||
productId: 267061
|
||||
packageName: Yarn Spinner+ for Unity, the friendly dialogue and narrative tool
|
||||
packageVersion: 3.2.8
|
||||
assetPath: Packages/dev.yarnspinner.unity.addons.textanimator/YarnSpinner.Addons.TextAnimatorIntegration.asmdef
|
||||
uploadId: 968678
|
||||
@@ -0,0 +1,20 @@
|
||||
{
|
||||
"name": "dev.yarnspinner.unity.addons.textanimator",
|
||||
"version": "3.1.0",
|
||||
"displayName": "Text Animator for Yarn Spinner",
|
||||
"description": "Description goes here",
|
||||
"unity": "2022.3",
|
||||
"dependencies": {
|
||||
"dev.yarnspinner.unity": "3.1.0"
|
||||
},
|
||||
"keywords": [
|
||||
"Dialogue",
|
||||
"Yarn"
|
||||
],
|
||||
"author": {
|
||||
"name": "Yarn Spinner Pty Ltd",
|
||||
"url": "https://yarnspinner.dev"
|
||||
},
|
||||
"hideInEditor": false,
|
||||
"type": "tool"
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 1edc4722010094a40bc1921a9164d800
|
||||
PackageManifestImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
AssetOrigin:
|
||||
serializedVersion: 1
|
||||
productId: 267061
|
||||
packageName: Yarn Spinner+ for Unity, the friendly dialogue and narrative tool
|
||||
packageVersion: 3.2.8
|
||||
assetPath: Packages/dev.yarnspinner.unity.addons.textanimator/package.json
|
||||
uploadId: 968678
|
||||
Reference in New Issue
Block a user