Skip to content

Commit 645b983

Browse files
authored
Merge pull request #2 from setchi/feature/unity2019
Unity2019 対応
2 parents 9f61133 + c94248e commit 645b983

5 files changed

Lines changed: 154 additions & 41 deletions

File tree

Assets/Hypertext/Examples/RegexExample.unity

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -325,7 +325,9 @@ MonoBehaviour:
325325
m_HorizontalOverflow: 0
326326
m_VerticalOverflow: 0
327327
m_LineSpacing: 1
328-
m_Text: "URL: https://example.com/\r\nHashtag: #hoge"
328+
m_Text: 'URL: https://example.com/
329+
330+
Hashtag: #hoge'
329331
--- !u!1 &1167677275
330332
GameObject:
331333
m_ObjectHideFlags: 0

Assets/Hypertext/Examples/RegexHypertext.cs

Lines changed: 0 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
using System;
22
using System.Collections.Generic;
3-
using System.Linq;
43
using System.Text.RegularExpressions;
54
using UnityEngine;
65

@@ -63,28 +62,11 @@ public override void RemoveListeners()
6362
/// </summary>
6463
protected override void AddListeners()
6564
{
66-
var lineCount = text.Count(x => x == '\n') + 1;
67-
bool hasFolded = lineCount != cachedTextGenerator.lineCount;
68-
6965
foreach (var entry in entries)
7066
{
7167
foreach (Match match in Regex.Matches(text, entry.RegexPattern))
7268
{
73-
#if UNITY_2019_1_OR_NEWER
74-
if (hasFolded)
75-
{
76-
OnClick(match.Index, match.Value.Length, entry.Color, entry.Callback);
77-
}
78-
else
79-
{
80-
// 折り返していない場合のみ「空白」と「改行」が描画されないため、調整する
81-
var head = text.Substring(0, match.Index);
82-
var count = head.Count(x => x == ' ') + head.Count(x => x == '\n');
83-
OnClick(match.Index - count, match.Value.Length, entry.Color, entry.Callback);
84-
}
85-
#else
8669
OnClick(match.Index, match.Value.Length, entry.Color, entry.Callback);
87-
#endif
8870
}
8971
}
9072
}

Assets/Hypertext/Scripts/HypertextBase.cs

