| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202 | <#@ template language="C#" #><#@ assembly name="System.Core" #><#@ import namespace="System.Linq" #><#@ import namespace="System.Text" #><#@ import namespace="System.Collections.Generic" #><#@ output extension=".cs" #><#    var sizes = new int[]    {        32, 64, 128, 512, 4096    };#>using Unity.Collections;using Unity.Burst;using Unity.Mathematics;using Unity.Collections.LowLevel.Unsafe;namespace LitMotion{    internal static partial class FixedStringHelper    {<# foreach(var size in sizes) { #>        [BurstCompile]        public static int GetUtf8CharCount(ref FixedString<#=size#>Bytes runes)        {            int length = 0;            var enumerator = runes.GetEnumerator();            while (enumerator.MoveNext()) length++;            return length;        }        static Unicode.Rune GetRuneOf(ref FixedString<#=size#>Bytes text, int charIndex)        {            int index = 0;            var enumerator = text.GetEnumerator();            while (enumerator.MoveNext())            {                if (index == charIndex) return enumerator.Current;                index++;            }            return Unicode.BadRune;        }        [BurstCompile]        public static void Interpolate(ref FixedString<#=size#>Bytes start, ref FixedString<#=size#>Bytes end, float t, ScrambleMode scrambleMode, bool richTextEnabled, ref Random randomState, ref FixedString64Bytes customScrambleChars, out FixedString<#=size#>Bytes result)        {            if (richTextEnabled)            {                RichTextParser.GetSymbols(ref start, Allocator.Temp, out var startTextSymbols, out var startTextUtf8Length);                RichTextParser.GetSymbols(ref end, Allocator.Temp, out var endTextSymbols, out var endTextUtf8Length);                FillRichText(ref startTextSymbols, ref endTextSymbols, startTextUtf8Length, endTextUtf8Length, t, scrambleMode, ref randomState, ref customScrambleChars, out result);                startTextSymbols.Dispose();                endTextSymbols.Dispose();            }            else            {                FillText(ref start, ref end, t, scrambleMode, ref randomState, ref customScrambleChars, out result);            }        }        unsafe static void FillText(            ref FixedString<#=size#>Bytes start,            ref FixedString<#=size#>Bytes end,            float t,            ScrambleMode scrambleMode,            ref Random randomState,            ref FixedString64Bytes customScrambleChars,            out FixedString<#=size#>Bytes result)        {            var startTextUtf8Length = GetUtf8CharCount(ref start);            var endTextUtf8Length = GetUtf8CharCount(ref end);            var length = math.max(startTextUtf8Length, endTextUtf8Length);            var currentTextLength = (int)math.round(length * t);            var enumeratorStart = start.GetEnumerator();            var enumeratorEnd = end.GetEnumerator();            result = new();                        for (int i = 0; i < length; i++)            {                var startMoveNext = enumeratorStart.MoveNext();                var endMoveNext = enumeratorEnd.MoveNext();                if (i < currentTextLength)                {                    if (endMoveNext)                    {                        result.Append(enumeratorEnd.Current);                    }                }                else                {                    if (startMoveNext)                    {                        result.Append(enumeratorStart.Current);                    }                }            }            FillScrambleChars(ref result, scrambleMode, ref randomState, ref customScrambleChars, length - currentTextLength);        }        unsafe static void FillRichText(            ref UnsafeList<RichTextSymbol<#=size#>Bytes> startSymbols,            ref UnsafeList<RichTextSymbol<#=size#>Bytes> endSymbols,            int startTextUtf8Length,            int endTextUtf8Length,            float t,            ScrambleMode scrambleMode,            ref Random randomState,            ref FixedString64Bytes customScrambleChars,            out FixedString<#=size#>Bytes result)        {            var length = math.max(startTextUtf8Length, endTextUtf8Length);            var currentTextLength = (int)math.round(length * t);            var slicedText1 = SliceSymbols(ref endSymbols, 0, currentTextLength, out var length1);            var slicedText2 = SliceSymbols(ref startSymbols, currentTextLength + 1, length - 1, out var length2);            result = new FixedString<#=size#>Bytes();            result.Append(slicedText1);            result.Append(slicedText2);            FillScrambleChars(ref result, scrambleMode, ref randomState, ref customScrambleChars, length - (length1 + length2));        }        unsafe static void FillScrambleChars(            ref FixedString<#=size#>Bytes target,            ScrambleMode scrambleMode,            ref Random randomState,            ref FixedString64Bytes customScrambleChars,            int count)        {            if (scrambleMode == ScrambleMode.None) return;            if (randomState.state == 0) randomState.InitState();            if (scrambleMode == ScrambleMode.Custom)            {                var customScrambleCharsUtf8Length = GetUtf8CharCount(ref customScrambleChars);                for (int i = 0; i < count; i++)                {                    target.Append(GetRuneOf(ref customScrambleChars, randomState.NextInt(0, customScrambleCharsUtf8Length)));                }            }            else            {                for (int i = 0; i < count; i++)                {                    target.Append(GetScrambleChar(scrambleMode, ref randomState));                }            }        }        unsafe static FixedString<#=size#>Bytes SliceSymbols(ref UnsafeList<RichTextSymbol<#=size#>Bytes> symbols, int from, int to, out int resultRichTextLength)        {            var text = new FixedString<#=size#>Bytes();            RichTextSymbol<#=size#>Bytes* symbolsPtr = symbols.Ptr;            var offset = 0;            var tagIndent = 0;            resultRichTextLength = 0;            for (int i = 0; i < symbols.Length; i++)            {                RichTextSymbol<#=size#>Bytes* symbol = symbolsPtr + i;                switch (symbol->Type)                {                    case RichTextSymbolType.Text:                        var enumerator = symbol->Text.GetEnumerator();                        while (enumerator.MoveNext())                        {                            var current = enumerator.Current;                            if (from <= offset && offset < to)                            {                                text.Append(current);                                resultRichTextLength++;                            }                            offset++;                            if (offset >= to && tagIndent == 0) goto LOOP_END;                        }                        break;                    case RichTextSymbolType.TagStart:                        text.Append(symbol->Text);                        tagIndent++;                        break;                    case RichTextSymbolType.TagEnd:                        text.Append(symbol->Text);                        tagIndent--;                        if (offset >= to && tagIndent == 0) goto LOOP_END;                        break;                }            }        LOOP_END:            return text;        }<# } #>    }}
 |