fzhangtj
6 年前
当前提交
bdd92944
共有 20 个文件被更改,包括 1037 次插入 和 442 次删除
-
7Runtime/editor/editor_window.cs
-
6Runtime/painting/text_painter.cs
-
2Runtime/painting/text_style.cs
-
12Runtime/rendering/editable.cs
-
5Runtime/rendering/paragraph.cs
-
15Runtime/ui/painting/canvas_impl.cs
-
100Runtime/ui/painting/txt/mesh_generator.cs
-
54Runtime/ui/painting/txt/text_blob.cs
-
4Runtime/ui/text.cs
-
288Runtime/ui/txt/linebreaker.cs
-
570Runtime/ui/txt/paragraph.cs
-
2Runtime/widgets/basic.cs
-
24Tests/Editor/Paragraph.cs
-
92Runtime/ui/txt/layout.cs
-
11Runtime/ui/txt/layout.cs.meta
-
19Runtime/ui/txt/layout_utils.cs
-
11Runtime/ui/txt/layout_utils.cs.meta
-
147Runtime/ui/txt/wordbreaker.cs
-
11Runtime/ui/txt/wordbreaker.cs.meta
-
99Tests/Editor/IMGUIText.cs
|
|||
using Unity.UIWidgets.foundation; |
|||
using System.Collections.Generic; |
|||
using Unity.UIWidgets.foundation; |
|||
|
|||
|
|||
public TextBlob(string text, int start, int end, Vector2d[] positions, TextStyle style, Rect bounds) { |
|||
D.assert(start < end); |
|||
public TextBlob(string text, int textOffset, int textSize, Vector2d[] positions, Rect bounds, TextStyle style) { |
|||
this.instanceId = ++_nextInstanceId; |
|||
this.positions = positions; |
|||
this.start = start; |
|||
this.end = end; |
|||
this.positions = positions; |
|||
this.textOffset = textOffset; |
|||
this.textSize = textSize; |
|||
get { return this.bounds.shift(new Offset(this.positions[this.start].x, this.positions[this.start].y)); } |
|||
get { return this.bounds.shift(new Offset(this.positions[0].x, this.positions[0].y)); } |
|||
static long _nextInstanceId = 0; |
|||
public readonly long instanceId; |
|||
public readonly int start; |
|||
public readonly int end; |
|||
public readonly int textOffset; |
|||
public readonly int textSize; |
|||
} |
|||
|
|||
public class TextBlobBuilder { |
|||
TextStyle _style; |
|||
public Vector2d[] positions; |
|||
string _text; |
|||
int _textOffset; |
|||
int _size; |
|||
Rect _bounds; |
|||
|
|||
public void allocRunPos(TextStyle style, string text, int offset, int size) { |
|||
|
|||
this._style = style; |
|||
this._text = text; |
|||
this._textOffset = offset; |
|||
this._size = size; |
|||
if (this.positions == null || this.positions.Length < size) { |
|||
this.positions = new Vector2d[size]; |
|||
} |
|||
} |
|||
|
|||
public void setBounds(Rect bounds) { |
|||
this._bounds = bounds; |
|||
} |
|||
|
|||
public TextBlob make() { |
|||
var result = new TextBlob(this._text, this._textOffset, |
|||
this._size, this.positions, this._bounds, this._style); |
|||
this.positions = null; |
|||
return result; |
|||
} |
|||
} |
|||
} |
|
|||
using System; |
|||
using System.Collections.Generic; |
|||
using System.Linq; |
|||
using UnityEngine.SocialPlatforms.Impl; |
|||
public class LineBreaker { |
|||
public class LineInfo { |
|||
public int start; |
|||
public double width; |
|||
} |
|||
StyledRuns _runs; |
|||
public class TabStops { |
|||
public Vector2d[] _characterPositions; |
|||
public double[] _characterWidth; |
|||
string _text; |
|||
double _width; |
|||
int _lineStart; |
|||
int _wordStart; |
|||
int _spaceCount = 0; |
|||
int tabCount = 4; |
|||
double _lineLength; |
|||
int _tabWidth; |
|||
List<int> _stops = new List<int>(); |
|||
|
|||
public void set(List<int> stops, int tabWidth) { |
|||
this._stops.Clear(); |
|||
if (stops != null) { |
|||
this._stops.AddRange(stops); |
|||
} |
|||
List<LineInfo> _lines; |
|||
this._tabWidth = tabWidth; |
|||
} |
|||
public float nextTab(float widthSoFar) { |
|||
for (int i = 0; i < this._stops.Count; i++) { |
|||
if (this._stops[i] > widthSoFar) { |
|||
return this._stops[i]; |
|||
} |
|||
} |
|||
return (float)(Math.Floor(widthSoFar / this._tabWidth + 1) * this._tabWidth); |
|||
} |
|||
} |
|||
public void setup(string text, StyledRuns runs, double width, Vector2d[] characterPositions, |
|||
double[] characterWidth) { |
|||
this._text = text; |
|||
this._runs = runs; |
|||
this._characterPositions = characterPositions; |
|||
this._characterWidth = characterWidth; |
|||
this._width = width; |
|||
public class Candidate { |
|||
public int offset; |
|||
public int pre; |
|||
public double preBreak; |
|||
public float penalty; |
|||
|
|||
public double postBreak; |
|||
public int preSpaceCount; |
|||
public int postSpaceCount; |
|||
} |
|||
|
|||
public class LineBreaker { |
|||
|
|||
const float ScoreInfty = float.MaxValue; |
|||
const float ScoreDesperate = 1e10f; |
|||
|
|||
string _textBuf; |
|||
int _textOffset; |
|||
int _textLength; |
|||
List<float> _charWidths = new List<float>(); |
|||
List<int> _breaks = new List<int>(); |
|||
List<float> _widths = new List<float>(); |
|||
WordBreaker _wordBreaker = new WordBreaker(); |
|||
double _width = 0.0; |
|||
double _preBreak; |
|||
double _lineWidth; |
|||
int _lastBreak; |
|||
int _bestBreak; |
|||
float _bestScore; |
|||
int _spaceCount; |
|||
TabStops _tabStops = new TabStops(); |
|||
int mFirstTabIndex; |
|||
List<Candidate> _candidates = new List<Candidate>(); |
|||
|
|||
public int computeBreaks() { |
|||
int nCand = this._candidates.Count; |
|||
if (nCand > 0 && (nCand == 1 || this._lastBreak != nCand - 1)) { |
|||
var cand = this._candidates[this._candidates.Count - 1]; |
|||
this._pushBreak(cand.offset, (float)(cand.postBreak - this._preBreak)); |
|||
} |
|||
return this._breaks.Count; |
|||
public List<LineInfo> getLines() { |
|||
return this._lines; |
|||
public List<int> getBreaks() { |
|||
return this._breaks; |
|||
public void doBreak(int blockStart, int blockEnd) { |
|||
this._lines = new List<LineInfo>(); |
|||
this._lineStart = blockStart; |
|||
this._wordStart = blockStart; |
|||
public void resize(int size) { |
|||
if (this._charWidths.Count < size) { |
|||
this._charWidths.AddRange(Enumerable.Repeat(0.0f, size - this._charWidths.Count)); |
|||
} |
|||
} |
|||
public void setText(string text, int textOffset, int textLength) { |
|||
this._textBuf = text; |
|||
this._textOffset = textOffset; |
|||
this._textLength = textLength; |
|||
this._wordBreaker.setText(this._textBuf, textOffset, textLength); |
|||
this._wordBreaker.next(); |
|||
this._candidates.Clear(); |
|||
Candidate can = new Candidate { |
|||
offset = 0, postBreak = 0, preBreak = 0, postSpaceCount = 0, preSpaceCount = 0, pre = 0 |
|||
}; |
|||
this._candidates.Add(can); |
|||
this._lastBreak = 0; |
|||
this._bestBreak = 0; |
|||
this._bestScore = ScoreInfty; |
|||
this._preBreak = 0; |
|||
this.mFirstTabIndex = int.MaxValue; |
|||
} |
|||
double offsetX = 0.0; |
|||
var runIterator = this._runs.iterator(); |
|||
for (var charIndex = blockStart; charIndex < blockEnd; charIndex++) { |
|||
runIterator.nextTo(charIndex); |
|||
var run = runIterator.run; |
|||
var font = FontManager.instance.getOrCreate(run.style.fontFamily).font; |
|||
public void setLineWidth(float lineWidth) { |
|||
this._lineWidth = lineWidth; |
|||
} |
|||
var style = run.style; |
|||
var charInfo = new CharacterInfo(); |
|||
public float addStyleRun(TextStyle style, int start, int end) { |
|||
float width = 0.0f; |
|||
if (style != null) { |
|||
width = Layout.measureText(this._textBuf, start + this._textOffset, end - start, style, |
|||
this._charWidths, start); |
|||
} |
|||
if (this._text[charIndex] == '\t') { |
|||
this._spaceCount++; |
|||
int current = this._wordBreaker.current(); |
|||
int afterWord = start; |
|||
int lastBreak = start; |
|||
font.GetCharacterInfo(' ', out charInfo, |
|||
style.UnityFontSize, style.UnityFontStyle); |
|||
double tabSize = charInfo.advance * this.tabCount; |
|||
var newX = Math.Floor(((offsetX / tabSize) + 1) * tabSize); |
|||
if (newX > this._width && this._lineStart != charIndex) { |
|||
this._characterWidth[charIndex] = tabSize; |
|||
this.makeLine(charIndex, charIndex); |
|||
} else { |
|||
this._characterWidth[charIndex] = newX - offsetX; |
|||
this._characterPositions[charIndex].x = offsetX; |
|||
double lastBreakWidth = this._width; |
|||
double postBreak = this._width; |
|||
int postSpaceCount = this._spaceCount; |
|||
|
|||
for (int i = start; i < end; i++) { |
|||
char c = this._textBuf[i + this._textOffset]; |
|||
if (c == '\t') { |
|||
this._width = this._preBreak + this._tabStops.nextTab((float)(this._width - this._preBreak)); |
|||
if (this.mFirstTabIndex == Int32.MaxValue) { |
|||
this.mFirstTabIndex = i; |
|||
offsetX = this._characterPositions[charIndex].x + this._characterWidth[charIndex]; |
|||
} else if (this._text[charIndex] == ' ') { |
|||
font.GetCharacterInfo(this._text[charIndex], out charInfo, style.UnityFontSize, |
|||
run.style.UnityFontStyle); |
|||
this._spaceCount++; |
|||
this._characterPositions[charIndex].x = offsetX; |
|||
this._characterWidth[charIndex] = charInfo.advance; |
|||
offsetX = this._characterPositions[charIndex].x + this._characterWidth[charIndex]; |
|||
// todo no wrap in space ?
|
|||
} else { |
|||
font.GetCharacterInfo(this._text[charIndex], out charInfo, style.UnityFontSize, |
|||
run.style.UnityFontStyle); |
|||
if (this._spaceCount > 0 || blockStart == charIndex) { |
|||
this._wordStart = charIndex; |
|||
} |
|||
else { |
|||
if (LayoutUtils.isWordSpace(c)) { |
|||
this._spaceCount += 1; |
|||
this._characterPositions[charIndex].x = offsetX; |
|||
this._characterWidth[charIndex] = charInfo.advance; |
|||
this._width += this._charWidths[i]; |
|||
if (!LayoutUtils.isLineEndSpace(c)) { |
|||
postBreak = this._width; |
|||
postSpaceCount = this._spaceCount; |
|||
afterWord = i + 1; |
|||
} |
|||
} |
|||
if (offsetX + charInfo.advance > this._width && this._lineStart != charIndex) { |
|||
if (this._lineStart == this._wordStart) { |
|||
this.makeLine(charIndex, charIndex); |
|||
this._wordStart = charIndex; |
|||
} else { |
|||
this.makeLine(this._wordStart, charIndex); |
|||
} |
|||
if (i + 1 == current) { |
|||
int wordStart = this._wordBreaker.wordStart(); |
|||
int wordEnd = this._wordBreaker.wordEnd(); |
|||
if (style != null || current == end || this._charWidths[current] > 0) { |
|||
this._addWordBreak(current, this._width, postBreak, this._spaceCount, postSpaceCount, 0); |
|||
offsetX = this._characterPositions[charIndex].x + this._characterWidth[charIndex]; |
|||
this._spaceCount = 0; |
|||
lastBreak = current; |
|||
lastBreakWidth = this._width; |
|||
current = this._wordBreaker.next(); |
|||
return width; |
|||
} |
|||
this.makeLine(blockEnd, blockEnd); |
|||
public void finish() { |
|||
this._wordBreaker.finish(); |
|||
this._width = 0; |
|||
this._candidates.Clear(); |
|||
this._widths.Clear(); |
|||
this._breaks.Clear(); |
|||
this._textBuf = null; |
|||
public List<float> getWidths() { |
|||
return this._widths; |
|||
} |
|||
void makeLine(int end, int last) { |
|||
Debug.Assert(this._lineStart < end); |
|||
Debug.Assert(end <= last); |
|||
this._lines.Add(new LineInfo() { |
|||
start = this._lineStart, |
|||
width = this._characterPositions[end - 1].x + this._characterWidth[end - 1], |
|||
}); |
|||
this._lineStart = end; |
|||
public void setTabStops(List<int> stops, int tabWidth) { |
|||
this._tabStops.set(stops, tabWidth); |
|||
} |
|||
if (end >= this._characterPositions.Length) { |
|||
return; |
|||
void _addWordBreak(int offset, double preBreak, double postBreak, int preSpaceCount, int postSpaceCount, float penalty) { |
|||
Candidate cand = new Candidate(); |
|||
double width = this._candidates[this._candidates.Count - 1].preBreak; |
|||
if (postBreak - width > this._lineWidth) { |
|||
int i = this._candidates[this._candidates.Count - 1].offset; |
|||
width += this._charWidths[i++]; |
|||
for (; i < offset; i++) { |
|||
float w = this._charWidths[i]; |
|||
if (w > 0) { |
|||
cand.offset = i; |
|||
cand.preBreak = width; |
|||
cand.postBreak = width; |
|||
cand.preSpaceCount = postSpaceCount; |
|||
cand.preSpaceCount = postSpaceCount; |
|||
cand.penalty = ScoreDesperate; |
|||
this._addCandidate(cand); |
|||
width += w; |
|||
|
|||
} |
|||
} |
|||
var offset = new Vector2d(-this._characterPositions[end].x, 0); |
|||
this._characterPositions[end].x = 0; |
|||
if (end < last) { |
|||
Paragraph.offsetCharacters(offset, this._characterPositions, end + 1, last + 1); |
|||
|
|||
cand.offset = offset; |
|||
cand.preBreak = preBreak; |
|||
cand.postBreak = postBreak; |
|||
cand.penalty = penalty; |
|||
cand.preSpaceCount = preSpaceCount; |
|||
cand.preSpaceCount = postSpaceCount; |
|||
this._addCandidate(cand); |
|||
} |
|||
|
|||
|
|||
|
|||
void _addCandidate(Candidate cand) { |
|||
int candIndex = this._candidates.Count; |
|||
this._candidates.Add(cand); |
|||
if (cand.postBreak - this._preBreak > this._lineWidth) { |
|||
this._pushGreedyBreak(); |
|||
} |
|||
|
|||
if (cand.penalty <= this._bestScore) { |
|||
this._bestBreak = candIndex; |
|||
this._bestScore = cand.penalty; |
|||
|
|||
void _pushGreedyBreak() { |
|||
var bestCandidate = this._candidates[this._bestBreak]; |
|||
this._pushBreak(bestCandidate.offset, (float)(bestCandidate.postBreak - this._preBreak)); |
|||
this._bestScore = ScoreInfty; |
|||
this._lastBreak = this._bestBreak; |
|||
this._preBreak = bestCandidate.preBreak; |
|||
} |
|||
|
|||
void _pushBreak(int offset, float width) { |
|||
this._breaks.Add(offset); |
|||
this._widths.Add(width); |
|||
} |
|||
|
|||
} |
|||
} |
|
|||
using System.Collections.Generic; |
|||
using UnityEngine; |
|||
|
|||
namespace Unity.UIWidgets.ui { |
|||
|
|||
public class Layout { |
|||
int _start; |
|||
int _count; |
|||
List<float> _advances = new List<float>(); |
|||
List<float> _positions = new List<float>(); |
|||
float _advance; |
|||
Rect _bounds; |
|||
string _text; |
|||
|
|||
public static float measureText(string buf, int start, int count, TextStyle style, |
|||
List<float> advances, int advanceOffset) { |
|||
Layout layout = new Layout(); |
|||
layout.doLayout(buf, start, count, style); |
|||
if (advances != null) { |
|||
var layoutAdv = layout.getAdvances(); |
|||
for (int i = 0; i < count; i++) { |
|||
advances[i + advanceOffset] = layoutAdv[i]; |
|||
} |
|||
} |
|||
|
|||
return layout.getAdvance(); |
|||
} |
|||
|
|||
public void doLayout(string text, int start, int count, TextStyle style) { |
|||
this._text = text; |
|||
this._advances.Clear(); |
|||
this._positions.Clear(); |
|||
this._count = count; |
|||
var font = FontManager.instance.getOrCreate(style.fontFamily).font; |
|||
font.RequestCharactersInTexture(this._text.Substring(start, count), |
|||
style.UnityFontSize, |
|||
style.UnityFontStyle); |
|||
|
|||
this._advance = 0; |
|||
this._bounds = null; |
|||
for (int i = 0; i < count; i++) { |
|||
int charIndex = start + i; |
|||
var ch = text[charIndex]; |
|||
CharacterInfo characterInfo; |
|||
font.GetCharacterInfo(ch, out characterInfo, style.UnityFontSize, style.UnityFontStyle); |
|||
|
|||
var rect = Rect.fromLTRB(characterInfo.minX, -characterInfo.maxY, characterInfo.maxX, |
|||
-characterInfo.minY); |
|||
rect = rect.translate(this._advance, 0); |
|||
if (this._bounds == null) { |
|||
this._bounds = rect; |
|||
} |
|||
else { |
|||
this._bounds = this._bounds.expandToInclude(rect); |
|||
} |
|||
|
|||
this._positions.Add(this._advance); |
|||
this._advances.Add(characterInfo.advance); |
|||
this._advance += characterInfo.advance; |
|||
|
|||
} |
|||
} |
|||
|
|||
public int nGlyphs() { |
|||
return this._count; |
|||
} |
|||
|
|||
public List<float> getAdvances() { |
|||
return this._advances; |
|||
} |
|||
|
|||
public float getAdvance() { |
|||
return this._advance; |
|||
} |
|||
|
|||
public float getX(int index) { |
|||
return this._positions[index]; |
|||
} |
|||
|
|||
public float getY(int index) { |
|||
return 0; |
|||
} |
|||
|
|||
public float getCharAdvance(int index) { |
|||
return this._advances[index]; |
|||
} |
|||
|
|||
public Rect getBounds() { |
|||
return this._bounds; |
|||
} |
|||
} |
|||
} |
|
|||
fileFormatVersion: 2 |
|||
guid: 291468e4e150b495fa305f2d62b134e3 |
|||
MonoImporter: |
|||
externalObjects: {} |
|||
serializedVersion: 2 |
|||
defaultReferences: [] |
|||
executionOrder: 0 |
|||
icon: {instanceID: 0} |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
|
|||
namespace Unity.UIWidgets.ui { |
|||
|
|||
public static class LayoutUtils { |
|||
|
|||
|
|||
public const char CHAR_NBSP = '\u00A0'; |
|||
|
|||
public static bool isWordSpace(char ch) { |
|||
return ch == ' ' || ch == CHAR_NBSP; |
|||
} |
|||
|
|||
public static bool isLineEndSpace(char c) { |
|||
return c == '\n' || c == ' ' || c == 0x1680 || (0x2000 <= c && c <= 0x200A && c != 0x2007) || |
|||
c == 0x205F || c == 0x3000; |
|||
} |
|||
|
|||
|
|||
} |
|||
} |
|
|||
fileFormatVersion: 2 |
|||
guid: 1b1768a705ffe4cb7ab2638ac53c657e |
|||
MonoImporter: |
|||
externalObjects: {} |
|||
serializedVersion: 2 |
|||
defaultReferences: [] |
|||
executionOrder: 0 |
|||
icon: {instanceID: 0} |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
|
|||
using System; |
|||
|
|||
namespace Unity.UIWidgets.ui { |
|||
|
|||
public class WordBreaker { |
|||
|
|||
public const uint U16_SURROGATE_OFFSET = ((0xd800<<10)+0xdc00-0x10000); |
|||
string _text; |
|||
int _offset; |
|||
int _size; |
|||
int _current; |
|||
int _last; |
|||
int _scanOffset; |
|||
bool _inEmailOrUrl; |
|||
|
|||
|
|||
public int next() { |
|||
this._last = this._current; |
|||
this._detectEmailOrUrl(); |
|||
if (this._inEmailOrUrl) { |
|||
this._current = this._findNextBreakInEmailOrUrl(); |
|||
} |
|||
else { |
|||
this._current = this._findNextBreakNormal(); |
|||
} |
|||
return this._current; |
|||
} |
|||
|
|||
public void setText(string data, int offset, int size) { |
|||
this._text = data; |
|||
this._offset = offset; |
|||
this._size = size; |
|||
this._last = 0; |
|||
this._current = 0; |
|||
this._scanOffset = 0; |
|||
this._inEmailOrUrl = false; |
|||
} |
|||
|
|||
public int current() { |
|||
return this._current; |
|||
} |
|||
|
|||
public int wordStart() { |
|||
if (this._inEmailOrUrl) { |
|||
return this._last; |
|||
} |
|||
|
|||
var result = this._last; |
|||
while (result < this._current) { |
|||
int ix = result; |
|||
uint c = nextCode(this._text, ref ix, this._current); |
|||
if (!LayoutUtils.isLineEndSpace((char) c)) { // todo
|
|||
break; |
|||
} |
|||
|
|||
result = ix; |
|||
} |
|||
return result; |
|||
} |
|||
|
|||
public int wordEnd() { |
|||
if (this._inEmailOrUrl) { |
|||
return this._last; |
|||
} |
|||
|
|||
int result = this._current; |
|||
while (result > this._last) { |
|||
int ix = result; |
|||
uint ch = preCode(_text, ref ix, this._last); |
|||
if (!LayoutUtils.isLineEndSpace((char) ch)) { // todo
|
|||
break; |
|||
} |
|||
|
|||
result = ix; |
|||
} |
|||
return result; |
|||
} |
|||
|
|||
public int breakBadness() { |
|||
return (this._inEmailOrUrl && this._current < this._scanOffset) ? 1 : 0; |
|||
} |
|||
|
|||
public void finish() { |
|||
this._text = null; |
|||
} |
|||
|
|||
int _findNextBreakInEmailOrUrl() { |
|||
return 0; |
|||
} |
|||
|
|||
int _findNextBreakNormal() { |
|||
if (this._current == this._size) { |
|||
return -1; |
|||
} |
|||
this._current++; |
|||
for (;this._current < this._size;++this._current) { |
|||
char c = this._text[this._current + this._offset]; |
|||
if (LayoutUtils.isWordSpace(c) || c == '\t') { |
|||
return this._current; |
|||
} |
|||
} |
|||
return this._current; |
|||
} |
|||
|
|||
void _detectEmailOrUrl() { |
|||
|
|||
} |
|||
|
|||
static uint nextCode(string text, ref int index, int end) { |
|||
uint ch = text[index++]; |
|||
if (isLeadSurrogate(ch)) { |
|||
if (index < end && isTrailSurrogate(text[index])) { |
|||
char ch2 = text[index]; |
|||
index++; |
|||
ch = getSupplementary(ch, ch2); |
|||
} |
|||
} |
|||
|
|||
return ch; |
|||
} |
|||
|
|||
static uint preCode(string text, ref int index, int start) { |
|||
uint ch = text[--index]; |
|||
if (isTrailSurrogate(ch)) { |
|||
if (index > start && isLeadSurrogate(text[index - 1])) { |
|||
ch = getSupplementary(text[index - 1], ch); |
|||
--index; |
|||
} |
|||
} |
|||
|
|||
return ch; |
|||
} |
|||
|
|||
public static bool isLeadSurrogate(uint c) { |
|||
return ((c) & 0xfffffc00) == 0xd800; |
|||
} |
|||
|
|||
|
|||
public static bool isTrailSurrogate(uint c) { |
|||
return ((c) & 0xfffffc00) == 0xdc00; |
|||
} |
|||
|
|||
public static uint getSupplementary(uint lead, uint trail) { |
|||
return (char)(((uint) (lead) << 10) + (uint) (trail - U16_SURROGATE_OFFSET)); |
|||
} |
|||
} |
|||
} |
|
|||
fileFormatVersion: 2 |
|||
guid: 30b4907a8b76c4df9a243dcd8d3518fb |
|||
MonoImporter: |
|||
externalObjects: {} |
|||
serializedVersion: 2 |
|||
defaultReferences: [] |
|||
executionOrder: 0 |
|||
icon: {instanceID: 0} |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
|
|||
using UnityEditor; |
|||
using UnityEngine; |
|||
|
|||
namespace UIWidgets.Tests { |
|||
public class IMGUIText: EditorWindow { |
|||
Font font; |
|||
string str = "wei"; |
|||
Mesh mesh; |
|||
|
|||
[MenuItem("UIWidgetsTests/IMGUIText")] |
|||
public static void getIMGUIText() { |
|||
EditorWindow.GetWindow(typeof(IMGUIText)); |
|||
} |
|||
|
|||
void OnEnable() { |
|||
font = Font.CreateDynamicFontFromOSFont("Helvetica", 14); |
|||
// Set the rebuild callback so that the mesh is regenerated on font changes.
|
|||
Font.textureRebuilt += OnFontTextureRebuilt; |
|||
|
|||
// Request characters.
|
|||
font.RequestCharactersInTexture(str); |
|||
// Set up mesh.
|
|||
mesh = new Mesh(); |
|||
// Generate font mesh.
|
|||
RebuildMesh(); |
|||
} |
|||
|
|||
void RebuildMesh() |
|||
{ |
|||
// Generate a mesh for the characters we want to print.
|
|||
var vertices = new Vector3[str.Length * 4]; |
|||
var triangles = new int[str.Length * 6]; |
|||
var uv = new Vector2[str.Length * 4]; |
|||
Vector3 pos = new Vector3(20, 60f, 0.0f); |
|||
for (int i = 0; i < str.Length; i++) |
|||
{ |
|||
// Get character rendering information from the font
|
|||
CharacterInfo ch; |
|||
font.GetCharacterInfo(str[i], out ch); |
|||
|
|||
vertices[4 * i + 0] = pos + new Vector3(ch.minX, -ch.maxY, 0); |
|||
vertices[4 * i + 1] = pos + new Vector3(ch.maxX, -ch.maxY, 0); |
|||
vertices[4 * i + 2] = pos + new Vector3(ch.maxX, -ch.minY, 0); |
|||
vertices[4 * i + 3] = pos + new Vector3(ch.minX, -ch.minY, 0); |
|||
|
|||
uv[4 * i + 0] = ch.uvTopLeft; |
|||
uv[4 * i + 1] = ch.uvTopRight; |
|||
uv[4 * i + 2] = ch.uvBottomRight; |
|||
uv[4 * i + 3] = ch.uvBottomLeft; |
|||
|
|||
triangles[6 * i + 0] = 4 * i + 0; |
|||
triangles[6 * i + 1] = 4 * i + 1; |
|||
triangles[6 * i + 2] = 4 * i + 2; |
|||
|
|||
triangles[6 * i + 3] = 4 * i + 0; |
|||
triangles[6 * i + 4] = 4 * i + 2; |
|||
triangles[6 * i + 5] = 4 * i + 3; |
|||
|
|||
// Advance character position
|
|||
pos += new Vector3(ch.advance, 0, 0); |
|||
} |
|||
mesh.vertices = vertices; |
|||
mesh.triangles = triangles; |
|||
mesh.uv = uv; |
|||
} |
|||
|
|||
public void setup() { |
|||
{ |
|||
|
|||
} |
|||
} |
|||
|
|||
void OnDestroy() |
|||
{ |
|||
Font.textureRebuilt -= OnFontTextureRebuilt; |
|||
} |
|||
|
|||
void OnFontTextureRebuilt(Font changedFont) |
|||
{ |
|||
if (changedFont != font) |
|||
return; |
|||
|
|||
RebuildMesh(); |
|||
} |
|||
|
|||
void OnGUI() { |
|||
if (Event.current.type == EventType.Repaint) { |
|||
font.material.SetPass(0); |
|||
var tt = font.material.mainTexture; |
|||
font.material.color = Color.black; |
|||
Graphics.DrawMeshNow(this.mesh, Matrix4x4.identity); |
|||
} |
|||
} |
|||
|
|||
void Update() { |
|||
font.RequestCharactersInTexture(str); |
|||
} |
|||
} |
|||
} |
撰写
预览
正在加载...
取消
保存
Reference in new issue