Lines changed: 148 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
using System;
22
using System.Collections.Generic;
3+
using System.Linq;
34
using UnityEngine;
45
using UnityEngine.EventSystems;
56
using UnityEngine.UI;
@@ -8,14 +9,7 @@ namespace Hypertext
89
{
910
public abstract class HypertextBase : Text, IPointerClickHandler
1011
{
11-
Canvas rootCanvas;
12-
Canvas RootCanvas => rootCanvas ?? (rootCanvas = GetComponentInParent<Canvas>());
13-
14-
const int CharVerts = 6;
15-
readonly List<Span> spans = new List<Span>();
16-
static readonly ObjectPool<List<UIVertex>> verticesPool = new ObjectPool<List<UIVertex>>(null, l => l.Clear());
17-
18-
struct Span
12+
class Span
1913
{
2014
public readonly int StartIndex;
2115
public readonly int Length;
@@ -33,6 +27,30 @@ public Span(int startIndex, int endIndex, Color color, Action<string> callback)
3327
}
3428
};
3529

30+
readonly List<Span> spans = new List<Span>();
31+
32+
// TODO: 頂点が生成されない空白文字をすべて洗い出す
33+
readonly char[] invisibleChars =
34+
{
35+
Space,
36+
Tab,
37+
LineFeed
38+
};
39+
static readonly ObjectPool<List<UIVertex>> verticesPool = new ObjectPool<List<UIVertex>>(null, l => l.Clear());
40+
41+
const int CharVerts = 6;
42+
const char
43+
Tab = '\t',
44+
LineFeed = '\n',
45+
Space = ' ',
46+
LesserThan = '<',
47+
GreaterThan = '>';
48+
49+
int[] visibleCharIndexMap;
50+
51+
Canvas rootCanvas;
52+
Canvas RootCanvas => rootCanvas ?? (rootCanvas = GetComponentInParent<Canvas>());
53+
3654
/// <summary>
3755
/// 指定した部分文字列にクリックイベントを登録します
3856
/// </summary>
@@ -75,33 +93,98 @@ public virtual void RemoveListeners()
7593
/// </summary>
7694
protected abstract void AddListeners();
7795

78-
protected override void OnPopulateMesh(VertexHelper vertexHelper)
96+
readonly UIVertex[] tempVerts = new UIVertex[4];
97+
protected override void OnPopulateMesh(VertexHelper toFill)
7998
{
80-
base.OnPopulateMesh(vertexHelper);
99+
if (font == null)
100+
{
101+
return;
102+
}
81103

82-
spans.Clear();
83-
AddListeners();
104+
m_DisableFontTextureRebuiltCallback = true;
105+
106+
var extents = rectTransform.rect.size;
107+
108+
var settings = GetGenerationSettings(extents);
109+
settings.generateOutOfBounds = true;
110+
cachedTextGenerator.PopulateWithErrors(text, settings, gameObject);
111+
112+
var verts = cachedTextGenerator.verts;
113+
var unitsPerPixel = 1 / pixelsPerUnit;
114+
int vertCount = verts.Count;
115+
116+
if (vertCount <= 0)
117+
{
118+
toFill.Clear();
119+
return;
120+
}
121+
122+
var roundingOffset = new Vector2(verts[0].position.x, verts[0].position.y) * unitsPerPixel;
123+
roundingOffset = PixelAdjustPoint(roundingOffset) - roundingOffset;
124+
toFill.Clear();
125+
126+
if (roundingOffset != Vector2.zero)
127+
{
128+
for (int i = 0; i < vertCount; ++i)
129+
{
130+
int tempVertsIndex = i & 3;
131+
tempVerts[tempVertsIndex] = verts[i];
132+
tempVerts[tempVertsIndex].position *= unitsPerPixel;
133+
tempVerts[tempVertsIndex].position.x += roundingOffset.x;
134+
tempVerts[tempVertsIndex].position.y += roundingOffset.y;
135+
136+
if (tempVertsIndex == 3)
137+
{
138+
toFill.AddUIVertexQuad(tempVerts);
139+
}
140+
}
141+
}
142+
else
143+
{
144+
for (int i = 0; i < vertCount; ++i)
145+
{
146+
int tempVertsIndex = i & 3;
147+
tempVerts[tempVertsIndex] = verts[i];
148+
tempVerts[tempVertsIndex].position *= unitsPerPixel;
149+
150+
if (tempVertsIndex == 3)
151+
{
152+
toFill.AddUIVertexQuad(tempVerts);
153+
}
154+
}
155+
}
156+
157+
m_DisableFontTextureRebuiltCallback = false;
84158

85159
var vertices = verticesPool.Get();
86-
vertexHelper.GetUIVertexStream(vertices);
160+
toFill.GetUIVertexStream(vertices);
87161

88-
Modify(ref vertices);
162+
GenerateVisibleCharIndexMap(vertices.Count < text.Length * CharVerts);
89163

90-
vertexHelper.Clear();
91-
vertexHelper.AddUIVertexTriangleStream(vertices);
164+
spans.Clear();
165+
AddListeners();
166+
GenerateHrefBoundingBoxes(ref vertices);
167+
168+
toFill.Clear();
169+
toFill.AddUIVertexTriangleStream(vertices);
92170
verticesPool.Release(vertices);
93171
}
94172

95-
void Modify(ref List<UIVertex> vertices)
173+
void GenerateHrefBoundingBoxes(ref List<UIVertex> vertices)
96174
{
97175
var verticesCount = vertices.Count;
98176

99177
for (var i = 0; i < spans.Count; i++)
100178
{
101179
var span = spans[i];
102-
var endIndex = span.StartIndex + span.Length;
103180

104-
for (var textIndex = span.StartIndex; textIndex < endIndex; textIndex++)
181+
var startIndex = visibleCharIndexMap[span.StartIndex];
182+
var endIndex = visibleCharIndexMap[span.StartIndex + span.Length - 1];
183+
184+
startIndex = Mathf.Clamp(startIndex, 0, text.Length - 1);
185+
endIndex = Mathf.Clamp(endIndex, 0, text.Length - 1);
186+
187+
for (var textIndex = startIndex; textIndex <= endIndex; textIndex++)
105188
{
106189
var vertexStartIndex = textIndex * CharVerts;
107190
if (vertexStartIndex + CharVerts > verticesCount)
@@ -146,7 +229,6 @@ void Modify(ref List<UIVertex> vertices)
146229

147230
// 文字ごとのバウンディングボックスを行ごとのバウンディングボックスにまとめる
148231
span.BoundingBoxes = CalculateLineBoundingBoxes(span.BoundingBoxes);
149-
spans[i] = span;
150232
}
151233
}
152234

@@ -205,6 +287,52 @@ static Rect CalculateAABB(IReadOnlyList<Rect> rects)
205287
return new Rect {min = min, max = max};
206288
}
207289

290+
void GenerateVisibleCharIndexMap(bool verticesReduced)
291+
{
292+
if (visibleCharIndexMap == null || visibleCharIndexMap.Length < text.Length)
293+
{
294+
Array.Resize(ref visibleCharIndexMap, text.Length);
295+
}
296+
297+
if (!verticesReduced)
298+
{
299+
for (var i = 0; i < visibleCharIndexMap.Length; i++)
300+
{
301+
visibleCharIndexMap[i] = i;
302+
}
303+
return;
304+
}
305+
306+
var offset = 0;
307+
var inTag = false;
308+
309+
for (var i = 0; i < text.Length; i++)
310+
{
311+
var character = text[i];
312+
313+
if (inTag)
314+
{
315+
offset++;
316+
317+
if (character == GreaterThan)
318+
{
319+
inTag = false;
320+
}
321+
}
322+
else if (supportRichText && character == LesserThan)
323+
{
324+
offset++;
325+
inTag = true;
326+
}
327+
else if (invisibleChars.Contains(character))
328+
{
329+
offset++;
330+
}
331+
332+
visibleCharIndexMap[i] = i - offset;
333+
}
334+
}
335+
208336
Vector3 CalculateLocalPosition(Vector3 position, Camera pressEventCamera)
209337
{
210338
if (!RootCanvas)

ProjectSettings/ProjectVersion.txt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1,2 @@
1-
m_EditorVersion: 2018.3.6f1
1+
m_EditorVersion: 2019.2.10f1
2+
m_EditorVersionWithRevision: 2019.2.10f1 (923acd2d43aa)

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ protected void OnClick(int startIndex, int length, Color color, Action<string> o
2828
```
2929

3030
## 開発環境
31-
Unity 2018.3.6f1
31+
Unity 2019.2.10f1
3232

3333
## Author
3434
[setchi](https://github.com/setchi)

0 commit comments

Comments
 (0)