1
0
mirror of https://github.com/Cardidi/dotween-upm-fork.git synced 2026-02-09 08:38:45 +08:00

- Added rich text support to string tweens (still needs work)

- Added ScrambleMode enum for additional scrambleMode options
This commit is contained in:
Daniele Giardini 2015-03-29 12:31:33 +02:00
parent 79c6148734
commit 38d7a1b04c
19 changed files with 251 additions and 40 deletions

View File

@ -21,7 +21,7 @@ namespace DG.Tweening
public class DOTween
{
/// <summary>DOTween's version</summary>
public static readonly string Version = "1.0.405";
public static readonly string Version = "1.0.410";
///////////////////////////////////////////////
// Options ////////////////////////////////////
@ -129,34 +129,31 @@ namespace DG.Tweening
if (initialized) return instance;
if (!Application.isPlaying || isQuitting) return null;
bool doRecycleAllByDefault = recycleAllByDefault == null ? false : (bool)recycleAllByDefault;
bool doUseSafeMode = useSafeMode == null ? true : (bool)useSafeMode;
LogBehaviour doLogBehaviour = logBehaviour == null ? LogBehaviour.ErrorsOnly : (LogBehaviour)logBehaviour;
DOTweenSettings settings = Resources.Load(DOTweenSettings.AssetName) as DOTweenSettings;
return Init(settings, doRecycleAllByDefault, doUseSafeMode, doLogBehaviour);
return Init(settings, recycleAllByDefault, useSafeMode, logBehaviour);
}
// Auto-init
static void AutoInit()
{
DOTweenSettings settings = Resources.Load(DOTweenSettings.AssetName) as DOTweenSettings;
if (settings == null) Init(null, defaultRecyclable, useSafeMode, logBehaviour);
else Init(settings, settings.defaultRecyclable, settings.useSafeMode, settings.logBehaviour);
Init(settings, null, null, null);
}
// Full init
static IDOTweenInit Init(DOTweenSettings settings, bool recycleAllByDefault, bool useSafeMode, LogBehaviour logBehaviour)
static IDOTweenInit Init(DOTweenSettings settings, bool? recycleAllByDefault, bool? useSafeMode, LogBehaviour? logBehaviour)
{
initialized = true;
// Options
DOTween.defaultRecyclable = recycleAllByDefault;
DOTween.useSafeMode = useSafeMode;
DOTween.logBehaviour = logBehaviour;
if (recycleAllByDefault != null) DOTween.defaultRecyclable = (bool)recycleAllByDefault;
if (useSafeMode != null) DOTween.useSafeMode = (bool)useSafeMode;
if (logBehaviour != null) DOTween.logBehaviour = (LogBehaviour)logBehaviour;
// Gameobject - also assign instance
DOTweenComponent.Create();
// Assign settings
if (settings != null) {
// DOTween.useSafeMode = settings.useSafeMode;
// DOTween.logBehaviour = settings.logBehaviour;
// DOTween.defaultRecyclable = settings.defaultRecyclable;
if (useSafeMode == null) DOTween.useSafeMode = settings.useSafeMode;
if (logBehaviour == null) DOTween.logBehaviour = settings.logBehaviour;
if (recycleAllByDefault == null) DOTween.defaultRecyclable = settings.defaultRecyclable;
DOTween.defaultRecyclable = recycleAllByDefault == null ? settings.defaultRecyclable : (bool)recycleAllByDefault;
DOTween.showUnityEditorReport = settings.showUnityEditorReport;
DOTween.defaultAutoPlay = settings.defaultAutoPlay;
DOTween.defaultUpdateType = settings.defaultUpdateType;
@ -168,7 +165,7 @@ namespace DG.Tweening
DOTween.defaultLoopType = settings.defaultLoopType;
}
// Log
if (Debugger.logPriority >= 2) Debugger.Log("DOTween initialization (useSafeMode: " + useSafeMode + ", logBehaviour: " + logBehaviour + ")");
if (Debugger.logPriority >= 2) Debugger.Log("DOTween initialization (useSafeMode: " + DOTween.useSafeMode + ", recycling: " + (DOTween.defaultRecyclable ? "ON" : "OFF") + ", logBehaviour: " + DOTween.logBehaviour + ")");
return instance;
}
@ -827,9 +824,7 @@ namespace DG.Tweening
{
if (initialized || !Application.isPlaying || isQuitting) return;
// Init(defaultRecyclable, useSafeMode, logBehaviour);
AutoInit();
// Debugger.LogWarning("DOTween auto-initialized with default settings (recycleAllByDefault: " + defaultRecyclable + ", useSafeMode: " + useSafeMode + ", logBehaviour: " + logBehaviour + "). Call DOTween.Init before creating your first tween in order to choose the settings yourself");
}
static TweenerCore<T1, T2, TPlugOptions> ApplyTo<T1, T2, TPlugOptions>(

View File

@ -81,6 +81,7 @@
<Compile Include="Plugins\Core\PathCore\Path.cs" />
<Compile Include="Plugins\PathPlugin.cs" />
<Compile Include="RotateMode.cs" />
<Compile Include="ScrambleMode.cs" />
<Compile Include="TweenExtensions.cs" />
<Compile Include="LoopType.cs" />
<Compile Include="Plugins\ColorPlugin.cs" />

View File

@ -9,7 +9,11 @@ namespace DG.Tweening.Plugins.Options
{
public struct StringOptions
{
public bool scramble;
public bool richTextEnabled;
public ScrambleMode scrambleMode;
public char[] scrambledChars; // If empty uses default scramble characters
// Stored by StringPlugin
internal int startValueStrippedLength, changeValueStrippedLength; // No-tag lengths of start and change value
}
}

View File

@ -6,6 +6,7 @@
using System;
using System.Text;
using System.Text.RegularExpressions;
using DG.Tweening.Core;
using DG.Tweening.Core.Easing;
using DG.Tweening.Plugins.Core;
@ -47,6 +48,10 @@ namespace DG.Tweening.Plugins
public override void SetChangeValue(TweenerCore<string, string, StringOptions> t)
{
t.changeValue = t.endValue;
// Store no-tags versions of values
t.plugOptions.startValueStrippedLength = Regex.Replace(t.startValue, @"<[^>]*>", "").Length;
t.plugOptions.changeValueStrippedLength = Regex.Replace(t.changeValue, @"<[^>]*>", "").Length;
}
public override float GetSpeedBasedDuration(StringOptions options, float unitsXSecond, string changeValue)
@ -73,24 +78,24 @@ namespace DG.Tweening.Plugins
}
}
int startValueLen = startValue.Length;
int changeValueLen = changeValue.Length;
int startValueLen = options.richTextEnabled ? options.startValueStrippedLength : startValue.Length;
int changeValueLen = options.richTextEnabled ? options.changeValueStrippedLength : changeValue.Length;
int len = (int)Math.Round(changeValueLen * EaseManager.Evaluate(t.easeType, t.customEase, elapsed, duration, t.easeOvershootOrAmplitude, t.easePeriod));
if (len > changeValueLen) len = changeValueLen;
else if (len < 0) len = 0;
if (isRelative) {
_Buffer.Append(startValue);
if (options.scramble) {
setter(_Buffer.Append(changeValue, 0, len).AppendScrambledChars(changeValueLen - len, options.scrambledChars ?? StringPluginExtensions.ScrambledChars).ToString());
if (options.scrambleMode != ScrambleMode.None) {
setter(_Buffer.Append(changeValue, 0, len).AppendScrambledChars(changeValueLen - len, ScrambledCharsToUse(options)).ToString());
return;
}
setter(_Buffer.Append(changeValue, 0, len).ToString());
return;
}
if (options.scramble) {
setter(_Buffer.Append(changeValue, 0, len).AppendScrambledChars(changeValueLen - len, options.scrambledChars ?? StringPluginExtensions.ScrambledChars).ToString());
if (options.scrambleMode != ScrambleMode.None) {
setter(_Buffer.Append(changeValue, 0, len).AppendScrambledChars(changeValueLen - len, ScrambledCharsToUse(options)).ToString());
return;
}
@ -101,10 +106,125 @@ namespace DG.Tweening.Plugins
float perc = (float)len / changeValueLen;
startValueMaxLen -= (int)(startValueMaxLen * perc);
} else startValueMaxLen -= len;
_Buffer.Append(changeValue, 0, len);
if (len < changeValueLen && len < startValueLen) _Buffer.Append(startValue, len, startValueMaxLen);
Append(changeValue, 0, len, options.richTextEnabled);
if (len < changeValueLen && len < startValueLen) Append(startValue, len, options.richTextEnabled ? len + startValueMaxLen : startValueMaxLen, options.richTextEnabled);
setter(_Buffer.ToString());
}
// Manages eventual rich text, if enabled, readding tags to the given string and closing them when necessary
void Append(string value, int startIndex, int length, bool richTextEnabled)
{
if (!richTextEnabled) {
_Buffer.Append(value, startIndex, length);
return;
}
const string tagMatch = @"<.*?(>)";
const string closeTagMatch = @"(</).*?>";
bool hasOpenTag = false;
int fullLen = value.Length;
int i;
for (i = 0; i < length; ++i) {
Char c = value[i];
if (c == '<') {
bool hadOpenTag = hasOpenTag;
hasOpenTag = !(i < fullLen - 1 && value[i + 1] == '/');
string s = value.Substring(i);
Match m = Regex.Match(s, tagMatch);
if (m.Success) {
if (!hasOpenTag && !hadOpenTag) {
// We have a closing tag without an opening tag, try to find opening tag an apply it
int t = i - 1;
while (t > -1) {
if (value[t] == '<' && value[t + 1] != '/') {
_Buffer.Insert(0, value.Substring(t, value.IndexOf('>', t) + 1 - t));
break;
}
t--;
}
}
// Append tag and increase loop length to match
_Buffer.Append(m.Value);
int add = m.Groups[1].Index + 1;
length += add;
startIndex += add;
i += add - 1;
}
} else if (i >= startIndex) _Buffer.Append(c);
}
if (hasOpenTag && i < fullLen - 1) {
// Last open tag was not closed: find next close tag and apply it
string next = value.Substring(i);
Match m = Regex.Match(next, closeTagMatch);
if (m.Success) _Buffer.Append(m.Value);
}
}
char[] ScrambledCharsToUse(StringOptions options)
{
switch (options.scrambleMode) {
case ScrambleMode.Uppercase:
return StringPluginExtensions.ScrambledCharsUppercase;
case ScrambleMode.Lowercase:
return StringPluginExtensions.ScrambledCharsLowercase;
case ScrambleMode.Numerals:
return StringPluginExtensions.ScrambledCharsNumerals;
case ScrambleMode.Custom:
return options.scrambledChars;
default:
return StringPluginExtensions.ScrambledCharsAll;
}
}
// public override void EvaluateAndApply(StringOptions options, Tween t, bool isRelative, DOGetter<string> getter, DOSetter<string> setter, float elapsed, string startValue, string changeValue, float duration, bool usingInversePosition)
// {
// _Buffer.Remove(0, _Buffer.Length);
//
// // Incremental works only with relative tweens (otherwise the tween makes no sense)
// // Sequence with Incremental loops have no effect here (why should they?)
// if (isRelative && t.loopType == LoopType.Incremental) {
// int iterations = t.isComplete ? t.completedLoops - 1 : t.completedLoops;
// if (iterations > 0) {
// _Buffer.Append(startValue);
// for (int i = 0; i < iterations; ++i) _Buffer.Append(changeValue);
// startValue = _Buffer.ToString();
// _Buffer.Remove(0, _Buffer.Length);
// }
// }
//
// int startValueLen = startValue.Length;
// int changeValueLen = changeValue.Length;
// int len = (int)Math.Round(changeValueLen * EaseManager.Evaluate(t.easeType, t.customEase, elapsed, duration, t.easeOvershootOrAmplitude, t.easePeriod));
// if (len > changeValueLen) len = changeValueLen;
// else if (len < 0) len = 0;
//
// if (isRelative) {
// _Buffer.Append(startValue);
// if (options.scramble) {
// setter(_Buffer.Append(changeValue, 0, len).AppendScrambledChars(changeValueLen - len, options.scrambledChars ?? StringPluginExtensions.ScrambledChars).ToString());
// return;
// }
// setter(_Buffer.Append(changeValue, 0, len).ToString());
// return;
// }
//
// if (options.scramble) {
// setter(_Buffer.Append(changeValue, 0, len).AppendScrambledChars(changeValueLen - len, options.scrambledChars ?? StringPluginExtensions.ScrambledChars).ToString());
// return;
// }
//
// int diff = startValueLen - changeValueLen;
// int startValueMaxLen = startValueLen;
// if (diff > 0) {
// // String to be replaced is longer than endValue: remove parts of it while tweening
// float perc = (float)len / changeValueLen;
// startValueMaxLen -= (int)(startValueMaxLen * perc);
// } else startValueMaxLen -= len;
// _Buffer.Append(changeValue, 0, len);
// if (len < changeValueLen && len < startValueLen) _Buffer.Append(startValue, len, startValueMaxLen);
// setter(_Buffer.ToString());
// }
}
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
@ -113,16 +233,28 @@ namespace DG.Tweening.Plugins
internal static class StringPluginExtensions
{
public static readonly char[] ScrambledChars = new[] {
public static readonly char[] ScrambledCharsAll = new[] {
'A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','X','Y','Z',
// 'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','x','y','z',
// '1','2','3','4','5','6','7','8','9','0'
'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','x','y','z',
'1','2','3','4','5','6','7','8','9','0'
};
public static readonly char[] ScrambledCharsUppercase = new[] {
'A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','X','Y','Z'
};
public static readonly char[] ScrambledCharsLowercase = new[] {
'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','x','y','z'
};
public static readonly char[] ScrambledCharsNumerals = new[] {
'1','2','3','4','5','6','7','8','9','0'
};
static int _lastRndSeed;
static StringPluginExtensions()
{
ScrambledChars.ScrambleChars();
ScrambledCharsAll.ScrambleChars();
ScrambledCharsUppercase.ScrambleChars();
ScrambledCharsLowercase.ScrambleChars();
ScrambledCharsNumerals.ScrambleChars();
}
internal static void ScrambleChars(this char[] chars)

View File

@ -0,0 +1,35 @@
// Author: Daniele Giardini - http://www.demigiant.com
// Created: 2015/03/29 11:12
namespace DG.Tweening
{
/// <summary>
/// Type of scramble to apply to string tweens
/// </summary>
public enum ScrambleMode
{
/// <summary>
/// No scrambling of characters
/// </summary>
None,
/// <summary>
/// A-Z + a-z + 0-9 characters
/// </summary>
All,
/// <summary>
/// A-Z characters
/// </summary>
Uppercase,
/// <summary>
/// a-z characters
/// </summary>
Lowercase,
/// <summary>
/// 0-9 characters
/// </summary>
Numerals,
/// <summary>
/// Custom characters
/// </summary>
Custom
}
}

View File

@ -674,15 +674,18 @@ namespace DG.Tweening
}
/// <summary>Options for Vector4 tweens</summary>
/// <param name="scramble">If TRUE the string will appear from a random animation of characters</param>
/// <param name="richTextEnabled">If TRUE, rich text will be interpreted correctly while animated,
/// otherwise all tags will be considered as normal text</param>
/// <param name="scrambleMode">The type of scramble to use, if any</param>
/// <param name="scrambleChars">A string containing the characters to use for scrambling.
/// Use as many characters as possible (minimum 10) because DOTween uses a fast scramble mode which gives better results with more characters.
/// Leave it to NULL to use default ones</param>
public static Tweener SetOptions(this TweenerCore<string, string, StringOptions> t, bool scramble, string scrambleChars = null)
public static Tweener SetOptions(this TweenerCore<string, string, StringOptions> t, bool richTextEnabled, ScrambleMode scrambleMode = ScrambleMode.None, string scrambleChars = null)
{
if (!t.active) return t;
t.plugOptions.scramble = scramble;
t.plugOptions.richTextEnabled = richTextEnabled;
t.plugOptions.scrambleMode = scrambleMode;
if (!string.IsNullOrEmpty(scrambleChars)) {
if (scrambleChars.Length <= 1) scrambleChars += scrambleChars;
t.plugOptions.scrambledChars = scrambleChars.ToCharArray();

View File

@ -226,14 +226,16 @@ namespace DG.Tweening
/// <summary>Tweens a Text's text to the given value.
/// Also stores the Text as the tween's target so it can be used for filtered operations</summary>
/// <param name="endValue">The end string to tween to</param><param name="duration">The duration of the tween</param>
/// <param name="scramble">If TRUE the string will appear from a random animation of characters</param>
/// <param name="richTextEnabled">If TRUE (default), rich text will be interpreted correctly while animated,
/// otherwise all tags will be considered as normal text</param>
/// <param name="scrambleMode">The type of scramble mode to use, if any</param>
/// <param name="scrambleChars">A string containing the characters to use for scrambling.
/// Use as many characters as possible (minimum 10) because DOTween uses a fast scramble mode which gives better results with more characters.
/// Leave it to NULL (default) to use default ones</param>
public static Tweener DOText(this Text target, string endValue, float duration, bool scramble = false, string scrambleChars = null)
public static Tweener DOText(this Text target, string endValue, float duration, bool richTextEnabled = true, ScrambleMode scrambleMode = ScrambleMode.None, string scrambleChars = null)
{
return DOTween.To(() => target.text, x => target.text = x, endValue, duration)
.SetOptions(scramble, scrambleChars)
.SetOptions(richTextEnabled, scrambleMode, scrambleChars)
.SetTarget(target);
}

View File

@ -567,9 +567,11 @@
<summary>Options for Vector4 tweens</summary>
<param name="snapping">If TRUE the tween will smoothly snap all values to integers</param>
</member>
<member name="M:DG.Tweening.TweenSettingsExtensions.SetOptions(DG.Tweening.Core.TweenerCore{System.String,System.String,DG.Tweening.Plugins.Options.StringOptions},System.Boolean,System.String)">
<member name="M:DG.Tweening.TweenSettingsExtensions.SetOptions(DG.Tweening.Core.TweenerCore{System.String,System.String,DG.Tweening.Plugins.Options.StringOptions},System.Boolean,DG.Tweening.ScrambleMode,System.String)">
<summary>Options for Vector4 tweens</summary>
<param name="scramble">If TRUE the string will appear from a random animation of characters</param>
<param name="richTextEnabled">If TRUE, rich text will be interpreted correctly while animated,
otherwise all tags will be considered as normal text</param>
<param name="scrambleMode">The type of scramble to use, if any</param>
<param name="scrambleChars">A string containing the characters to use for scrambling.
Use as many characters as possible (minimum 10) because DOTween uses a fast scramble mode which gives better results with more characters.
Leave it to NULL to use default ones</param>
@ -1941,5 +1943,40 @@
Public only so custom shortcuts can access some of these methods
</summary>
</member>
<member name="T:DG.Tweening.ScrambleMode">
<summary>
Type of scramble to apply to string tweens
</summary>
</member>
<member name="F:DG.Tweening.ScrambleMode.None">
<summary>
No scrambling of characters
</summary>
</member>
<member name="F:DG.Tweening.ScrambleMode.All">
<summary>
A-Z + a-z + 0-9 characters
</summary>
</member>
<member name="F:DG.Tweening.ScrambleMode.Uppercase">
<summary>
A-Z characters
</summary>
</member>
<member name="F:DG.Tweening.ScrambleMode.Lowercase">
<summary>
a-z characters
</summary>
</member>
<member name="F:DG.Tweening.ScrambleMode.Numerals">
<summary>
0-9 characters
</summary>
</member>
<member name="F:DG.Tweening.ScrambleMode.Custom">
<summary>
Custom characters
</summary>
</member>
</members>
</doc>

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -107,11 +107,13 @@
Also stores the Text as the tween's target so it can be used for filtered operations</summary>
<param name="endValue">The end value to reach</param><param name="duration">The duration of the tween</param>
</member>
<member name="M:DG.Tweening.ShortcutExtensions.DOText(UnityEngine.UI.Text,System.String,System.Single,System.Boolean,System.String)">
<member name="M:DG.Tweening.ShortcutExtensions.DOText(UnityEngine.UI.Text,System.String,System.Single,System.Boolean,DG.Tweening.ScrambleMode,System.String)">
<summary>Tweens a Text's text to the given value.
Also stores the Text as the tween's target so it can be used for filtered operations</summary>
<param name="endValue">The end string to tween to</param><param name="duration">The duration of the tween</param>
<param name="scramble">If TRUE the string will appear from a random animation of characters</param>
<param name="richTextEnabled">If TRUE (default), rich text will be interpreted correctly while animated,
otherwise all tags will be considered as normal text</param>
<param name="scrambleMode">The type of scramble mode to use, if any</param>
<param name="scrambleChars">A string containing the characters to use for scrambling.
Use as many characters as possible (minimum 10) because DOTween uses a fast scramble mode which gives better results with more characters.
Leave it to NULL (default) to use default ones</param>

Binary file not shown.