Skip to content

Commit dc599a0

Browse files
committed
- Minor improvements
- Started reworking the parsing system - Fixed maxvisible character reveal
1 parent 0f81a16 commit dc599a0

18 files changed

+445
-284
lines changed

Runtime/Components/IntervalTree.cs

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
using UnityEngine;
2+
3+
namespace BP.TMPA
4+
{
5+
public class IntervalTree : MonoBehaviour
6+
{
7+
// Start is called once before the first execution of Update after the MonoBehaviour is created
8+
void Start()
9+
{
10+
11+
}
12+
13+
// Update is called once per frame
14+
void Update()
15+
{
16+
17+
}
18+
}
19+
}

Runtime/Components/IntervalTree.cs.meta

Lines changed: 2 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Lines changed: 9 additions & 151 deletions
Original file line numberDiff line numberDiff line change
@@ -1,190 +1,48 @@
11
using System;
22
using System.Collections.Generic;
33
using System.Linq;
4-
using System.Text.RegularExpressions;
54
using TMPro;
6-
using UnityEngine.Pool;
75

86
namespace BP.TMPA
97
{
108
internal class TextMeshPreprocessor : ITextPreprocessor, IDisposable
119
{
12-
private const string tagPattern = @"<(\/?)([A-Za-z0-9]+)(=[^>]+)?(\/?)>";
13-
1410
// Caching mechanisms
1511
private string lastInputText;
1612
private string processedText;
13+
private readonly TagValidator tagValidator;
1714

18-
// Object pooling for TagData
19-
private readonly ObjectPool<TextTagData> tagDataPool;
20-
private readonly ObjectPool<List<TextTagData>> tagListPool;
21-
22-
public Dictionary<int, List<TextTagData>> CharacterTagEffects { get; } = new();
23-
private readonly Func<string, string, bool> tagValidator;
24-
25-
// Reusable collections to reduce allocations
26-
private readonly Dictionary<string, Stack<TextTagData>> activeStacks = new(16);
27-
28-
public TextMeshPreprocessor(Func<string, string, bool> tagValidator)
15+
public TextMeshPreprocessor(TagValidator tagValidator)
2916
{
30-
this.tagValidator = tagValidator ?? throw new ArgumentNullException(nameof(tagValidator));
31-
32-
tagDataPool = new ObjectPool<TextTagData>(
33-
createFunc: () => new TextTagData(),
34-
actionOnGet: (tag) => tag.Reset(),
35-
actionOnRelease: (tag) => tag.Clear(),
36-
defaultCapacity: 64
37-
);
38-
39-
tagListPool = new ObjectPool<List<TextTagData>>(
40-
createFunc: () => new List<TextTagData>(),
41-
actionOnGet: (list) => list.Clear(),
42-
defaultCapacity: 64
43-
);
17+
this.tagValidator = tagValidator;
4418
}
4519

4620
public string PreprocessText(string inputText)
4721
{
4822
// Checks if the last processed text really changed
4923
if (inputText != lastInputText)
5024
{
51-
processedText = ProcessText(inputText);
25+
processedText = TextParser.RemoveCustomTags(inputText, tagValidator);
5226
lastInputText = inputText;
5327
}
5428

5529
return processedText;
5630
}
5731

58-
private string ProcessText(string input)
59-
{
60-
ReleaseResources();
61-
CharacterTagEffects.Clear();
62-
activeStacks.Clear();
63-
64-
string processedText = input;
65-
var matches = Regex.Matches(input, tagPattern);
66-
int charIndex = 0;
67-
68-
foreach (Match match in matches.Cast<Match>())
69-
{
70-
// Tag properties
71-
string tag = match.Value;
72-
bool isClosingTag = match.Groups[1].Value == "/";
73-
string tagName = match.Groups[2].Value;
74-
string attributes = match.Groups[3].Value;
75-
int tagIndex = match.Index - charIndex;
76-
77-
if (tagValidator(tagName, attributes))
78-
{
79-
if (isClosingTag)
80-
{
81-
if (!activeStacks.TryGetValue(tagName, out var activeStack))
82-
continue;
83-
84-
var matchingOpenTag = activeStack.Pop();
85-
if (matchingOpenTag != null)
86-
{
87-
matchingOpenTag.Close(tagIndex);
88-
for (int i = matchingOpenTag.StartIndex; i < matchingOpenTag.EndIndex; i++)
89-
{
90-
// Use pooled list for character tag effects
91-
if (!CharacterTagEffects.TryGetValue(i, out var tagList))
92-
{
93-
tagList = tagListPool.Get();
94-
CharacterTagEffects[i] = tagList;
95-
}
96-
97-
// Only add the innermost tag at each position
98-
if (!tagList.Any(t => t.Name == matchingOpenTag.Name))
99-
tagList.Add(matchingOpenTag);
100-
}
101-
}
102-
}
103-
else
104-
{
105-
var tagData = tagDataPool.Get();
106-
tagData.Initialize(tag, tagName, attributes, tagIndex, int.MaxValue);
107-
AddTagToStack(tagName, tagData);
108-
}
109-
110-
// Removes tag from display and offsets the range
111-
processedText = processedText.Replace(tag, string.Empty);
112-
charIndex += tag.Length;
113-
}
114-
}
115-
116-
foreach (var stack in activeStacks)
117-
{
118-
foreach (var tag in stack.Value)
119-
{
120-
for (int i = tag.StartIndex; i < processedText.Length; i++)
121-
{
122-
// Use pooled list for character tag effects
123-
if (!CharacterTagEffects.TryGetValue(i, out var tagList))
124-
{
125-
tagList = tagListPool.Get();
126-
CharacterTagEffects[i] = tagList;
127-
}
128-
129-
if (!tagList.Any(t => t.Name == tag.Name))
130-
tagList.Add(tag);
131-
}
132-
}
133-
}
134-
135-
return processedText;
136-
}
137-
138-
private void AddTagToStack(string name, TextTagData data)
32+
public List<TextTagData> GetTagEffectsAtIndex(int index)
13933
{
140-
if (activeStacks.TryGetValue(name, out var stack))
141-
{
142-
if (stack.Peek().RawTag != data.RawTag)
143-
stack.Push(data);
144-
}
145-
else
146-
{
147-
var newStack = new Stack<TextTagData>();
148-
newStack.Push(data);
149-
activeStacks.Add(name, newStack);
150-
}
34+
return Array.Empty<TextTagData>().ToList();
15135
}
15236

153-
/// <summary>
154-
/// Releases all tag lists back to the pool.
155-
/// </summary>
156-
private void ReleaseResources()
157-
{
158-
// Release all the tag lists before rebuilding them
159-
foreach (var tagList in CharacterTagEffects.Values)
160-
{
161-
if (tagList != null)
162-
{
163-
tagListPool.Release(tagList);
164-
}
165-
}
166-
167-
// Clear the dictionary as well
168-
CharacterTagEffects.Clear();
169-
}
170-
171-
public List<TextTagData> GetTagEffectsAtIndex(int index)
37+
public void ClearCache()
17238
{
173-
CharacterTagEffects.TryGetValue(index, out var tags);
174-
return tags;
39+
lastInputText = string.Empty;
40+
processedText = string.Empty;
17541
}
17642

17743
public void Dispose()
17844
{
179-
tagDataPool.Clear();
180-
tagListPool.Clear();
181-
CharacterTagEffects.Clear();
182-
}
18345

184-
public void ClearCache()
185-
{
186-
lastInputText = string.Empty;
187-
processedText = string.Empty;
18846
}
18947
}
19048
}

0 commit comments

Comments
 (0)