10using System.Collections.Generic;
21 [LeapGraphicTag(
"Text")]
25 public const string DEFAULT_SHADER =
"LeapMotion/GraphicRenderer/Text/Dynamic";
29 private Font _font =
default(Font);
32 private float _dynamicPixelsPerUnit = 1.0f;
40 [Header(
"Rendering Settings")]
42 private Shader _shader =
default(Shader);
45 private float _scale = 1f;
47 #pragma warning disable 0649
52 private Material _material;
53 #pragma warning restore 0649
57 private List<Matrix4x4> _curved_worldToAnchor =
new List<Matrix4x4>();
58 private List<Vector4> _curved_graphicParameters =
new List<Vector4>();
78 _font.RequestCharactersInTexture(textGraphic.text);
83 Font.textureRebuilt += onFontTextureRebuild;
87 Font.textureRebuilt -= onFontTextureRebuild;
92 ensureFontIsUpToDate();
97 if (graphic.isRepresentationDirtyOrEditTime || graphic.HasRectChanged()) {
98 generateTextMesh(i, graphic, _meshData[i]);
106 if (graphic.isActiveAndEnabled) {
107 Graphics.DrawMesh(_meshData[i], graphic.transform.localToWorldMatrix, _material, 0);
114 using (
new ProfilerSample(
"Build Material Data And Draw Meshes")) {
115 _curved_worldToAnchor.Clear();
116 _curved_graphicParameters.Clear();
117 for (
int i = 0; i < _meshData.
Count; i++) {
119 if (!graphic.isActiveAndEnabled) {
120 _curved_graphicParameters.Add(Vector4.zero);
121 _curved_worldToAnchor.Add(Matrix4x4.identity);
125 var transformer = graphic.anchor.transformer;
127 Vector3 localPos =
renderer.transform.InverseTransformPoint(graphic.transform.position);
129 Matrix4x4 mainTransform =
renderer.transform.localToWorldMatrix * transformer.GetTransformationMatrix(localPos);
130 Matrix4x4 deform =
renderer.transform.worldToLocalMatrix * Matrix4x4.TRS(
renderer.transform.position - graphic.transform.position, Quaternion.identity, Vector3.one) * graphic.transform.localToWorldMatrix;
131 Matrix4x4 total = mainTransform * deform;
133 _curved_graphicParameters.Add((transformer as
IRadialTransformer).GetVectorRepresentation(graphic.transform));
134 _curved_worldToAnchor.Add(mainTransform.inverse);
136 Graphics.DrawMesh(_meshData[i], total, _material, 0);
141 _material.SetFloat(SpaceProperties.RADIAL_SPACE_RADIUS, curvedSpace.radius);
142 _material.SetMatrixArraySafe(
"_GraphicRendererCurved_WorldToAnchor", _curved_worldToAnchor);
143 _material.SetMatrix(
"_GraphicRenderer_LocalToWorld",
renderer.transform.localToWorldMatrix);
144 _material.SetVectorArraySafe(
"_GraphicRendererCurved_GraphicParameters", _curved_graphicParameters);
151 public override void OnEnableRendererEditor() {
152 base.OnEnableRendererEditor();
154 _font = Resources.GetBuiltinResource<Font>(
DEFAULT_FONT);
158 public override void OnUpdateRendererEditor() {
159 base.OnUpdateRendererEditor();
162 _font = Resources.GetBuiltinResource<Font>(
DEFAULT_FONT);
165 if (_shader ==
null) {
183 PreventDuplication(ref _material);
187 private void onFontTextureRebuild(Font font) {
193 graphic.isRepresentationDirty =
true;
197 private void generateMaterial() {
198 if (_material ==
null) {
199 _material =
new Material(_font.material);
203 Undo.RecordObject(_material,
"Touched material");
206 _material.mainTexture = _font.material.mainTexture;
207 _material.name =
"Font material";
208 _material.shader = _shader;
210 foreach (var keyword
in _material.shaderKeywords) {
211 _material.DisableKeyword(keyword);
216 _material.EnableKeyword(SpaceProperties.CYLINDRICAL_FEATURE);
218 _material.EnableKeyword(SpaceProperties.SPHERICAL_FEATURE);
223 _material.EnableKeyword(LeapGraphicRenderer.FEATURE_PREFIX +
"VERTEX_COLORS");
227 private void ensureFontIsUpToDate() {
229 bool doesNeedRebuild =
false;
233 int scaledFontSize = Mathf.RoundToInt(graphic.fontSize * _dynamicPixelsPerUnit);
235 if (graphic.isRepresentationDirtyOrEditTime) {
236 for (
int j = 0; j < graphic.text.Length; j++) {
237 char character = graphic.text[j];
239 if (!_font.GetCharacterInfo(character, out info, scaledFontSize, graphic.fontStyle)) {
240 doesNeedRebuild =
true;
245 if (doesNeedRebuild) {
251 if (!doesNeedRebuild) {
257 int scaledFontSize = Mathf.RoundToInt(graphic.fontSize * _dynamicPixelsPerUnit);
259 graphic.isRepresentationDirty =
true;
260 _font.RequestCharactersInTexture(graphic.text,
266 private List<TextWrapper.Line> _tempLines =
new List<TextWrapper.Line>();
267 private List<Vector3> _verts =
new List<Vector3>();
268 private List<Vector4> _uvs =
new List<Vector4>();
269 private List<Color> _colors =
new List<Color>();
270 private List<int> _tris =
new List<int>();
271 private void generateTextMesh(
int index, LeapTextGraphic graphic, Mesh mesh) {
272 using (
new ProfilerSample(
"Generate Text Mesh")) {
273 mesh.Clear(keepVertexLayout:
false);
275 graphic.isRepresentationDirty =
false;
277 int scaledFontSize = Mathf.RoundToInt(graphic.fontSize * _dynamicPixelsPerUnit);
281 HashSet<char> unfoundCharacters =
null;
283 foreach (var character
in graphic.text) {
284 if (character ==
'\n') {
288 if (unfoundCharacters !=
null && unfoundCharacters.Contains(character)) {
292 if (!_font.GetCharacterInfo(character, out info, scaledFontSize, graphic.fontStyle)) {
293 if (unfoundCharacters ==
null) unfoundCharacters =
new HashSet<char>();
294 unfoundCharacters.Add(character);
295 Debug.LogError(
"Could not find character [" + character +
"] in font " + _font +
"!");
300 var text = graphic.text;
302 float _charScale = this._scale *
SCALE_CONSTANT / _dynamicPixelsPerUnit;
303 float _scale = _charScale * graphic.fontSize / _font.fontSize;
304 float lineHeight = _scale * graphic.lineSpacing * _font.lineHeight * _dynamicPixelsPerUnit;
306 RectTransform rectTransform = graphic.transform as RectTransform;
308 if (rectTransform !=
null) {
309 maxWidth = rectTransform.rect.width;
311 maxWidth =
float.MaxValue;
314 _widthCalculator.font = _font;
315 _widthCalculator.charScale = _charScale;
316 _widthCalculator.fontStyle = graphic.fontStyle;
317 _widthCalculator.scaledFontSize = scaledFontSize;
318 TextWrapper.Wrap(text, graphic.tokens, _tempLines, _widthCalculator.func, maxWidth);
320 float textHeight = _tempLines.Count * lineHeight;
323 origin.y -= _font.ascent * _scale * _dynamicPixelsPerUnit;
325 if (rectTransform !=
null) {
326 origin.y -= rectTransform.rect.y;
328 switch (graphic.verticalAlignment) {
329 case LeapTextGraphic.VerticalAlignment.Center:
330 origin.y -= (rectTransform.rect.height - textHeight) / 2;
332 case LeapTextGraphic.VerticalAlignment.Bottom:
333 origin.y -= (rectTransform.rect.height - textHeight);
338 foreach (var line
in _tempLines) {
340 if (rectTransform !=
null) {
341 origin.x = rectTransform.rect.x;
342 switch (graphic.horizontalAlignment) {
343 case LeapTextGraphic.HorizontalAlignment.Center:
344 origin.x += (rectTransform.rect.width - line.width) / 2;
346 case LeapTextGraphic.HorizontalAlignment.Right:
347 origin.x += (rectTransform.rect.width - line.width);
351 switch (graphic.horizontalAlignment) {
352 case LeapTextGraphic.HorizontalAlignment.Left:
355 case LeapTextGraphic.HorizontalAlignment.Center:
356 origin.x = -line.width / 2;
358 case LeapTextGraphic.HorizontalAlignment.Right:
359 origin.x = -line.width;
364 for (
int i = line.start; i < line.end; i++) {
368 if (!_font.GetCharacterInfo(c, out info, scaledFontSize, graphic.fontStyle)) {
372 int offset = _verts.Count;
373 _tris.Add(offset + 0);
374 _tris.Add(offset + 1);
375 _tris.Add(offset + 2);
377 _tris.Add(offset + 0);
378 _tris.Add(offset + 2);
379 _tris.Add(offset + 3);
381 _verts.Add(_charScale *
new Vector3(info.minX, info.maxY, 0) + origin);
382 _verts.Add(_charScale *
new Vector3(info.maxX, info.maxY, 0) + origin);
383 _verts.Add(_charScale *
new Vector3(info.maxX, info.minY, 0) + origin);
384 _verts.Add(_charScale *
new Vector3(info.minX, info.minY, 0) + origin);
386 _uvs.Add(info.uvTopLeft);
387 _uvs.Add(info.uvTopRight);
388 _uvs.Add(info.uvBottomRight);
389 _uvs.Add(info.uvBottomLeft);
395 origin.x += info.advance * _charScale;
397 origin.y -= lineHeight;
400 for (
int i = 0; i < _uvs.Count; i++) {
406 mesh.SetVertices(_verts);
407 mesh.SetTriangles(_tris, 0);
408 mesh.SetUVs(0, _uvs);
411 mesh.SetColors(_colors);
422 private CharWidthCalculator _widthCalculator =
new CharWidthCalculator();
423 private class CharWidthCalculator {
425 public int scaledFontSize;
426 public FontStyle fontStyle;
427 public float charScale;
429 public Func<char, float> func;
431 public CharWidthCalculator() {
435 private float funcMethod(
char c) {
437 font.GetCharacterInfo(c, out info, scaledFontSize, fontStyle);
438 return info.advance * charScale;
List< LeapGraphic > graphics
Returns the list of graphics attached to this group. This getter returns a regular mutable list for s...
const string PROPERTY_PREFIX
LeapSpace space
Returns the leap space that is currently attached to this graphic renderer.
LeapGraphicGroup group
Gets the group this rendering method is attached to.
LeapGraphicRenderer renderer
Gets the renderer this rendering method is attached to.
void OnAddRemoveGraphics(List< int > dirtyIndexes)
Must be implemented by a renderer to report that it is able to support adding and removing graphics a...
const float SCALE_CONSTANT
override SupportInfo GetSpaceSupportInfo(LeapSpace space)
override void OnEnableRenderer()
Called when the renderer is enabled at runtime.
const string DEFAULT_SHADER
const string DEFAULT_FONT
override void OnUpdateRenderer()
Called from LateUpdate during runtime. Use this to update the renderer using any changes made to duri...
override void OnDisableRenderer()
Called when the renderer is disabled at runtime.
void RemoveMesh(int index)
void Validate(LeapRenderingMethod renderingMethod)
The support info class provides a very basic way to notify that something is fully supported,...
static SupportInfo FullSupport()
Helper getter to return a struct that signifies full support.
A utility struct for ease of use when you want to wrap a piece of code in a Profiler....