The fucking 3rd time i had to upload this project to git

This commit is contained in:
Madhav Kapa
2023-10-06 20:18:29 -04:00
commit 5658acfe16
2689 changed files with 1259400 additions and 0 deletions

View File

@ -0,0 +1,121 @@
using System.Collections;
using UnityEngine;
namespace TMPro.Examples
{
public class Benchmark01 : MonoBehaviour
{
private const string label01 = "The <#0050FF>count is: </color>{0}";
private const string label02 = "The <color=#0050FF>count is: </color>";
public int BenchmarkType;
public TMP_FontAsset TMProFont;
public Font TextMeshFont;
//private string m_string;
//private int m_frame;
private Material m_material01;
private Material m_material02;
private TextContainer m_textContainer;
private TextMesh m_textMesh;
private TextMeshPro m_textMeshPro;
private IEnumerator Start()
{
if (BenchmarkType == 0) // TextMesh Pro Component
{
m_textMeshPro = gameObject.AddComponent<TextMeshPro>();
m_textMeshPro.autoSizeTextContainer = true;
//m_textMeshPro.anchorDampening = true;
if (TMProFont != null)
m_textMeshPro.font = TMProFont;
//m_textMeshPro.font = Resources.Load("Fonts & Materials/Anton SDF", typeof(TextMeshProFont)) as TextMeshProFont; // Make sure the Anton SDF exists before calling this...
//m_textMeshPro.fontSharedMaterial = Resources.Load("Fonts & Materials/Anton SDF", typeof(Material)) as Material; // Same as above make sure this material exists.
m_textMeshPro.fontSize = 48;
m_textMeshPro.alignment = TextAlignmentOptions.Center;
//m_textMeshPro.anchor = AnchorPositions.Center;
m_textMeshPro.extraPadding = true;
//m_textMeshPro.outlineWidth = 0.25f;
//m_textMeshPro.fontSharedMaterial.SetFloat("_OutlineWidth", 0.2f);
//m_textMeshPro.fontSharedMaterial.EnableKeyword("UNDERLAY_ON");
//m_textMeshPro.lineJustification = LineJustificationTypes.Center;
m_textMeshPro.enableWordWrapping = false;
//m_textMeshPro.lineLength = 60;
//m_textMeshPro.characterSpacing = 0.2f;
//m_textMeshPro.fontColor = new Color32(255, 255, 255, 255);
m_material01 = m_textMeshPro.font.material;
m_material02 =
Resources.Load<Material>(
"Fonts & Materials/LiberationSans SDF - Drop Shadow"); // Make sure the LiberationSans SDF exists before calling this...
}
else if (BenchmarkType == 1) // TextMesh
{
m_textMesh = gameObject.AddComponent<TextMesh>();
if (TextMeshFont != null)
{
m_textMesh.font = TextMeshFont;
m_textMesh.GetComponent<Renderer>().sharedMaterial = m_textMesh.font.material;
}
else
{
m_textMesh.font = Resources.Load("Fonts/ARIAL", typeof(Font)) as Font;
m_textMesh.GetComponent<Renderer>().sharedMaterial = m_textMesh.font.material;
}
m_textMesh.fontSize = 48;
m_textMesh.anchor = TextAnchor.MiddleCenter;
//m_textMesh.color = new Color32(255, 255, 0, 255);
}
for (var i = 0; i <= 1000000; i++)
{
if (BenchmarkType == 0)
{
m_textMeshPro.SetText(label01, i % 1000);
if (i % 1000 == 999)
m_textMeshPro.fontSharedMaterial = m_textMeshPro.fontSharedMaterial == m_material01
? m_textMeshPro.fontSharedMaterial = m_material02
: m_textMeshPro.fontSharedMaterial = m_material01;
}
else if (BenchmarkType == 1)
{
m_textMesh.text = label02 + (i % 1000);
}
yield return null;
}
yield return null;
}
/*
void Update()
{
if (BenchmarkType == 0)
{
m_textMeshPro.text = (m_frame % 1000).ToString();
}
else if (BenchmarkType == 1)
{
m_textMesh.text = (m_frame % 1000).ToString();
}
m_frame += 1;
}
*/
}
}

View File

@ -0,0 +1,10 @@
fileFormatVersion: 2
guid: f970ea55f9f84bf79b05dab180b8c125
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,126 @@
using System.Collections;
using UnityEngine;
using UnityEngine.UI;
namespace TMPro.Examples
{
public class Benchmark01_UGUI : MonoBehaviour
{
private const string label01 = "The <#0050FF>count is: </color>";
private const string label02 = "The <color=#0050FF>count is: </color>";
public int BenchmarkType;
public Canvas canvas;
public TMP_FontAsset TMProFont;
public Font TextMeshFont;
//private const string label01 = "TextMesh <#0050FF>Pro!</color> The count is: {0}";
//private const string label02 = "Text Mesh<color=#0050FF> The count is: </color>";
//private string m_string;
//private int m_frame;
private Material m_material01;
private Material m_material02;
//private TextContainer m_textContainer;
private Text m_textMesh;
private TextMeshProUGUI m_textMeshPro;
private IEnumerator Start()
{
if (BenchmarkType == 0) // TextMesh Pro Component
{
m_textMeshPro = gameObject.AddComponent<TextMeshProUGUI>();
//m_textContainer = GetComponent<TextContainer>();
//m_textMeshPro.anchorDampening = true;
if (TMProFont != null)
m_textMeshPro.font = TMProFont;
//m_textMeshPro.font = Resources.Load("Fonts & Materials/Anton SDF", typeof(TextMeshProFont)) as TextMeshProFont; // Make sure the Anton SDF exists before calling this...
//m_textMeshPro.fontSharedMaterial = Resources.Load("Fonts & Materials/Anton SDF", typeof(Material)) as Material; // Same as above make sure this material exists.
m_textMeshPro.fontSize = 48;
m_textMeshPro.alignment = TextAlignmentOptions.Center;
//m_textMeshPro.anchor = AnchorPositions.Center;
m_textMeshPro.extraPadding = true;
//m_textMeshPro.outlineWidth = 0.25f;
//m_textMeshPro.fontSharedMaterial.SetFloat("_OutlineWidth", 0.2f);
//m_textMeshPro.fontSharedMaterial.EnableKeyword("UNDERLAY_ON");
//m_textMeshPro.lineJustification = LineJustificationTypes.Center;
//m_textMeshPro.enableWordWrapping = true;
//m_textMeshPro.lineLength = 60;
//m_textMeshPro.characterSpacing = 0.2f;
//m_textMeshPro.fontColor = new Color32(255, 255, 255, 255);
m_material01 = m_textMeshPro.font.material;
m_material02 =
Resources.Load<Material>(
"Fonts & Materials/LiberationSans SDF - BEVEL"); // Make sure the LiberationSans SDF exists before calling this...
}
else if (BenchmarkType == 1) // TextMesh
{
m_textMesh = gameObject.AddComponent<Text>();
if (TextMeshFont != null)
{
m_textMesh.font = TextMeshFont;
//m_textMesh.renderer.sharedMaterial = m_textMesh.font.material;
}
//m_textMesh.font = Resources.Load("Fonts/ARIAL", typeof(Font)) as Font;
//m_textMesh.renderer.sharedMaterial = m_textMesh.font.material;
m_textMesh.fontSize = 48;
m_textMesh.alignment = TextAnchor.MiddleCenter;
//m_textMesh.color = new Color32(255, 255, 0, 255);
}
for (var i = 0; i <= 1000000; i++)
{
if (BenchmarkType == 0)
{
m_textMeshPro.text = label01 + i % 1000;
if (i % 1000 == 999)
m_textMeshPro.fontSharedMaterial = m_textMeshPro.fontSharedMaterial == m_material01
? m_textMeshPro.fontSharedMaterial = m_material02
: m_textMeshPro.fontSharedMaterial = m_material01;
}
else if (BenchmarkType == 1)
{
m_textMesh.text = label02 + (i % 1000);
}
yield return null;
}
yield return null;
}
/*
void Update()
{
if (BenchmarkType == 0)
{
m_textMeshPro.text = (m_frame % 1000).ToString();
}
else if (BenchmarkType == 1)
{
m_textMesh.text = (m_frame % 1000).ToString();
}
m_frame += 1;
}
*/
}
}

View File

@ -0,0 +1,10 @@
fileFormatVersion: 2
guid: 8ef7be1c625941f7ba8ed7cc71718c0d
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,85 @@
using UnityEngine;
namespace TMPro.Examples
{
public class Benchmark02 : MonoBehaviour
{
public int SpawnType;
public int NumberOfNPC = 12;
public bool IsTextObjectScaleStatic;
private TextMeshProFloatingText floatingText_Script;
private void Start()
{
for (var i = 0; i < NumberOfNPC; i++)
if (SpawnType == 0)
{
// TextMesh Pro Implementation
var go = new GameObject();
go.transform.position = new Vector3(Random.Range(-95f, 95f), 0.25f, Random.Range(-95f, 95f));
var textMeshPro = go.AddComponent<TextMeshPro>();
textMeshPro.autoSizeTextContainer = true;
textMeshPro.rectTransform.pivot = new Vector2(0.5f, 0);
textMeshPro.alignment = TextAlignmentOptions.Bottom;
textMeshPro.fontSize = 96;
textMeshPro.enableKerning = false;
textMeshPro.color = new Color32(255, 255, 0, 255);
textMeshPro.text = "!";
textMeshPro.isTextObjectScaleStatic = IsTextObjectScaleStatic;
// Spawn Floating Text
floatingText_Script = go.AddComponent<TextMeshProFloatingText>();
floatingText_Script.SpawnType = 0;
floatingText_Script.IsTextObjectScaleStatic = IsTextObjectScaleStatic;
}
else if (SpawnType == 1)
{
// TextMesh Implementation
var go = new GameObject();
go.transform.position = new Vector3(Random.Range(-95f, 95f), 0.25f, Random.Range(-95f, 95f));
var textMesh = go.AddComponent<TextMesh>();
textMesh.font = Resources.Load<Font>("Fonts/ARIAL");
textMesh.GetComponent<Renderer>().sharedMaterial = textMesh.font.material;
textMesh.anchor = TextAnchor.LowerCenter;
textMesh.fontSize = 96;
textMesh.color = new Color32(255, 255, 0, 255);
textMesh.text = "!";
// Spawn Floating Text
floatingText_Script = go.AddComponent<TextMeshProFloatingText>();
floatingText_Script.SpawnType = 1;
}
else if (SpawnType == 2)
{
// Canvas WorldSpace Camera
var go = new GameObject();
var canvas = go.AddComponent<Canvas>();
canvas.worldCamera = Camera.main;
go.transform.localScale = new Vector3(0.1f, 0.1f, 0.1f);
go.transform.position = new Vector3(Random.Range(-95f, 95f), 5f, Random.Range(-95f, 95f));
var textObject = new GameObject().AddComponent<TextMeshProUGUI>();
textObject.rectTransform.SetParent(go.transform, false);
textObject.color = new Color32(255, 255, 0, 255);
textObject.alignment = TextAlignmentOptions.Bottom;
textObject.fontSize = 96;
textObject.text = "!";
// Spawn Floating Text
floatingText_Script = go.AddComponent<TextMeshProFloatingText>();
floatingText_Script.SpawnType = 0;
}
}
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: e8538afcddc14efbb5d9e94b7ae50197
MonoImporter:
serializedVersion: 2
defaultReferences:
- TheFont: {instanceID: 0}
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,91 @@
using UnityEngine;
using UnityEngine.TextCore.LowLevel;
namespace TMPro.Examples
{
public class Benchmark03 : MonoBehaviour
{
public enum BenchmarkType
{
TMP_SDF_MOBILE = 0,
TMP_SDF__MOBILE_SSD = 1,
TMP_SDF = 2,
TMP_BITMAP_MOBILE = 3,
TEXTMESH_BITMAP = 4
}
public int NumberOfSamples = 100;
public BenchmarkType Benchmark;
public Font SourceFont;
private void Awake()
{
}
private void Start()
{
TMP_FontAsset fontAsset = null;
// Create Dynamic Font Asset for the given font file.
switch (Benchmark)
{
case BenchmarkType.TMP_SDF_MOBILE:
fontAsset = TMP_FontAsset.CreateFontAsset(SourceFont, 90, 9, GlyphRenderMode.SDFAA, 256, 256);
break;
case BenchmarkType.TMP_SDF__MOBILE_SSD:
fontAsset = TMP_FontAsset.CreateFontAsset(SourceFont, 90, 9, GlyphRenderMode.SDFAA, 256, 256);
fontAsset.material.shader = Shader.Find("TextMeshPro/Mobile/Distance Field SSD");
break;
case BenchmarkType.TMP_SDF:
fontAsset = TMP_FontAsset.CreateFontAsset(SourceFont, 90, 9, GlyphRenderMode.SDFAA, 256, 256);
fontAsset.material.shader = Shader.Find("TextMeshPro/Distance Field");
break;
case BenchmarkType.TMP_BITMAP_MOBILE:
fontAsset = TMP_FontAsset.CreateFontAsset(SourceFont, 90, 9, GlyphRenderMode.SMOOTH, 256, 256);
break;
}
for (var i = 0; i < NumberOfSamples; i++)
switch (Benchmark)
{
case BenchmarkType.TMP_SDF_MOBILE:
case BenchmarkType.TMP_SDF__MOBILE_SSD:
case BenchmarkType.TMP_SDF:
case BenchmarkType.TMP_BITMAP_MOBILE:
{
var go = new GameObject();
go.transform.position = new Vector3(0, 1.2f, 0);
var textComponent = go.AddComponent<TextMeshPro>();
textComponent.font = fontAsset;
textComponent.fontSize = 128;
textComponent.text = "@";
textComponent.alignment = TextAlignmentOptions.Center;
textComponent.color = new Color32(255, 255, 0, 255);
if (Benchmark == BenchmarkType.TMP_BITMAP_MOBILE)
textComponent.fontSize = 132;
}
break;
case BenchmarkType.TEXTMESH_BITMAP:
{
var go = new GameObject();
go.transform.position = new Vector3(0, 1.2f, 0);
var textMesh = go.AddComponent<TextMesh>();
textMesh.GetComponent<Renderer>().sharedMaterial = SourceFont.material;
textMesh.font = SourceFont;
textMesh.anchor = TextAnchor.MiddleCenter;
textMesh.fontSize = 130;
textMesh.color = new Color32(255, 255, 0, 255);
textMesh.text = "@";
}
break;
}
}
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: a73109742c8d47ac822895a473300c29
MonoImporter:
serializedVersion: 2
defaultReferences:
- TheFont: {instanceID: 0}
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,77 @@
using UnityEngine;
namespace TMPro.Examples
{
public class Benchmark04 : MonoBehaviour
{
public int SpawnType;
public int MinPointSize = 12;
public int MaxPointSize = 64;
public int Steps = 4;
private Transform m_Transform;
//private TextMeshProFloatingText floatingText_Script;
//public Material material;
private void Start()
{
m_Transform = transform;
float lineHeight = 0;
var orthoSize = Camera.main.orthographicSize = Screen.height / 2;
var ratio = (float)Screen.width / Screen.height;
for (var i = MinPointSize; i <= MaxPointSize; i += Steps)
if (SpawnType == 0)
{
// TextMesh Pro Implementation
var go = new GameObject("Text - " + i + " Pts");
if (lineHeight > orthoSize * 2) return;
go.transform.position = m_Transform.position +
new Vector3(ratio * -orthoSize * 0.975f, orthoSize * 0.975f - lineHeight,
0);
var textMeshPro = go.AddComponent<TextMeshPro>();
//textMeshPro.fontSharedMaterial = material;
//textMeshPro.font = Resources.Load("Fonts & Materials/LiberationSans SDF", typeof(TextMeshProFont)) as TextMeshProFont;
//textMeshPro.anchor = AnchorPositions.Left;
textMeshPro.rectTransform.pivot = new Vector2(0, 0.5f);
textMeshPro.enableWordWrapping = false;
textMeshPro.extraPadding = true;
textMeshPro.isOrthographic = true;
textMeshPro.fontSize = i;
textMeshPro.text = i + " pts - Lorem ipsum dolor sit...";
textMeshPro.color = new Color32(255, 255, 255, 255);
lineHeight += i;
}
// TextMesh Implementation
// Causes crashes since atlas needed exceeds 4096 X 4096
/*
GameObject go = new GameObject("Arial " + i);
//if (lineHeight > orthoSize * 2 * 0.9f) return;
go.transform.position = m_Transform.position + new Vector3(ratio * -orthoSize * 0.975f, orthoSize * 0.975f - lineHeight, 1);
TextMesh textMesh = go.AddComponent<TextMesh>();
textMesh.font = Resources.Load("Fonts/ARIAL", typeof(Font)) as Font;
textMesh.renderer.sharedMaterial = textMesh.font.material;
textMesh.anchor = TextAnchor.MiddleLeft;
textMesh.fontSize = i * 10;
textMesh.color = new Color32(255, 255, 255, 255);
textMesh.text = i + " pts - Lorem ipsum dolor sit...";
lineHeight += i;
*/
}
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: dc20866c0d5e413ab7559440e15333ae
MonoImporter:
serializedVersion: 2
defaultReferences:
- TheFont: {instanceID: 0}
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,278 @@
using UnityEngine;
namespace TMPro.Examples
{
public class CameraController : MonoBehaviour
{
public enum CameraModes
{
Follow,
Isometric,
Free
}
// Controls for Touches on Mobile devices
//private float prev_ZoomDelta;
private const string event_SmoothingValue = "Slider - Smoothing Value";
private const string event_FollowDistance = "Slider - Camera Zoom";
public Transform CameraTarget;
public float FollowDistance = 30.0f;
public float MaxFollowDistance = 100.0f;
public float MinFollowDistance = 2.0f;
public float ElevationAngle = 30.0f;
public float MaxElevationAngle = 85.0f;
public float MinElevationAngle;
public float OrbitalAngle;
public CameraModes CameraMode = CameraModes.Follow;
public bool MovementSmoothing = true;
public bool RotationSmoothing;
public float MovementSmoothingValue = 25f;
public float RotationSmoothingValue = 5.0f;
public float MoveSensitivity = 2.0f;
private Transform cameraTransform;
private Vector3 currentVelocity = Vector3.zero;
private Vector3 desiredPosition;
private Transform dummyTarget;
private float mouseWheel;
private float mouseX;
private float mouseY;
private Vector3 moveVector;
private bool previousSmoothing;
private void Awake()
{
if (QualitySettings.vSyncCount > 0)
Application.targetFrameRate = 60;
else
Application.targetFrameRate = -1;
if (Application.platform == RuntimePlatform.IPhonePlayer || Application.platform == RuntimePlatform.Android)
Input.simulateMouseWithTouches = false;
cameraTransform = transform;
previousSmoothing = MovementSmoothing;
}
// Use this for initialization
private void Start()
{
if (CameraTarget == null)
{
// If we don't have a target (assigned by the player, create a dummy in the center of the scene).
dummyTarget = new GameObject("Camera Target").transform;
CameraTarget = dummyTarget;
}
}
// Update is called once per frame
private void LateUpdate()
{
GetPlayerInput();
// Check if we still have a valid target
if (CameraTarget != null)
{
if (CameraMode == CameraModes.Isometric)
{
desiredPosition = CameraTarget.position + Quaternion.Euler(ElevationAngle, OrbitalAngle, 0f) *
new Vector3(0, 0, -FollowDistance);
}
else if (CameraMode == CameraModes.Follow)
{
desiredPosition = CameraTarget.position + CameraTarget.TransformDirection(
Quaternion.Euler(ElevationAngle, OrbitalAngle, 0f) * new Vector3(0, 0, -FollowDistance));
}
// Free Camera implementation
if (MovementSmoothing)
// Using Smoothing
cameraTransform.position = Vector3.SmoothDamp(cameraTransform.position, desiredPosition,
ref currentVelocity, MovementSmoothingValue * Time.fixedDeltaTime);
//cameraTransform.position = Vector3.Lerp(cameraTransform.position, desiredPosition, Time.deltaTime * 5.0f);
else
// Not using Smoothing
cameraTransform.position = desiredPosition;
if (RotationSmoothing)
cameraTransform.rotation = Quaternion.Lerp(cameraTransform.rotation,
Quaternion.LookRotation(CameraTarget.position - cameraTransform.position),
RotationSmoothingValue * Time.deltaTime);
else
cameraTransform.LookAt(CameraTarget);
}
}
private void GetPlayerInput()
{
moveVector = Vector3.zero;
// Check Mouse Wheel Input prior to Shift Key so we can apply multiplier on Shift for Scrolling
mouseWheel = Input.GetAxis("Mouse ScrollWheel");
float touchCount = Input.touchCount;
if (Input.GetKey(KeyCode.LeftShift) || Input.GetKey(KeyCode.RightShift) || touchCount > 0)
{
mouseWheel *= 10;
if (Input.GetKeyDown(KeyCode.I))
CameraMode = CameraModes.Isometric;
if (Input.GetKeyDown(KeyCode.F))
CameraMode = CameraModes.Follow;
if (Input.GetKeyDown(KeyCode.S))
MovementSmoothing = !MovementSmoothing;
// Check for right mouse button to change camera follow and elevation angle
if (Input.GetMouseButton(1))
{
mouseY = Input.GetAxis("Mouse Y");
mouseX = Input.GetAxis("Mouse X");
if (mouseY > 0.01f || mouseY < -0.01f)
{
ElevationAngle -= mouseY * MoveSensitivity;
// Limit Elevation angle between min & max values.
ElevationAngle = Mathf.Clamp(ElevationAngle, MinElevationAngle, MaxElevationAngle);
}
if (mouseX > 0.01f || mouseX < -0.01f)
{
OrbitalAngle += mouseX * MoveSensitivity;
if (OrbitalAngle > 360)
OrbitalAngle -= 360;
if (OrbitalAngle < 0)
OrbitalAngle += 360;
}
}
// Get Input from Mobile Device
if (touchCount == 1 && Input.GetTouch(0).phase == TouchPhase.Moved)
{
var deltaPosition = Input.GetTouch(0).deltaPosition;
// Handle elevation changes
if (deltaPosition.y > 0.01f || deltaPosition.y < -0.01f)
{
ElevationAngle -= deltaPosition.y * 0.1f;
// Limit Elevation angle between min & max values.
ElevationAngle = Mathf.Clamp(ElevationAngle, MinElevationAngle, MaxElevationAngle);
}
// Handle left & right
if (deltaPosition.x > 0.01f || deltaPosition.x < -0.01f)
{
OrbitalAngle += deltaPosition.x * 0.1f;
if (OrbitalAngle > 360)
OrbitalAngle -= 360;
if (OrbitalAngle < 0)
OrbitalAngle += 360;
}
}
// Check for left mouse button to select a new CameraTarget or to reset Follow position
if (Input.GetMouseButton(0))
{
var ray = Camera.main.ScreenPointToRay(Input.mousePosition);
RaycastHit hit;
if (Physics.Raycast(ray, out hit, 300, (1 << 10) | (1 << 11) | (1 << 12) | (1 << 14)))
{
if (hit.transform == CameraTarget)
{
// Reset Follow Position
OrbitalAngle = 0;
}
else
{
CameraTarget = hit.transform;
OrbitalAngle = 0;
MovementSmoothing = previousSmoothing;
}
}
}
if (Input.GetMouseButton(2))
{
if (dummyTarget == null)
{
// We need a Dummy Target to anchor the Camera
dummyTarget = new GameObject("Camera Target").transform;
dummyTarget.position = CameraTarget.position;
dummyTarget.rotation = CameraTarget.rotation;
CameraTarget = dummyTarget;
previousSmoothing = MovementSmoothing;
MovementSmoothing = false;
}
else if (dummyTarget != CameraTarget)
{
// Move DummyTarget to CameraTarget
dummyTarget.position = CameraTarget.position;
dummyTarget.rotation = CameraTarget.rotation;
CameraTarget = dummyTarget;
previousSmoothing = MovementSmoothing;
MovementSmoothing = false;
}
mouseY = Input.GetAxis("Mouse Y");
mouseX = Input.GetAxis("Mouse X");
moveVector = cameraTransform.TransformDirection(mouseX, mouseY, 0);
dummyTarget.Translate(-moveVector, Space.World);
}
}
// Check Pinching to Zoom in - out on Mobile device
if (touchCount == 2)
{
var touch0 = Input.GetTouch(0);
var touch1 = Input.GetTouch(1);
var touch0PrevPos = touch0.position - touch0.deltaPosition;
var touch1PrevPos = touch1.position - touch1.deltaPosition;
var prevTouchDelta = (touch0PrevPos - touch1PrevPos).magnitude;
var touchDelta = (touch0.position - touch1.position).magnitude;
var zoomDelta = prevTouchDelta - touchDelta;
if (zoomDelta > 0.01f || zoomDelta < -0.01f)
{
FollowDistance += zoomDelta * 0.25f;
// Limit FollowDistance between min & max values.
FollowDistance = Mathf.Clamp(FollowDistance, MinFollowDistance, MaxFollowDistance);
}
}
// Check MouseWheel to Zoom in-out
if (mouseWheel < -0.01f || mouseWheel > 0.01f)
{
FollowDistance -= mouseWheel * 5.0f;
// Limit FollowDistance between min & max values.
FollowDistance = Mathf.Clamp(FollowDistance, MinFollowDistance, MaxFollowDistance);
}
}
}
}

View File

@ -0,0 +1,10 @@
fileFormatVersion: 2
guid: 2d687537154440a3913a9a3c7977978c
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,51 @@
using System;
using TMPro;
using UnityEngine;
using UnityEngine.UI;
public class ChatController : MonoBehaviour
{
public TMP_InputField ChatInputField;
public TMP_Text ChatDisplayOutput;
public Scrollbar ChatScrollbar;
private void OnEnable()
{
ChatInputField.onSubmit.AddListener(AddToChatOutput);
}
private void OnDisable()
{
ChatInputField.onSubmit.RemoveListener(AddToChatOutput);
}
private void AddToChatOutput(string newText)
{
// Clear Input Field
ChatInputField.text = string.Empty;
var timeNow = DateTime.Now;
var formattedInput = "[<#FFFF80>" + timeNow.Hour.ToString("d2") + ":" + timeNow.Minute.ToString("d2") + ":" +
timeNow.Second.ToString("d2") + "</color>] " + newText;
if (ChatDisplayOutput != null)
{
// No special formatting for first entry
// Add line feed before each subsequent entries
if (ChatDisplayOutput.text == string.Empty)
ChatDisplayOutput.text = formattedInput;
else
ChatDisplayOutput.text += "\n" + formattedInput;
}
// Keep Chat input field active
ChatInputField.ActivateInputField();
// Set the scrollbar to the bottom when next text is submitted.
ChatScrollbar.value = 0;
}
}

View File

@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: 53d91f98a2664f5cb9af11de72ac54ec
timeCreated: 1487197841
licenseType: Pro
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,18 @@
using TMPro;
using UnityEngine;
public class DropdownSample : MonoBehaviour
{
[SerializeField] private TextMeshProUGUI text;
[SerializeField] private TMP_Dropdown dropdownWithoutPlaceholder;
[SerializeField] private TMP_Dropdown dropdownWithPlaceholder;
public void OnButtonClick()
{
text.text = dropdownWithPlaceholder.value > -1
? "Selected values:\n" + dropdownWithoutPlaceholder.value + " - " + dropdownWithPlaceholder.value
: "Error: Please make a selection";
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: ac1eb05af6d391b4eb0f4c070a99f1d0
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,37 @@
using System.Collections;
using TMPro;
using UnityEngine;
public class EnvMapAnimator : MonoBehaviour
{
//private Vector3 TranslationSpeeds;
public Vector3 RotationSpeeds;
private Material m_material;
private TMP_Text m_textMeshPro;
private void Awake()
{
//Debug.Log("Awake() on Script called.");
m_textMeshPro = GetComponent<TMP_Text>();
m_material = m_textMeshPro.fontSharedMaterial;
}
// Use this for initialization
private IEnumerator Start()
{
var matrix = new Matrix4x4();
while (true)
{
//matrix.SetTRS(new Vector3 (Time.time * TranslationSpeeds.x, Time.time * TranslationSpeeds.y, Time.time * TranslationSpeeds.z), Quaternion.Euler(Time.time * RotationSpeeds.x, Time.time * RotationSpeeds.y , Time.time * RotationSpeeds.z), Vector3.one);
matrix.SetTRS(Vector3.zero,
Quaternion.Euler(Time.time * RotationSpeeds.x, Time.time * RotationSpeeds.y,
Time.time * RotationSpeeds.z), Vector3.one);
m_material.SetMatrix("_EnvMatrix", matrix);
yield return null;
}
}
}

View File

@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: a4b6f99e8bc54541bbd149b014ff441c
timeCreated: 1449025325
licenseType: Pro
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,72 @@
using UnityEngine;
namespace TMPro.Examples
{
public class ObjectSpin : MonoBehaviour
{
#pragma warning disable 0414
public float SpinSpeed = 5;
public int RotationRange = 15;
private Transform m_transform;
private float m_time;
private Vector3 m_prevPOS;
private Vector3 m_initial_Rotation;
private Vector3 m_initial_Position;
private Color32 m_lightColor;
private int frames;
public enum MotionType
{
Rotation,
BackAndForth,
Translation
}
public MotionType Motion;
private void Awake()
{
m_transform = transform;
m_initial_Rotation = m_transform.rotation.eulerAngles;
m_initial_Position = m_transform.position;
var light = GetComponent<Light>();
m_lightColor = light != null ? light.color : Color.black;
}
// Update is called once per frame
private void Update()
{
if (Motion == MotionType.Rotation)
{
m_transform.Rotate(0, SpinSpeed * Time.deltaTime, 0);
}
else if (Motion == MotionType.BackAndForth)
{
m_time += SpinSpeed * Time.deltaTime;
m_transform.rotation = Quaternion.Euler(m_initial_Rotation.x,
Mathf.Sin(m_time) * RotationRange + m_initial_Rotation.y, m_initial_Rotation.z);
}
else
{
m_time += SpinSpeed * Time.deltaTime;
var x = 15 * Mathf.Cos(m_time * .95f);
float y = 10; // *Mathf.Sin(m_time * 1f) * Mathf.Cos(m_time * 1f);
var z = 0f; // *Mathf.Sin(m_time * .9f);
m_transform.position = m_initial_Position + new Vector3(x, z, y);
// Drawing light patterns because they can be cool looking.
//if (frames > 2)
// Debug.DrawLine(m_transform.position, m_prevPOS, m_lightColor, 100f);
m_prevPOS = m_transform.position;
frames += 1;
}
}
}
}

View File

@ -0,0 +1,10 @@
fileFormatVersion: 2
guid: 4f19c7f94c794c5097d8bd11e39c750d
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,48 @@
using System.Collections;
using UnityEngine;
namespace TMPro.Examples
{
public class ShaderPropAnimator : MonoBehaviour
{
public AnimationCurve GlowCurve;
public float m_frame;
private Material m_Material;
private Renderer m_Renderer;
private void Awake()
{
// Cache a reference to object's renderer
m_Renderer = GetComponent<Renderer>();
// Cache a reference to object's material and create an instance by doing so.
m_Material = m_Renderer.material;
}
private void Start()
{
StartCoroutine(AnimateProperties());
}
private IEnumerator AnimateProperties()
{
//float lightAngle;
float glowPower;
m_frame = Random.Range(0f, 1f);
while (true)
{
//lightAngle = (m_Material.GetFloat(ShaderPropertyIDs.ID_LightAngle) + Time.deltaTime) % 6.2831853f;
//m_Material.SetFloat(ShaderPropertyIDs.ID_LightAngle, lightAngle);
glowPower = GlowCurve.Evaluate(m_frame);
m_Material.SetFloat(ShaderUtilities.ID_GlowPower, glowPower);
m_frame += Time.deltaTime * Random.Range(0.2f, 0.3f);
yield return new WaitForEndOfFrame();
}
}
}
}

View File

@ -0,0 +1,10 @@
fileFormatVersion: 2
guid: 2787a46a4dc848c1b4b7b9307b614bfd
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,54 @@
using UnityEngine;
namespace TMPro.Examples
{
public class SimpleScript : MonoBehaviour
{
//private TMP_FontAsset m_FontAsset;
private const string label = "The <#0050FF>count is: </color>{0:2}";
private float m_frame;
private TextMeshPro m_textMeshPro;
private void Start()
{
// Add new TextMesh Pro Component
m_textMeshPro = gameObject.AddComponent<TextMeshPro>();
m_textMeshPro.autoSizeTextContainer = true;
// Load the Font Asset to be used.
//m_FontAsset = Resources.Load("Fonts & Materials/LiberationSans SDF", typeof(TMP_FontAsset)) as TMP_FontAsset;
//m_textMeshPro.font = m_FontAsset;
// Assign Material to TextMesh Pro Component
//m_textMeshPro.fontSharedMaterial = Resources.Load("Fonts & Materials/LiberationSans SDF - Bevel", typeof(Material)) as Material;
//m_textMeshPro.fontSharedMaterial.EnableKeyword("BEVEL_ON");
// Set various font settings.
m_textMeshPro.fontSize = 48;
m_textMeshPro.alignment = TextAlignmentOptions.Center;
//m_textMeshPro.anchorDampening = true; // Has been deprecated but under consideration for re-implementation.
//m_textMeshPro.enableAutoSizing = true;
//m_textMeshPro.characterSpacing = 0.2f;
//m_textMeshPro.wordSpacing = 0.1f;
//m_textMeshPro.enableCulling = true;
m_textMeshPro.enableWordWrapping = false;
//textMeshPro.fontColor = new Color32(255, 255, 255, 255);
}
private void Update()
{
m_textMeshPro.SetText(label, m_frame % 1000);
m_frame += 1 * Time.deltaTime;
}
}
}

View File

@ -0,0 +1,10 @@
fileFormatVersion: 2
guid: 9eff140b25d64601aabc6ba32245d099
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,168 @@
using System.Collections;
using UnityEngine;
namespace TMPro.Examples
{
public class SkewTextExample : MonoBehaviour
{
public AnimationCurve VertexCurve = new(new Keyframe(0, 0), new Keyframe(0.25f, 2.0f), new Keyframe(0.5f, 0),
new Keyframe(0.75f, 2.0f), new Keyframe(1, 0f));
//public float AngleMultiplier = 1.0f;
//public float SpeedMultiplier = 1.0f;
public float CurveScale = 1.0f;
public float ShearAmount = 1.0f;
private TMP_Text m_TextComponent;
private void Awake()
{
m_TextComponent = gameObject.GetComponent<TMP_Text>();
}
private void Start()
{
StartCoroutine(WarpText());
}
private AnimationCurve CopyAnimationCurve(AnimationCurve curve)
{
var newCurve = new AnimationCurve();
newCurve.keys = curve.keys;
return newCurve;
}
/// <summary>
/// Method to curve text along a Unity animation curve.
/// </summary>
/// <param name="textComponent"></param>
/// <returns></returns>
private IEnumerator WarpText()
{
VertexCurve.preWrapMode = WrapMode.Clamp;
VertexCurve.postWrapMode = WrapMode.Clamp;
//Mesh mesh = m_TextComponent.textInfo.meshInfo[0].mesh;
Vector3[] vertices;
Matrix4x4 matrix;
m_TextComponent.havePropertiesChanged = true; // Need to force the TextMeshPro Object to be updated.
CurveScale *= 10;
var old_CurveScale = CurveScale;
var old_ShearValue = ShearAmount;
var old_curve = CopyAnimationCurve(VertexCurve);
while (true)
{
if (!m_TextComponent.havePropertiesChanged && old_CurveScale == CurveScale &&
old_curve.keys[1].value == VertexCurve.keys[1].value && old_ShearValue == ShearAmount)
{
yield return null;
continue;
}
old_CurveScale = CurveScale;
old_curve = CopyAnimationCurve(VertexCurve);
old_ShearValue = ShearAmount;
m_TextComponent
.ForceMeshUpdate(); // Generate the mesh and populate the textInfo with data we can use and manipulate.
var textInfo = m_TextComponent.textInfo;
var characterCount = textInfo.characterCount;
if (characterCount == 0) continue;
//vertices = textInfo.meshInfo[0].vertices;
//int lastVertexIndex = textInfo.characterInfo[characterCount - 1].vertexIndex;
var boundsMinX = m_TextComponent.bounds.min.x; //textInfo.meshInfo[0].mesh.bounds.min.x;
var boundsMaxX = m_TextComponent.bounds.max.x; //textInfo.meshInfo[0].mesh.bounds.max.x;
for (var i = 0; i < characterCount; i++)
{
if (!textInfo.characterInfo[i].isVisible)
continue;
var vertexIndex = textInfo.characterInfo[i].vertexIndex;
// Get the index of the mesh used by this character.
var materialIndex = textInfo.characterInfo[i].materialReferenceIndex;
vertices = textInfo.meshInfo[materialIndex].vertices;
// Compute the baseline mid point for each character
Vector3 offsetToMidBaseline =
new Vector2((vertices[vertexIndex + 0].x + vertices[vertexIndex + 2].x) / 2,
textInfo.characterInfo[i].baseLine);
//float offsetY = VertexCurve.Evaluate((float)i / characterCount + loopCount / 50f); // Random.Range(-0.25f, 0.25f);
// Apply offset to adjust our pivot point.
vertices[vertexIndex + 0] += -offsetToMidBaseline;
vertices[vertexIndex + 1] += -offsetToMidBaseline;
vertices[vertexIndex + 2] += -offsetToMidBaseline;
vertices[vertexIndex + 3] += -offsetToMidBaseline;
// Apply the Shearing FX
var shear_value = ShearAmount * 0.01f;
var topShear =
new Vector3(
shear_value * (textInfo.characterInfo[i].topRight.y - textInfo.characterInfo[i].baseLine),
0, 0);
var bottomShear =
new Vector3(
shear_value * (textInfo.characterInfo[i].baseLine -
textInfo.characterInfo[i].bottomRight.y), 0, 0);
vertices[vertexIndex + 0] += -bottomShear;
vertices[vertexIndex + 1] += topShear;
vertices[vertexIndex + 2] += topShear;
vertices[vertexIndex + 3] += -bottomShear;
// Compute the angle of rotation for each character based on the animation curve
var x0 = (offsetToMidBaseline.x - boundsMinX) /
(boundsMaxX - boundsMinX); // Character's position relative to the bounds of the mesh.
var x1 = x0 + 0.0001f;
var y0 = VertexCurve.Evaluate(x0) * CurveScale;
var y1 = VertexCurve.Evaluate(x1) * CurveScale;
var horizontal = new Vector3(1, 0, 0);
//Vector3 normal = new Vector3(-(y1 - y0), (x1 * (boundsMaxX - boundsMinX) + boundsMinX) - offsetToMidBaseline.x, 0);
var tangent = new Vector3(x1 * (boundsMaxX - boundsMinX) + boundsMinX, y1) -
new Vector3(offsetToMidBaseline.x, y0);
var dot = Mathf.Acos(Vector3.Dot(horizontal, tangent.normalized)) * 57.2957795f;
var cross = Vector3.Cross(horizontal, tangent);
var angle = cross.z > 0 ? dot : 360 - dot;
matrix = Matrix4x4.TRS(new Vector3(0, y0, 0), Quaternion.Euler(0, 0, angle), Vector3.one);
vertices[vertexIndex + 0] = matrix.MultiplyPoint3x4(vertices[vertexIndex + 0]);
vertices[vertexIndex + 1] = matrix.MultiplyPoint3x4(vertices[vertexIndex + 1]);
vertices[vertexIndex + 2] = matrix.MultiplyPoint3x4(vertices[vertexIndex + 2]);
vertices[vertexIndex + 3] = matrix.MultiplyPoint3x4(vertices[vertexIndex + 3]);
vertices[vertexIndex + 0] += offsetToMidBaseline;
vertices[vertexIndex + 1] += offsetToMidBaseline;
vertices[vertexIndex + 2] += offsetToMidBaseline;
vertices[vertexIndex + 3] += offsetToMidBaseline;
}
// Upload the mesh with the revised information
m_TextComponent.UpdateVertexData();
yield return null; // new WaitForSeconds(0.025f);
}
}
}
}

View File

@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: d412675cfb3441efa3bf8dcd9b7624dc
timeCreated: 1458801336
licenseType: Pro
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,25 @@
using System;
namespace TMPro
{
/// <summary>
/// EXample of a Custom Character Input Validator to only allow digits from 0 to 9.
/// </summary>
[Serializable]
//[CreateAssetMenu(fileName = "InputValidator - Digits.asset", menuName = "TextMeshPro/Input Validators/Digits", order = 100)]
public class TMP_DigitValidator : TMP_InputValidator
{
// Custom text input validation function
public override char Validate(ref string text, ref int pos, char ch)
{
if (ch >= '0' && ch <= '9')
{
text += ch;
pos += 1;
return ch;
}
return (char)0;
}
}
}

View File

@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: 1a7eb92a01ed499a987bde9def05fbce
timeCreated: 1473112765
licenseType: Pro
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,62 @@
using UnityEngine;
namespace TMPro.Examples
{
public class TMP_ExampleScript_01 : MonoBehaviour
{
public enum objectType
{
TextMeshPro = 0,
TextMeshProUGUI = 1
}
//private TMP_InputField m_inputfield;
private const string k_label = "The count is <#0080ff>{0}</color>";
public objectType ObjectType;
public bool isStatic;
private int count;
private TMP_Text m_text;
private void Awake()
{
// Get a reference to the TMP text component if one already exists otherwise add one.
// This example show the convenience of having both TMP components derive from TMP_Text.
if (ObjectType == 0)
m_text = GetComponent<TextMeshPro>() ?? gameObject.AddComponent<TextMeshPro>();
else
m_text = GetComponent<TextMeshProUGUI>() ?? gameObject.AddComponent<TextMeshProUGUI>();
// Load a new font asset and assign it to the text object.
m_text.font = Resources.Load<TMP_FontAsset>("Fonts & Materials/Anton SDF");
// Load a new material preset which was created with the context menu duplicate.
m_text.fontSharedMaterial = Resources.Load<Material>("Fonts & Materials/Anton SDF - Drop Shadow");
// Set the size of the font.
m_text.fontSize = 120;
// Set the text
m_text.text = "A <#0080ff>simple</color> line of text.";
// Get the preferred width and height based on the supplied width and height as opposed to the actual size of the current text container.
var size = m_text.GetPreferredValues(Mathf.Infinity, Mathf.Infinity);
// Set the size of the RectTransform based on the new calculated values.
m_text.rectTransform.sizeDelta = new Vector2(size.x, size.y);
}
private void Update()
{
if (!isStatic)
{
m_text.SetText(k_label, count % 1000);
count += 1;
}
}
}
}

View File

@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: 6f2c5b59b6874405865e2616e4ec276a
timeCreated: 1449625634
licenseType: Pro
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,136 @@
using UnityEngine;
namespace TMPro.Examples
{
public class TMP_FrameRateCounter : MonoBehaviour
{
public enum FpsCounterAnchorPositions
{
TopLeft,
BottomLeft,
TopRight,
BottomRight
}
private const string fpsLabel = "{0:2}</color> <#8080ff>FPS \n<#FF8000>{1:2} <#8080ff>MS";
public float UpdateInterval = 5.0f;
public FpsCounterAnchorPositions AnchorPosition = FpsCounterAnchorPositions.TopRight;
private string htmlColorTag;
private FpsCounterAnchorPositions last_AnchorPosition;
private Camera m_camera;
private Transform m_frameCounter_transform;
private int m_Frames;
private float m_LastInterval;
private TextMeshPro m_TextMeshPro;
private void Awake()
{
if (!enabled)
return;
m_camera = Camera.main;
Application.targetFrameRate = 9999;
var frameCounter = new GameObject("Frame Counter");
m_TextMeshPro = frameCounter.AddComponent<TextMeshPro>();
m_TextMeshPro.font = Resources.Load<TMP_FontAsset>("Fonts & Materials/LiberationSans SDF");
m_TextMeshPro.fontSharedMaterial =
Resources.Load<Material>("Fonts & Materials/LiberationSans SDF - Overlay");
m_frameCounter_transform = frameCounter.transform;
m_frameCounter_transform.SetParent(m_camera.transform);
m_frameCounter_transform.localRotation = Quaternion.identity;
m_TextMeshPro.enableWordWrapping = false;
m_TextMeshPro.fontSize = 24;
//m_TextMeshPro.FontColor = new Color32(255, 255, 255, 128);
//m_TextMeshPro.edgeWidth = .15f;
//m_TextMeshPro.isOverlay = true;
//m_TextMeshPro.FaceColor = new Color32(255, 128, 0, 0);
//m_TextMeshPro.EdgeColor = new Color32(0, 255, 0, 255);
//m_TextMeshPro.FontMaterial.renderQueue = 4000;
//m_TextMeshPro.CreateSoftShadowClone(new Vector2(1f, -1f));
Set_FrameCounter_Position(AnchorPosition);
last_AnchorPosition = AnchorPosition;
}
private void Start()
{
m_LastInterval = Time.realtimeSinceStartup;
m_Frames = 0;
}
private void Update()
{
if (AnchorPosition != last_AnchorPosition)
Set_FrameCounter_Position(AnchorPosition);
last_AnchorPosition = AnchorPosition;
m_Frames += 1;
var timeNow = Time.realtimeSinceStartup;
if (timeNow > m_LastInterval + UpdateInterval)
{
// display two fractional digits (f2 format)
var fps = m_Frames / (timeNow - m_LastInterval);
var ms = 1000.0f / Mathf.Max(fps, 0.00001f);
if (fps < 30)
htmlColorTag = "<color=yellow>";
else if (fps < 10)
htmlColorTag = "<color=red>";
else
htmlColorTag = "<color=green>";
//string format = System.String.Format(htmlColorTag + "{0:F2} </color>FPS \n{1:F2} <#8080ff>MS",fps, ms);
//m_TextMeshPro.text = format;
m_TextMeshPro.SetText(htmlColorTag + fpsLabel, fps, ms);
m_Frames = 0;
m_LastInterval = timeNow;
}
}
private void Set_FrameCounter_Position(FpsCounterAnchorPositions anchor_position)
{
//Debug.Log("Changing frame counter anchor position.");
m_TextMeshPro.margin = new Vector4(1f, 1f, 1f, 1f);
switch (anchor_position)
{
case FpsCounterAnchorPositions.TopLeft:
m_TextMeshPro.alignment = TextAlignmentOptions.TopLeft;
m_TextMeshPro.rectTransform.pivot = new Vector2(0, 1);
m_frameCounter_transform.position = m_camera.ViewportToWorldPoint(new Vector3(0, 1, 100.0f));
break;
case FpsCounterAnchorPositions.BottomLeft:
m_TextMeshPro.alignment = TextAlignmentOptions.BottomLeft;
m_TextMeshPro.rectTransform.pivot = new Vector2(0, 0);
m_frameCounter_transform.position = m_camera.ViewportToWorldPoint(new Vector3(0, 0, 100.0f));
break;
case FpsCounterAnchorPositions.TopRight:
m_TextMeshPro.alignment = TextAlignmentOptions.TopRight;
m_TextMeshPro.rectTransform.pivot = new Vector2(1, 1);
m_frameCounter_transform.position = m_camera.ViewportToWorldPoint(new Vector3(1, 1, 100.0f));
break;
case FpsCounterAnchorPositions.BottomRight:
m_TextMeshPro.alignment = TextAlignmentOptions.BottomRight;
m_TextMeshPro.rectTransform.pivot = new Vector2(1, 0);
m_frameCounter_transform.position = m_camera.ViewportToWorldPoint(new Vector3(1, 0, 100.0f));
break;
}
}
}
}

View File

@ -0,0 +1,10 @@
fileFormatVersion: 2
guid: 686ec78b56aa445795335fbadafcfaa4
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,102 @@
using System;
using UnityEngine;
namespace TMPro
{
/// <summary>
/// Example of a Custom Character Input Validator to only allow phone number in the (800) 555-1212 format.
/// </summary>
[Serializable]
//[CreateAssetMenu(fileName = "InputValidator - Phone Numbers.asset", menuName = "TextMeshPro/Input Validators/Phone Numbers")]
public class TMP_PhoneNumberValidator : TMP_InputValidator
{
// Custom text input validation function
public override char Validate(ref string text, ref int pos, char ch)
{
Debug.Log("Trying to validate...");
// Return unless the character is a valid digit
if (ch < '0' && ch > '9') return (char)0;
var length = text.Length;
// Enforce Phone Number format for every character input.
for (var i = 0; i < length + 1; i++)
switch (i)
{
case 0:
if (i == length)
text = "(" + ch;
pos = 2;
break;
case 1:
if (i == length)
text += ch;
pos = 2;
break;
case 2:
if (i == length)
text += ch;
pos = 3;
break;
case 3:
if (i == length)
text += ch + ") ";
pos = 6;
break;
case 4:
if (i == length)
text += ") " + ch;
pos = 7;
break;
case 5:
if (i == length)
text += " " + ch;
pos = 7;
break;
case 6:
if (i == length)
text += ch;
pos = 7;
break;
case 7:
if (i == length)
text += ch;
pos = 8;
break;
case 8:
if (i == length)
text += ch + "-";
pos = 10;
break;
case 9:
if (i == length)
text += "-" + ch;
pos = 11;
break;
case 10:
if (i == length)
text += ch;
pos = 11;
break;
case 11:
if (i == length)
text += ch;
pos = 12;
break;
case 12:
if (i == length)
text += ch;
pos = 13;
break;
case 13:
if (i == length)
text += ch;
pos = 14;
break;
}
return ch;
}
}
}

View File

@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: 83680ab1a69f4102ac67d1459fe76e1f
timeCreated: 1473056437
licenseType: Pro
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,73 @@
using UnityEngine;
namespace TMPro.Examples
{
public class TMP_TextEventCheck : MonoBehaviour
{
public TMP_TextEventHandler TextEventHandler;
private TMP_Text m_TextComponent;
private void OnEnable()
{
if (TextEventHandler != null)
{
// Get a reference to the text component
m_TextComponent = TextEventHandler.GetComponent<TMP_Text>();
TextEventHandler.onCharacterSelection.AddListener(OnCharacterSelection);
TextEventHandler.onSpriteSelection.AddListener(OnSpriteSelection);
TextEventHandler.onWordSelection.AddListener(OnWordSelection);
TextEventHandler.onLineSelection.AddListener(OnLineSelection);
TextEventHandler.onLinkSelection.AddListener(OnLinkSelection);
}
}
private void OnDisable()
{
if (TextEventHandler != null)
{
TextEventHandler.onCharacterSelection.RemoveListener(OnCharacterSelection);
TextEventHandler.onSpriteSelection.RemoveListener(OnSpriteSelection);
TextEventHandler.onWordSelection.RemoveListener(OnWordSelection);
TextEventHandler.onLineSelection.RemoveListener(OnLineSelection);
TextEventHandler.onLinkSelection.RemoveListener(OnLinkSelection);
}
}
private void OnCharacterSelection(char c, int index)
{
Debug.Log("Character [" + c + "] at Index: " + index + " has been selected.");
}
private void OnSpriteSelection(char c, int index)
{
Debug.Log("Sprite [" + c + "] at Index: " + index + " has been selected.");
}
private void OnWordSelection(string word, int firstCharacterIndex, int length)
{
Debug.Log("Word [" + word + "] with first character index of " + firstCharacterIndex + " and length of " +
length + " has been selected.");
}
private void OnLineSelection(string lineText, int firstCharacterIndex, int length)
{
Debug.Log("Line [" + lineText + "] with first character index of " + firstCharacterIndex +
" and length of " + length + " has been selected.");
}
private void OnLinkSelection(string linkID, string linkText, int linkIndex)
{
if (m_TextComponent != null)
{
var linkInfo = m_TextComponent.textInfo.linkInfo[linkIndex];
}
Debug.Log("Link Index: " + linkIndex + " with ID [" + linkID + "] and Text \"" + linkText +
"\" has been selected.");
}
}
}

View File

@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: d736ce056cf444ca96e424f4d9c42b76
timeCreated: 1480416736
licenseType: Pro
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,271 @@
using System;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.EventSystems;
namespace TMPro
{
public class TMP_TextEventHandler : MonoBehaviour, IPointerEnterHandler, IPointerExitHandler
{
[SerializeField] private CharacterSelectionEvent m_OnCharacterSelection = new();
[SerializeField] private SpriteSelectionEvent m_OnSpriteSelection = new();
[SerializeField] private WordSelectionEvent m_OnWordSelection = new();
[SerializeField] private LineSelectionEvent m_OnLineSelection = new();
[SerializeField] private LinkSelectionEvent m_OnLinkSelection = new();
private Camera m_Camera;
private Canvas m_Canvas;
private int m_lastCharIndex = -1;
private int m_lastLineIndex = -1;
private int m_lastWordIndex = -1;
private int m_selectedLink = -1;
private TMP_Text m_TextComponent;
/// <summary>
/// Event delegate triggered when pointer is over a character.
/// </summary>
public CharacterSelectionEvent onCharacterSelection
{
get => m_OnCharacterSelection;
set => m_OnCharacterSelection = value;
}
/// <summary>
/// Event delegate triggered when pointer is over a sprite.
/// </summary>
public SpriteSelectionEvent onSpriteSelection
{
get => m_OnSpriteSelection;
set => m_OnSpriteSelection = value;
}
/// <summary>
/// Event delegate triggered when pointer is over a word.
/// </summary>
public WordSelectionEvent onWordSelection
{
get => m_OnWordSelection;
set => m_OnWordSelection = value;
}
/// <summary>
/// Event delegate triggered when pointer is over a line.
/// </summary>
public LineSelectionEvent onLineSelection
{
get => m_OnLineSelection;
set => m_OnLineSelection = value;
}
/// <summary>
/// Event delegate triggered when pointer is over a link.
/// </summary>
public LinkSelectionEvent onLinkSelection
{
get => m_OnLinkSelection;
set => m_OnLinkSelection = value;
}
private void Awake()
{
// Get a reference to the text component.
m_TextComponent = gameObject.GetComponent<TMP_Text>();
// Get a reference to the camera rendering the text taking into consideration the text component type.
if (m_TextComponent.GetType() == typeof(TextMeshProUGUI))
{
m_Canvas = gameObject.GetComponentInParent<Canvas>();
if (m_Canvas != null)
{
if (m_Canvas.renderMode == RenderMode.ScreenSpaceOverlay)
m_Camera = null;
else
m_Camera = m_Canvas.worldCamera;
}
}
else
{
m_Camera = Camera.main;
}
}
private void LateUpdate()
{
if (TMP_TextUtilities.IsIntersectingRectTransform(m_TextComponent.rectTransform, Input.mousePosition,
m_Camera))
{
#region Example of Character or Sprite Selection
var charIndex =
TMP_TextUtilities.FindIntersectingCharacter(m_TextComponent, Input.mousePosition, m_Camera, true);
if (charIndex != -1 && charIndex != m_lastCharIndex)
{
m_lastCharIndex = charIndex;
var elementType = m_TextComponent.textInfo.characterInfo[charIndex].elementType;
// Send event to any event listeners depending on whether it is a character or sprite.
if (elementType == TMP_TextElementType.Character)
SendOnCharacterSelection(m_TextComponent.textInfo.characterInfo[charIndex].character,
charIndex);
else if (elementType == TMP_TextElementType.Sprite)
SendOnSpriteSelection(m_TextComponent.textInfo.characterInfo[charIndex].character, charIndex);
}
#endregion
#region Example of Word Selection
// Check if Mouse intersects any words and if so assign a random color to that word.
var wordIndex = TMP_TextUtilities.FindIntersectingWord(m_TextComponent, Input.mousePosition, m_Camera);
if (wordIndex != -1 && wordIndex != m_lastWordIndex)
{
m_lastWordIndex = wordIndex;
// Get the information about the selected word.
var wInfo = m_TextComponent.textInfo.wordInfo[wordIndex];
// Send the event to any listeners.
SendOnWordSelection(wInfo.GetWord(), wInfo.firstCharacterIndex, wInfo.characterCount);
}
#endregion
#region Example of Line Selection
// Check if Mouse intersects any words and if so assign a random color to that word.
var lineIndex = TMP_TextUtilities.FindIntersectingLine(m_TextComponent, Input.mousePosition, m_Camera);
if (lineIndex != -1 && lineIndex != m_lastLineIndex)
{
m_lastLineIndex = lineIndex;
// Get the information about the selected word.
var lineInfo = m_TextComponent.textInfo.lineInfo[lineIndex];
// Send the event to any listeners.
var buffer = new char[lineInfo.characterCount];
for (var i = 0;
i < lineInfo.characterCount && i < m_TextComponent.textInfo.characterInfo.Length;
i++)
buffer[i] = m_TextComponent.textInfo.characterInfo[i + lineInfo.firstCharacterIndex].character;
var lineText = new string(buffer);
SendOnLineSelection(lineText, lineInfo.firstCharacterIndex, lineInfo.characterCount);
}
#endregion
#region Example of Link Handling
// Check if mouse intersects with any links.
var linkIndex = TMP_TextUtilities.FindIntersectingLink(m_TextComponent, Input.mousePosition, m_Camera);
// Handle new Link selection.
if (linkIndex != -1 && linkIndex != m_selectedLink)
{
m_selectedLink = linkIndex;
// Get information about the link.
var linkInfo = m_TextComponent.textInfo.linkInfo[linkIndex];
// Send the event to any listeners.
SendOnLinkSelection(linkInfo.GetLinkID(), linkInfo.GetLinkText(), linkIndex);
}
#endregion
}
else
{
// Reset all selections given we are hovering outside the text container bounds.
m_selectedLink = -1;
m_lastCharIndex = -1;
m_lastWordIndex = -1;
m_lastLineIndex = -1;
}
}
public void OnPointerEnter(PointerEventData eventData)
{
//Debug.Log("OnPointerEnter()");
}
public void OnPointerExit(PointerEventData eventData)
{
//Debug.Log("OnPointerExit()");
}
private void SendOnCharacterSelection(char character, int characterIndex)
{
if (onCharacterSelection != null)
onCharacterSelection.Invoke(character, characterIndex);
}
private void SendOnSpriteSelection(char character, int characterIndex)
{
if (onSpriteSelection != null)
onSpriteSelection.Invoke(character, characterIndex);
}
private void SendOnWordSelection(string word, int charIndex, int length)
{
if (onWordSelection != null)
onWordSelection.Invoke(word, charIndex, length);
}
private void SendOnLineSelection(string line, int charIndex, int length)
{
if (onLineSelection != null)
onLineSelection.Invoke(line, charIndex, length);
}
private void SendOnLinkSelection(string linkID, string linkText, int linkIndex)
{
if (onLinkSelection != null)
onLinkSelection.Invoke(linkID, linkText, linkIndex);
}
[Serializable]
public class CharacterSelectionEvent : UnityEvent<char, int>
{
}
[Serializable]
public class SpriteSelectionEvent : UnityEvent<char, int>
{
}
[Serializable]
public class WordSelectionEvent : UnityEvent<string, int, int>
{
}
[Serializable]
public class LineSelectionEvent : UnityEvent<string, int, int>
{
}
[Serializable]
public class LinkSelectionEvent : UnityEvent<string, string, int>
{
}
}
}

View File

@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: 1312ae25639a4bae8e25ae223209cc50
timeCreated: 1452811039
licenseType: Pro
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,701 @@
using System;
using UnityEditor;
using UnityEngine;
namespace TMPro.Examples
{
public class TMP_TextInfoDebugTool : MonoBehaviour
{
// Since this script is used for debugging, we exclude it from builds.
// TODO: Rework this script to make it into an editor utility.
#if UNITY_EDITOR
public bool ShowCharacters;
public bool ShowWords;
public bool ShowLinks;
public bool ShowLines;
public bool ShowMeshBounds;
public bool ShowTextBounds;
[Space(10)] [TextArea(2, 2)] public string ObjectStats;
[SerializeField] private TMP_Text m_TextComponent;
private Transform m_Transform;
private TMP_TextInfo m_TextInfo;
private float m_ScaleMultiplier;
private float m_HandleSize;
private void OnDrawGizmos()
{
if (m_TextComponent == null)
{
m_TextComponent = GetComponent<TMP_Text>();
if (m_TextComponent == null)
return;
}
m_Transform = m_TextComponent.transform;
// Get a reference to the text object's textInfo
m_TextInfo = m_TextComponent.textInfo;
// Update Text Statistics
ObjectStats = "Characters: " + m_TextInfo.characterCount + " Words: " + m_TextInfo.wordCount +
" Spaces: " + m_TextInfo.spaceCount + " Sprites: " + m_TextInfo.spriteCount +
" Links: " + m_TextInfo.linkCount
+ "\nLines: " + m_TextInfo.lineCount + " Pages: " + m_TextInfo.pageCount;
// Get the handle size for drawing the various
m_ScaleMultiplier = m_TextComponent.GetType() == typeof(TextMeshPro) ? 1 : 0.1f;
m_HandleSize = HandleUtility.GetHandleSize(m_Transform.position) * m_ScaleMultiplier;
// Draw line metrics
#region Draw Lines
if (ShowLines)
DrawLineBounds();
#endregion
// Draw word metrics
#region Draw Words
if (ShowWords)
DrawWordBounds();
#endregion
// Draw character metrics
#region Draw Characters
if (ShowCharacters)
DrawCharactersBounds();
#endregion
// Draw Quads around each of the words
#region Draw Links
if (ShowLinks)
DrawLinkBounds();
#endregion
// Draw Quad around the bounds of the text
#region Draw Bounds
if (ShowMeshBounds)
DrawBounds();
#endregion
// Draw Quad around the rendered region of the text.
#region Draw Text Bounds
if (ShowTextBounds)
DrawTextBounds();
#endregion
}
/// <summary>
/// Method to draw a rectangle around each character.
/// </summary>
/// <param name="text"></param>
private void DrawCharactersBounds()
{
var characterCount = m_TextInfo.characterCount;
for (var i = 0; i < characterCount; i++)
{
// Draw visible as well as invisible characters
var characterInfo = m_TextInfo.characterInfo[i];
var isCharacterVisible = i < m_TextComponent.maxVisibleCharacters &&
characterInfo.lineNumber < m_TextComponent.maxVisibleLines &&
i >= m_TextComponent.firstVisibleCharacter;
if (m_TextComponent.overflowMode == TextOverflowModes.Page)
isCharacterVisible = isCharacterVisible &&
characterInfo.pageNumber + 1 == m_TextComponent.pageToDisplay;
if (!isCharacterVisible)
continue;
float dottedLineSize = 6;
// Get Bottom Left and Top Right position of the current character
var bottomLeft = m_Transform.TransformPoint(characterInfo.bottomLeft);
var topLeft =
m_Transform.TransformPoint(new Vector3(characterInfo.topLeft.x, characterInfo.topLeft.y, 0));
var topRight = m_Transform.TransformPoint(characterInfo.topRight);
var bottomRight =
m_Transform.TransformPoint(new Vector3(characterInfo.bottomRight.x, characterInfo.bottomRight.y,
0));
// Draw character bounds
if (characterInfo.isVisible)
{
var color = Color.green;
DrawDottedRectangle(bottomLeft, topRight, color);
}
else
{
var color = Color.grey;
var whiteSpaceAdvance = Math.Abs(characterInfo.origin - characterInfo.xAdvance) > 0.01f
? characterInfo.xAdvance
: characterInfo.origin + (characterInfo.ascender - characterInfo.descender) * 0.03f;
DrawDottedRectangle(
m_Transform.TransformPoint(new Vector3(characterInfo.origin, characterInfo.descender, 0)),
m_Transform.TransformPoint(new Vector3(whiteSpaceAdvance, characterInfo.ascender, 0)), color,
4);
}
var origin = characterInfo.origin;
var advance = characterInfo.xAdvance;
var ascentline = characterInfo.ascender;
var baseline = characterInfo.baseLine;
var descentline = characterInfo.descender;
//Draw Ascent line
var ascentlineStart = m_Transform.TransformPoint(new Vector3(origin, ascentline, 0));
var ascentlineEnd = m_Transform.TransformPoint(new Vector3(advance, ascentline, 0));
Handles.color = Color.cyan;
Handles.DrawDottedLine(ascentlineStart, ascentlineEnd, dottedLineSize);
// Draw Cap Height & Mean line
var capline = characterInfo.fontAsset == null
? 0
: baseline + characterInfo.fontAsset.faceInfo.capLine * characterInfo.scale;
var capHeightStart =
new Vector3(topLeft.x, m_Transform.TransformPoint(new Vector3(0, capline, 0)).y, 0);
var capHeightEnd = new Vector3(topRight.x, m_Transform.TransformPoint(new Vector3(0, capline, 0)).y, 0);
var meanline = characterInfo.fontAsset == null
? 0
: baseline + characterInfo.fontAsset.faceInfo.meanLine * characterInfo.scale;
var meanlineStart =
new Vector3(topLeft.x, m_Transform.TransformPoint(new Vector3(0, meanline, 0)).y, 0);
var meanlineEnd = new Vector3(topRight.x, m_Transform.TransformPoint(new Vector3(0, meanline, 0)).y, 0);
if (characterInfo.isVisible)
{
// Cap line
Handles.color = Color.cyan;
Handles.DrawDottedLine(capHeightStart, capHeightEnd, dottedLineSize);
// Mean line
Handles.color = Color.cyan;
Handles.DrawDottedLine(meanlineStart, meanlineEnd, dottedLineSize);
}
//Draw Base line
var baselineStart = m_Transform.TransformPoint(new Vector3(origin, baseline, 0));
var baselineEnd = m_Transform.TransformPoint(new Vector3(advance, baseline, 0));
Handles.color = Color.cyan;
Handles.DrawDottedLine(baselineStart, baselineEnd, dottedLineSize);
//Draw Descent line
var descentlineStart = m_Transform.TransformPoint(new Vector3(origin, descentline, 0));
var descentlineEnd = m_Transform.TransformPoint(new Vector3(advance, descentline, 0));
Handles.color = Color.cyan;
Handles.DrawDottedLine(descentlineStart, descentlineEnd, dottedLineSize);
// Draw Origin
var originPosition = m_Transform.TransformPoint(new Vector3(origin, baseline, 0));
DrawCrosshair(originPosition, 0.05f / m_ScaleMultiplier, Color.cyan);
// Draw Horizontal Advance
var advancePosition = m_Transform.TransformPoint(new Vector3(advance, baseline, 0));
DrawSquare(advancePosition, 0.025f / m_ScaleMultiplier, Color.yellow);
DrawCrosshair(advancePosition, 0.0125f / m_ScaleMultiplier, Color.yellow);
// Draw text labels for metrics
if (m_HandleSize < 0.5f)
{
var style = new GUIStyle(GUI.skin.GetStyle("Label"));
style.normal.textColor = new Color(0.6f, 0.6f, 0.6f, 1.0f);
style.fontSize = 12;
style.fixedWidth = 200;
style.fixedHeight = 20;
Vector3 labelPosition;
var center = (origin + advance) / 2;
//float baselineMetrics = 0;
//float ascentlineMetrics = ascentline - baseline;
//float caplineMetrics = capline - baseline;
//float meanlineMetrics = meanline - baseline;
//float descentlineMetrics = descentline - baseline;
// Ascent Line
labelPosition = m_Transform.TransformPoint(new Vector3(center, ascentline, 0));
style.alignment = TextAnchor.UpperCenter;
Handles.Label(labelPosition, "Ascent Line", style);
//Handles.Label(labelPosition, "Ascent Line (" + ascentlineMetrics.ToString("f3") + ")" , style);
// Base Line
labelPosition = m_Transform.TransformPoint(new Vector3(center, baseline, 0));
Handles.Label(labelPosition, "Base Line", style);
//Handles.Label(labelPosition, "Base Line (" + baselineMetrics.ToString("f3") + ")" , style);
// Descent line
labelPosition = m_Transform.TransformPoint(new Vector3(center, descentline, 0));
Handles.Label(labelPosition, "Descent Line", style);
//Handles.Label(labelPosition, "Descent Line (" + descentlineMetrics.ToString("f3") + ")" , style);
if (characterInfo.isVisible)
{
// Cap Line
labelPosition = m_Transform.TransformPoint(new Vector3(center, capline, 0));
style.alignment = TextAnchor.UpperCenter;
Handles.Label(labelPosition, "Cap Line", style);
//Handles.Label(labelPosition, "Cap Line (" + caplineMetrics.ToString("f3") + ")" , style);
// Mean Line
labelPosition = m_Transform.TransformPoint(new Vector3(center, meanline, 0));
style.alignment = TextAnchor.UpperCenter;
Handles.Label(labelPosition, "Mean Line", style);
//Handles.Label(labelPosition, "Mean Line (" + ascentlineMetrics.ToString("f3") + ")" , style);
// Origin
labelPosition = m_Transform.TransformPoint(new Vector3(origin, baseline, 0));
style.alignment = TextAnchor.UpperRight;
Handles.Label(labelPosition, "Origin ", style);
// Advance
labelPosition = m_Transform.TransformPoint(new Vector3(advance, baseline, 0));
style.alignment = TextAnchor.UpperLeft;
Handles.Label(labelPosition, " Advance", style);
}
}
}
}
/// <summary>
/// Method to draw rectangles around each word of the text.
/// </summary>
/// <param name="text"></param>
private void DrawWordBounds()
{
for (var i = 0; i < m_TextInfo.wordCount; i++)
{
var wInfo = m_TextInfo.wordInfo[i];
var isBeginRegion = false;
var bottomLeft = Vector3.zero;
var topLeft = Vector3.zero;
var bottomRight = Vector3.zero;
var topRight = Vector3.zero;
var maxAscender = -Mathf.Infinity;
var minDescender = Mathf.Infinity;
var wordColor = Color.green;
// Iterate through each character of the word
for (var j = 0; j < wInfo.characterCount; j++)
{
var characterIndex = wInfo.firstCharacterIndex + j;
var currentCharInfo = m_TextInfo.characterInfo[characterIndex];
var currentLine = currentCharInfo.lineNumber;
var isCharacterVisible = characterIndex > m_TextComponent.maxVisibleCharacters ||
currentCharInfo.lineNumber > m_TextComponent.maxVisibleLines ||
(m_TextComponent.overflowMode == TextOverflowModes.Page &&
currentCharInfo.pageNumber + 1 != m_TextComponent.pageToDisplay)
? false
: true;
// Track Max Ascender and Min Descender
maxAscender = Mathf.Max(maxAscender, currentCharInfo.ascender);
minDescender = Mathf.Min(minDescender, currentCharInfo.descender);
if (isBeginRegion == false && isCharacterVisible)
{
isBeginRegion = true;
bottomLeft = new Vector3(currentCharInfo.bottomLeft.x, currentCharInfo.descender, 0);
topLeft = new Vector3(currentCharInfo.bottomLeft.x, currentCharInfo.ascender, 0);
//Debug.Log("Start Word Region at [" + currentCharInfo.character + "]");
// If Word is one character
if (wInfo.characterCount == 1)
{
isBeginRegion = false;
topLeft = m_Transform.TransformPoint(new Vector3(topLeft.x, maxAscender, 0));
bottomLeft = m_Transform.TransformPoint(new Vector3(bottomLeft.x, minDescender, 0));
bottomRight =
m_Transform.TransformPoint(new Vector3(currentCharInfo.topRight.x, minDescender, 0));
topRight = m_Transform.TransformPoint(new Vector3(currentCharInfo.topRight.x, maxAscender,
0));
// Draw Region
DrawRectangle(bottomLeft, topLeft, topRight, bottomRight, wordColor);
//Debug.Log("End Word Region at [" + currentCharInfo.character + "]");
}
}
// Last Character of Word
if (isBeginRegion && j == wInfo.characterCount - 1)
{
isBeginRegion = false;
topLeft = m_Transform.TransformPoint(new Vector3(topLeft.x, maxAscender, 0));
bottomLeft = m_Transform.TransformPoint(new Vector3(bottomLeft.x, minDescender, 0));
bottomRight =
m_Transform.TransformPoint(new Vector3(currentCharInfo.topRight.x, minDescender, 0));
topRight = m_Transform.TransformPoint(new Vector3(currentCharInfo.topRight.x, maxAscender, 0));
// Draw Region
DrawRectangle(bottomLeft, topLeft, topRight, bottomRight, wordColor);
//Debug.Log("End Word Region at [" + currentCharInfo.character + "]");
}
// If Word is split on more than one line.
else if (isBeginRegion && currentLine != m_TextInfo.characterInfo[characterIndex + 1].lineNumber)
{
isBeginRegion = false;
topLeft = m_Transform.TransformPoint(new Vector3(topLeft.x, maxAscender, 0));
bottomLeft = m_Transform.TransformPoint(new Vector3(bottomLeft.x, minDescender, 0));
bottomRight =
m_Transform.TransformPoint(new Vector3(currentCharInfo.topRight.x, minDescender, 0));
topRight = m_Transform.TransformPoint(new Vector3(currentCharInfo.topRight.x, maxAscender, 0));
// Draw Region
DrawRectangle(bottomLeft, topLeft, topRight, bottomRight, wordColor);
//Debug.Log("End Word Region at [" + currentCharInfo.character + "]");
maxAscender = -Mathf.Infinity;
minDescender = Mathf.Infinity;
}
}
//Debug.Log(wInfo.GetWord(m_TextMeshPro.textInfo.characterInfo));
}
}
/// <summary>
/// Draw rectangle around each of the links contained in the text.
/// </summary>
/// <param name="text"></param>
private void DrawLinkBounds()
{
var textInfo = m_TextComponent.textInfo;
for (var i = 0; i < textInfo.linkCount; i++)
{
var linkInfo = textInfo.linkInfo[i];
var isBeginRegion = false;
var bottomLeft = Vector3.zero;
var topLeft = Vector3.zero;
var bottomRight = Vector3.zero;
var topRight = Vector3.zero;
var maxAscender = -Mathf.Infinity;
var minDescender = Mathf.Infinity;
Color32 linkColor = Color.cyan;
// Iterate through each character of the link text
for (var j = 0; j < linkInfo.linkTextLength; j++)
{
var characterIndex = linkInfo.linkTextfirstCharacterIndex + j;
var currentCharInfo = textInfo.characterInfo[characterIndex];
var currentLine = currentCharInfo.lineNumber;
var isCharacterVisible = characterIndex > m_TextComponent.maxVisibleCharacters ||
currentCharInfo.lineNumber > m_TextComponent.maxVisibleLines ||
(m_TextComponent.overflowMode == TextOverflowModes.Page &&
currentCharInfo.pageNumber + 1 != m_TextComponent.pageToDisplay)
? false
: true;
// Track Max Ascender and Min Descender
maxAscender = Mathf.Max(maxAscender, currentCharInfo.ascender);
minDescender = Mathf.Min(minDescender, currentCharInfo.descender);
if (isBeginRegion == false && isCharacterVisible)
{
isBeginRegion = true;
bottomLeft = new Vector3(currentCharInfo.bottomLeft.x, currentCharInfo.descender, 0);
topLeft = new Vector3(currentCharInfo.bottomLeft.x, currentCharInfo.ascender, 0);
//Debug.Log("Start Word Region at [" + currentCharInfo.character + "]");
// If Link is one character
if (linkInfo.linkTextLength == 1)
{
isBeginRegion = false;
topLeft = m_Transform.TransformPoint(new Vector3(topLeft.x, maxAscender, 0));
bottomLeft = m_Transform.TransformPoint(new Vector3(bottomLeft.x, minDescender, 0));
bottomRight =
m_Transform.TransformPoint(new Vector3(currentCharInfo.topRight.x, minDescender, 0));
topRight = m_Transform.TransformPoint(new Vector3(currentCharInfo.topRight.x, maxAscender,
0));
// Draw Region
DrawRectangle(bottomLeft, topLeft, topRight, bottomRight, linkColor);
//Debug.Log("End Word Region at [" + currentCharInfo.character + "]");
}
}
// Last Character of Link
if (isBeginRegion && j == linkInfo.linkTextLength - 1)
{
isBeginRegion = false;
topLeft = m_Transform.TransformPoint(new Vector3(topLeft.x, maxAscender, 0));
bottomLeft = m_Transform.TransformPoint(new Vector3(bottomLeft.x, minDescender, 0));
bottomRight =
m_Transform.TransformPoint(new Vector3(currentCharInfo.topRight.x, minDescender, 0));
topRight = m_Transform.TransformPoint(new Vector3(currentCharInfo.topRight.x, maxAscender, 0));
// Draw Region
DrawRectangle(bottomLeft, topLeft, topRight, bottomRight, linkColor);
//Debug.Log("End Word Region at [" + currentCharInfo.character + "]");
}
// If Link is split on more than one line.
else if (isBeginRegion && currentLine != textInfo.characterInfo[characterIndex + 1].lineNumber)
{
isBeginRegion = false;
topLeft = m_Transform.TransformPoint(new Vector3(topLeft.x, maxAscender, 0));
bottomLeft = m_Transform.TransformPoint(new Vector3(bottomLeft.x, minDescender, 0));
bottomRight =
m_Transform.TransformPoint(new Vector3(currentCharInfo.topRight.x, minDescender, 0));
topRight = m_Transform.TransformPoint(new Vector3(currentCharInfo.topRight.x, maxAscender, 0));
// Draw Region
DrawRectangle(bottomLeft, topLeft, topRight, bottomRight, linkColor);
maxAscender = -Mathf.Infinity;
minDescender = Mathf.Infinity;
//Debug.Log("End Word Region at [" + currentCharInfo.character + "]");
}
}
//Debug.Log(wInfo.GetWord(m_TextMeshPro.textInfo.characterInfo));
}
}
/// <summary>
/// Draw Rectangles around each lines of the text.
/// </summary>
/// <param name="text"></param>
private void DrawLineBounds()
{
var lineCount = m_TextInfo.lineCount;
for (var i = 0; i < lineCount; i++)
{
var lineInfo = m_TextInfo.lineInfo[i];
var firstCharacterInfo = m_TextInfo.characterInfo[lineInfo.firstCharacterIndex];
var lastCharacterInfo = m_TextInfo.characterInfo[lineInfo.lastCharacterIndex];
var isLineVisible = (lineInfo.characterCount == 1 && (firstCharacterInfo.character == 10 ||
firstCharacterInfo.character == 11 ||
firstCharacterInfo.character == 0x2028 ||
firstCharacterInfo.character == 0x2029)) ||
i > m_TextComponent.maxVisibleLines ||
(m_TextComponent.overflowMode == TextOverflowModes.Page &&
firstCharacterInfo.pageNumber + 1 != m_TextComponent.pageToDisplay)
? false
: true;
if (!isLineVisible) continue;
var lineBottomLeft = firstCharacterInfo.bottomLeft.x;
var lineTopRight = lastCharacterInfo.topRight.x;
var ascentline = lineInfo.ascender;
var baseline = lineInfo.baseline;
var descentline = lineInfo.descender;
float dottedLineSize = 12;
// Draw line extents
DrawDottedRectangle(m_Transform.TransformPoint(lineInfo.lineExtents.min),
m_Transform.TransformPoint(lineInfo.lineExtents.max), Color.green, 4);
// Draw Ascent line
var ascentlineStart = m_Transform.TransformPoint(new Vector3(lineBottomLeft, ascentline, 0));
var ascentlineEnd = m_Transform.TransformPoint(new Vector3(lineTopRight, ascentline, 0));
Handles.color = Color.yellow;
Handles.DrawDottedLine(ascentlineStart, ascentlineEnd, dottedLineSize);
// Draw Base line
var baseLineStart = m_Transform.TransformPoint(new Vector3(lineBottomLeft, baseline, 0));
var baseLineEnd = m_Transform.TransformPoint(new Vector3(lineTopRight, baseline, 0));
Handles.color = Color.yellow;
Handles.DrawDottedLine(baseLineStart, baseLineEnd, dottedLineSize);
// Draw Descent line
var descentLineStart = m_Transform.TransformPoint(new Vector3(lineBottomLeft, descentline, 0));
var descentLineEnd = m_Transform.TransformPoint(new Vector3(lineTopRight, descentline, 0));
Handles.color = Color.yellow;
Handles.DrawDottedLine(descentLineStart, descentLineEnd, dottedLineSize);
// Draw text labels for metrics
if (m_HandleSize < 1.0f)
{
var style = new GUIStyle();
style.normal.textColor = new Color(0.8f, 0.8f, 0.8f, 1.0f);
style.fontSize = 12;
style.fixedWidth = 200;
style.fixedHeight = 20;
Vector3 labelPosition;
// Ascent Line
labelPosition = m_Transform.TransformPoint(new Vector3(lineBottomLeft, ascentline, 0));
style.padding = new RectOffset(0, 10, 0, 5);
style.alignment = TextAnchor.MiddleRight;
Handles.Label(labelPosition, "Ascent Line", style);
// Base Line
labelPosition = m_Transform.TransformPoint(new Vector3(lineBottomLeft, baseline, 0));
Handles.Label(labelPosition, "Base Line", style);
// Descent line
labelPosition = m_Transform.TransformPoint(new Vector3(lineBottomLeft, descentline, 0));
Handles.Label(labelPosition, "Descent Line", style);
}
}
}
/// <summary>
/// Draw Rectangle around the bounds of the text object.
/// </summary>
private void DrawBounds()
{
var meshBounds = m_TextComponent.bounds;
// Get Bottom Left and Top Right position of each word
var bottomLeft = m_TextComponent.transform.position + meshBounds.min;
var topRight = m_TextComponent.transform.position + meshBounds.max;
DrawRectangle(bottomLeft, topRight, new Color(1, 0.5f, 0));
}
private void DrawTextBounds()
{
var textBounds = m_TextComponent.textBounds;
var bottomLeft = m_TextComponent.transform.position + (textBounds.center - textBounds.extents);
var topRight = m_TextComponent.transform.position + (textBounds.center + textBounds.extents);
DrawRectangle(bottomLeft, topRight, new Color(0f, 0.5f, 0.5f));
}
// Draw Rectangles
private void DrawRectangle(Vector3 BL, Vector3 TR, Color color)
{
Gizmos.color = color;
Gizmos.DrawLine(new Vector3(BL.x, BL.y, 0), new Vector3(BL.x, TR.y, 0));
Gizmos.DrawLine(new Vector3(BL.x, TR.y, 0), new Vector3(TR.x, TR.y, 0));
Gizmos.DrawLine(new Vector3(TR.x, TR.y, 0), new Vector3(TR.x, BL.y, 0));
Gizmos.DrawLine(new Vector3(TR.x, BL.y, 0), new Vector3(BL.x, BL.y, 0));
}
private void DrawDottedRectangle(Vector3 bottomLeft, Vector3 topRight, Color color, float size = 5.0f)
{
Handles.color = color;
Handles.DrawDottedLine(bottomLeft, new Vector3(bottomLeft.x, topRight.y, bottomLeft.z), size);
Handles.DrawDottedLine(new Vector3(bottomLeft.x, topRight.y, bottomLeft.z), topRight, size);
Handles.DrawDottedLine(topRight, new Vector3(topRight.x, bottomLeft.y, bottomLeft.z), size);
Handles.DrawDottedLine(new Vector3(topRight.x, bottomLeft.y, bottomLeft.z), bottomLeft, size);
}
private void DrawSolidRectangle(Vector3 bottomLeft, Vector3 topRight, Color color, float size = 5.0f)
{
Handles.color = color;
var rect = new Rect(bottomLeft, topRight - bottomLeft);
Handles.DrawSolidRectangleWithOutline(rect, color, Color.black);
}
private void DrawSquare(Vector3 position, float size, Color color)
{
Handles.color = color;
var bottomLeft = new Vector3(position.x - size, position.y - size, position.z);
var topLeft = new Vector3(position.x - size, position.y + size, position.z);
var topRight = new Vector3(position.x + size, position.y + size, position.z);
var bottomRight = new Vector3(position.x + size, position.y - size, position.z);
Handles.DrawLine(bottomLeft, topLeft);
Handles.DrawLine(topLeft, topRight);
Handles.DrawLine(topRight, bottomRight);
Handles.DrawLine(bottomRight, bottomLeft);
}
private void DrawCrosshair(Vector3 position, float size, Color color)
{
Handles.color = color;
Handles.DrawLine(new Vector3(position.x - size, position.y, position.z),
new Vector3(position.x + size, position.y, position.z));
Handles.DrawLine(new Vector3(position.x, position.y - size, position.z),
new Vector3(position.x, position.y + size, position.z));
}
// Draw Rectangles
private void DrawRectangle(Vector3 bl, Vector3 tl, Vector3 tr, Vector3 br, Color color)
{
Gizmos.color = color;
Gizmos.DrawLine(bl, tl);
Gizmos.DrawLine(tl, tr);
Gizmos.DrawLine(tr, br);
Gizmos.DrawLine(br, bl);
}
// Draw Rectangles
private void DrawDottedRectangle(Vector3 bl, Vector3 tl, Vector3 tr, Vector3 br, Color color)
{
var cam = Camera.current;
var dotSpacing = (cam.WorldToScreenPoint(br).x - cam.WorldToScreenPoint(bl).x) / 75f;
Handles.color = color;
Handles.DrawDottedLine(bl, tl, dotSpacing);
Handles.DrawDottedLine(tl, tr, dotSpacing);
Handles.DrawDottedLine(tr, br, dotSpacing);
Handles.DrawDottedLine(br, bl, dotSpacing);
}
#endif
}
}

View File

@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: 21256c5b62f346f18640dad779911e20
timeCreated: 1430348781
licenseType: Store
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,161 @@
using UnityEngine;
using UnityEngine.EventSystems;
namespace TMPro.Examples
{
public class TMP_TextSelector_A : MonoBehaviour, IPointerEnterHandler, IPointerExitHandler
{
private Camera m_Camera;
private bool m_isHoveringObject;
private int m_lastCharIndex = -1;
private int m_lastWordIndex = -1;
private int m_selectedLink = -1;
private TextMeshPro m_TextMeshPro;
private void Awake()
{
m_TextMeshPro = gameObject.GetComponent<TextMeshPro>();
m_Camera = Camera.main;
// Force generation of the text object so we have valid data to work with. This is needed since LateUpdate() will be called before the text object has a chance to generated when entering play mode.
m_TextMeshPro.ForceMeshUpdate();
}
private void LateUpdate()
{
m_isHoveringObject = false;
if (TMP_TextUtilities.IsIntersectingRectTransform(m_TextMeshPro.rectTransform, Input.mousePosition,
Camera.main)) m_isHoveringObject = true;
if (m_isHoveringObject)
{
#region Example of Character Selection
var charIndex =
TMP_TextUtilities.FindIntersectingCharacter(m_TextMeshPro, Input.mousePosition, Camera.main, true);
if (charIndex != -1 && charIndex != m_lastCharIndex &&
(Input.GetKey(KeyCode.LeftShift) || Input.GetKey(KeyCode.RightShift)))
{
//Debug.Log("[" + m_TextMeshPro.textInfo.characterInfo[charIndex].character + "] has been selected.");
m_lastCharIndex = charIndex;
var meshIndex = m_TextMeshPro.textInfo.characterInfo[charIndex].materialReferenceIndex;
var vertexIndex = m_TextMeshPro.textInfo.characterInfo[charIndex].vertexIndex;
var c = new Color32((byte)Random.Range(0, 255), (byte)Random.Range(0, 255),
(byte)Random.Range(0, 255), 255);
var vertexColors = m_TextMeshPro.textInfo.meshInfo[meshIndex].colors32;
vertexColors[vertexIndex + 0] = c;
vertexColors[vertexIndex + 1] = c;
vertexColors[vertexIndex + 2] = c;
vertexColors[vertexIndex + 3] = c;
//m_TextMeshPro.mesh.colors32 = vertexColors;
m_TextMeshPro.textInfo.meshInfo[meshIndex].mesh.colors32 = vertexColors;
}
#endregion
#region Example of Link Handling
// Check if mouse intersects with any links.
var linkIndex = TMP_TextUtilities.FindIntersectingLink(m_TextMeshPro, Input.mousePosition, m_Camera);
// Clear previous link selection if one existed.
if ((linkIndex == -1 && m_selectedLink != -1) || linkIndex != m_selectedLink)
//m_TextPopup_RectTransform.gameObject.SetActive(false);
m_selectedLink = -1;
// Handle new Link selection.
if (linkIndex != -1 && linkIndex != m_selectedLink)
{
m_selectedLink = linkIndex;
var linkInfo = m_TextMeshPro.textInfo.linkInfo[linkIndex];
// The following provides an example of how to access the link properties.
//Debug.Log("Link ID: \"" + linkInfo.GetLinkID() + "\" Link Text: \"" + linkInfo.GetLinkText() + "\""); // Example of how to retrieve the Link ID and Link Text.
Vector3 worldPointInRectangle;
RectTransformUtility.ScreenPointToWorldPointInRectangle(m_TextMeshPro.rectTransform,
Input.mousePosition, m_Camera, out worldPointInRectangle);
switch (linkInfo.GetLinkID())
{
case "id_01": // 100041637: // id_01
//m_TextPopup_RectTransform.position = worldPointInRectangle;
//m_TextPopup_RectTransform.gameObject.SetActive(true);
//m_TextPopup_TMPComponent.text = k_LinkText + " ID 01";
break;
case "id_02": // 100041638: // id_02
//m_TextPopup_RectTransform.position = worldPointInRectangle;
//m_TextPopup_RectTransform.gameObject.SetActive(true);
//m_TextPopup_TMPComponent.text = k_LinkText + " ID 02";
break;
}
}
#endregion
#region Example of Word Selection
// Check if Mouse intersects any words and if so assign a random color to that word.
var wordIndex = TMP_TextUtilities.FindIntersectingWord(m_TextMeshPro, Input.mousePosition, Camera.main);
if (wordIndex != -1 && wordIndex != m_lastWordIndex)
{
m_lastWordIndex = wordIndex;
var wInfo = m_TextMeshPro.textInfo.wordInfo[wordIndex];
var wordPOS = m_TextMeshPro.transform.TransformPoint(m_TextMeshPro.textInfo
.characterInfo[wInfo.firstCharacterIndex].bottomLeft);
wordPOS = Camera.main.WorldToScreenPoint(wordPOS);
//Debug.Log("Mouse Position: " + Input.mousePosition.ToString("f3") + " Word Position: " + wordPOS.ToString("f3"));
var vertexColors = m_TextMeshPro.textInfo.meshInfo[0].colors32;
var c = new Color32((byte)Random.Range(0, 255), (byte)Random.Range(0, 255),
(byte)Random.Range(0, 255), 255);
for (var i = 0; i < wInfo.characterCount; i++)
{
var vertexIndex = m_TextMeshPro.textInfo.characterInfo[wInfo.firstCharacterIndex + i]
.vertexIndex;
vertexColors[vertexIndex + 0] = c;
vertexColors[vertexIndex + 1] = c;
vertexColors[vertexIndex + 2] = c;
vertexColors[vertexIndex + 3] = c;
}
m_TextMeshPro.mesh.colors32 = vertexColors;
}
#endregion
}
}
public void OnPointerEnter(PointerEventData eventData)
{
Debug.Log("OnPointerEnter()");
m_isHoveringObject = true;
}
public void OnPointerExit(PointerEventData eventData)
{
Debug.Log("OnPointerExit()");
m_isHoveringObject = false;
}
}
}

View File

@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: 103e0a6a1d404693b9fb1a5173e0e979
timeCreated: 1452811039
licenseType: Pro
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,557 @@
using UnityEngine;
using UnityEngine.EventSystems;
#pragma warning disable 0618 // Disabled warning due to SetVertices being deprecated until new release with SetMesh() is available.
namespace TMPro.Examples
{
public class TMP_TextSelector_B : MonoBehaviour, IPointerEnterHandler, IPointerExitHandler, IPointerClickHandler,
IPointerUpHandler
{
private const string k_LinkText = "You have selected link <#ffff00>";
private const string k_WordText = "Word Index: <#ffff00>";
public RectTransform TextPopup_Prefab_01;
// Flags
private bool isHoveringObject;
private TMP_MeshInfo[] m_cachedMeshInfoVertexData;
private Camera m_Camera;
private Canvas m_Canvas;
private int m_lastIndex = -1;
private Matrix4x4 m_matrix;
private int m_selectedLink = -1;
private int m_selectedWord = -1;
private TextMeshProUGUI m_TextMeshPro;
private RectTransform m_TextPopup_RectTransform;
private TextMeshProUGUI m_TextPopup_TMPComponent;
private void Awake()
{
m_TextMeshPro = gameObject.GetComponent<TextMeshProUGUI>();
m_Canvas = gameObject.GetComponentInParent<Canvas>();
// Get a reference to the camera if Canvas Render Mode is not ScreenSpace Overlay.
if (m_Canvas.renderMode == RenderMode.ScreenSpaceOverlay)
m_Camera = null;
else
m_Camera = m_Canvas.worldCamera;
// Create pop-up text object which is used to show the link information.
m_TextPopup_RectTransform = Instantiate(TextPopup_Prefab_01);
m_TextPopup_RectTransform.SetParent(m_Canvas.transform, false);
m_TextPopup_TMPComponent = m_TextPopup_RectTransform.GetComponentInChildren<TextMeshProUGUI>();
m_TextPopup_RectTransform.gameObject.SetActive(false);
}
private void LateUpdate()
{
if (isHoveringObject)
{
// Check if Mouse Intersects any of the characters. If so, assign a random color.
#region Handle Character Selection
var charIndex =
TMP_TextUtilities.FindIntersectingCharacter(m_TextMeshPro, Input.mousePosition, m_Camera, true);
// Undo Swap and Vertex Attribute changes.
if (charIndex == -1 || charIndex != m_lastIndex)
{
RestoreCachedVertexAttributes(m_lastIndex);
m_lastIndex = -1;
}
if (charIndex != -1 && charIndex != m_lastIndex &&
(Input.GetKey(KeyCode.LeftShift) || Input.GetKey(KeyCode.RightShift)))
{
m_lastIndex = charIndex;
// Get the index of the material / sub text object used by this character.
var materialIndex = m_TextMeshPro.textInfo.characterInfo[charIndex].materialReferenceIndex;
// Get the index of the first vertex of the selected character.
var vertexIndex = m_TextMeshPro.textInfo.characterInfo[charIndex].vertexIndex;
// Get a reference to the vertices array.
var vertices = m_TextMeshPro.textInfo.meshInfo[materialIndex].vertices;
// Determine the center point of the character.
Vector2 charMidBasline = (vertices[vertexIndex + 0] + vertices[vertexIndex + 2]) / 2;
// Need to translate all 4 vertices of the character to aligned with middle of character / baseline.
// This is needed so the matrix TRS is applied at the origin for each character.
Vector3 offset = charMidBasline;
// Translate the character to the middle baseline.
vertices[vertexIndex + 0] = vertices[vertexIndex + 0] - offset;
vertices[vertexIndex + 1] = vertices[vertexIndex + 1] - offset;
vertices[vertexIndex + 2] = vertices[vertexIndex + 2] - offset;
vertices[vertexIndex + 3] = vertices[vertexIndex + 3] - offset;
var zoomFactor = 1.5f;
// Setup the Matrix for the scale change.
m_matrix = Matrix4x4.TRS(Vector3.zero, Quaternion.identity, Vector3.one * zoomFactor);
// Apply Matrix operation on the given character.
vertices[vertexIndex + 0] = m_matrix.MultiplyPoint3x4(vertices[vertexIndex + 0]);
vertices[vertexIndex + 1] = m_matrix.MultiplyPoint3x4(vertices[vertexIndex + 1]);
vertices[vertexIndex + 2] = m_matrix.MultiplyPoint3x4(vertices[vertexIndex + 2]);
vertices[vertexIndex + 3] = m_matrix.MultiplyPoint3x4(vertices[vertexIndex + 3]);
// Translate the character back to its original position.
vertices[vertexIndex + 0] = vertices[vertexIndex + 0] + offset;
vertices[vertexIndex + 1] = vertices[vertexIndex + 1] + offset;
vertices[vertexIndex + 2] = vertices[vertexIndex + 2] + offset;
vertices[vertexIndex + 3] = vertices[vertexIndex + 3] + offset;
// Change Vertex Colors of the highlighted character
var c = new Color32(255, 255, 192, 255);
// Get a reference to the vertex color
var vertexColors = m_TextMeshPro.textInfo.meshInfo[materialIndex].colors32;
vertexColors[vertexIndex + 0] = c;
vertexColors[vertexIndex + 1] = c;
vertexColors[vertexIndex + 2] = c;
vertexColors[vertexIndex + 3] = c;
// Get a reference to the meshInfo of the selected character.
var meshInfo = m_TextMeshPro.textInfo.meshInfo[materialIndex];
// Get the index of the last character's vertex attributes.
var lastVertexIndex = vertices.Length - 4;
// Swap the current character's vertex attributes with those of the last element in the vertex attribute arrays.
// We do this to make sure this character is rendered last and over other characters.
meshInfo.SwapVertexData(vertexIndex, lastVertexIndex);
// Need to update the appropriate
m_TextMeshPro.UpdateVertexData(TMP_VertexDataUpdateFlags.All);
}
#endregion
#region Word Selection Handling
//Check if Mouse intersects any words and if so assign a random color to that word.
var wordIndex = TMP_TextUtilities.FindIntersectingWord(m_TextMeshPro, Input.mousePosition, m_Camera);
// Clear previous word selection.
if (m_TextPopup_RectTransform != null && m_selectedWord != -1 &&
(wordIndex == -1 || wordIndex != m_selectedWord))
{
var wInfo = m_TextMeshPro.textInfo.wordInfo[m_selectedWord];
// Iterate through each of the characters of the word.
for (var i = 0; i < wInfo.characterCount; i++)
{
var characterIndex = wInfo.firstCharacterIndex + i;
// Get the index of the material / sub text object used by this character.
var meshIndex = m_TextMeshPro.textInfo.characterInfo[characterIndex].materialReferenceIndex;
// Get the index of the first vertex of this character.
var vertexIndex = m_TextMeshPro.textInfo.characterInfo[characterIndex].vertexIndex;
// Get a reference to the vertex color
var vertexColors = m_TextMeshPro.textInfo.meshInfo[meshIndex].colors32;
var c = vertexColors[vertexIndex + 0].Tint(1.33333f);
vertexColors[vertexIndex + 0] = c;
vertexColors[vertexIndex + 1] = c;
vertexColors[vertexIndex + 2] = c;
vertexColors[vertexIndex + 3] = c;
}
// Update Geometry
m_TextMeshPro.UpdateVertexData(TMP_VertexDataUpdateFlags.All);
m_selectedWord = -1;
}
// Word Selection Handling
if (wordIndex != -1 && wordIndex != m_selectedWord &&
!(Input.GetKey(KeyCode.LeftShift) || Input.GetKey(KeyCode.RightShift)))
{
m_selectedWord = wordIndex;
var wInfo = m_TextMeshPro.textInfo.wordInfo[wordIndex];
// Iterate through each of the characters of the word.
for (var i = 0; i < wInfo.characterCount; i++)
{
var characterIndex = wInfo.firstCharacterIndex + i;
// Get the index of the material / sub text object used by this character.
var meshIndex = m_TextMeshPro.textInfo.characterInfo[characterIndex].materialReferenceIndex;
var vertexIndex = m_TextMeshPro.textInfo.characterInfo[characterIndex].vertexIndex;
// Get a reference to the vertex color
var vertexColors = m_TextMeshPro.textInfo.meshInfo[meshIndex].colors32;
var c = vertexColors[vertexIndex + 0].Tint(0.75f);
vertexColors[vertexIndex + 0] = c;
vertexColors[vertexIndex + 1] = c;
vertexColors[vertexIndex + 2] = c;
vertexColors[vertexIndex + 3] = c;
}
// Update Geometry
m_TextMeshPro.UpdateVertexData(TMP_VertexDataUpdateFlags.All);
}
#endregion
#region Example of Link Handling
// Check if mouse intersects with any links.
var linkIndex = TMP_TextUtilities.FindIntersectingLink(m_TextMeshPro, Input.mousePosition, m_Camera);
// Clear previous link selection if one existed.
if ((linkIndex == -1 && m_selectedLink != -1) || linkIndex != m_selectedLink)
{
m_TextPopup_RectTransform.gameObject.SetActive(false);
m_selectedLink = -1;
}
// Handle new Link selection.
if (linkIndex != -1 && linkIndex != m_selectedLink)
{
m_selectedLink = linkIndex;
var linkInfo = m_TextMeshPro.textInfo.linkInfo[linkIndex];
// Debug.Log("Link ID: \"" + linkInfo.GetLinkID() + "\" Link Text: \"" + linkInfo.GetLinkText() + "\""); // Example of how to retrieve the Link ID and Link Text.
Vector3 worldPointInRectangle;
RectTransformUtility.ScreenPointToWorldPointInRectangle(m_TextMeshPro.rectTransform,
Input.mousePosition, m_Camera, out worldPointInRectangle);
switch (linkInfo.GetLinkID())
{
case "id_01": // 100041637: // id_01
m_TextPopup_RectTransform.position = worldPointInRectangle;
m_TextPopup_RectTransform.gameObject.SetActive(true);
m_TextPopup_TMPComponent.text = k_LinkText + " ID 01";
break;
case "id_02": // 100041638: // id_02
m_TextPopup_RectTransform.position = worldPointInRectangle;
m_TextPopup_RectTransform.gameObject.SetActive(true);
m_TextPopup_TMPComponent.text = k_LinkText + " ID 02";
break;
}
}
#endregion
}
else
{
// Restore any character that may have been modified
if (m_lastIndex != -1)
{
RestoreCachedVertexAttributes(m_lastIndex);
m_lastIndex = -1;
}
}
}
private void OnEnable()
{
// Subscribe to event fired when text object has been regenerated.
TMPro_EventManager.TEXT_CHANGED_EVENT.Add(ON_TEXT_CHANGED);
}
private void OnDisable()
{
// UnSubscribe to event fired when text object has been regenerated.
TMPro_EventManager.TEXT_CHANGED_EVENT.Remove(ON_TEXT_CHANGED);
}
public void OnPointerClick(PointerEventData eventData)
{
//Debug.Log("Click at POS: " + eventData.position + " World POS: " + eventData.worldPosition);
// Check if Mouse Intersects any of the characters. If so, assign a random color.
#region Character Selection Handling
/*
int charIndex = TMP_TextUtilities.FindIntersectingCharacter(m_TextMeshPro, Input.mousePosition, m_Camera, true);
if (charIndex != -1 && charIndex != m_lastIndex)
{
//Debug.Log("Character [" + m_TextMeshPro.textInfo.characterInfo[index].character + "] was selected at POS: " + eventData.position);
m_lastIndex = charIndex;
Color32 c = new Color32((byte)Random.Range(0, 255), (byte)Random.Range(0, 255), (byte)Random.Range(0, 255), 255);
int vertexIndex = m_TextMeshPro.textInfo.characterInfo[charIndex].vertexIndex;
UIVertex[] uiVertices = m_TextMeshPro.textInfo.meshInfo.uiVertices;
uiVertices[vertexIndex + 0].color = c;
uiVertices[vertexIndex + 1].color = c;
uiVertices[vertexIndex + 2].color = c;
uiVertices[vertexIndex + 3].color = c;
m_TextMeshPro.canvasRenderer.SetVertices(uiVertices, uiVertices.Length);
}
*/
#endregion
#region Word Selection Handling
//Check if Mouse intersects any words and if so assign a random color to that word.
/*
int wordIndex = TMP_TextUtilities.FindIntersectingWord(m_TextMeshPro, Input.mousePosition, m_Camera);
// Clear previous word selection.
if (m_TextPopup_RectTransform != null && m_selectedWord != -1 && (wordIndex == -1 || wordIndex != m_selectedWord))
{
TMP_WordInfo wInfo = m_TextMeshPro.textInfo.wordInfo[m_selectedWord];
// Get a reference to the uiVertices array.
UIVertex[] uiVertices = m_TextMeshPro.textInfo.meshInfo.uiVertices;
// Iterate through each of the characters of the word.
for (int i = 0; i < wInfo.characterCount; i++)
{
int vertexIndex = m_TextMeshPro.textInfo.characterInfo[wInfo.firstCharacterIndex + i].vertexIndex;
Color32 c = uiVertices[vertexIndex + 0].color.Tint(1.33333f);
uiVertices[vertexIndex + 0].color = c;
uiVertices[vertexIndex + 1].color = c;
uiVertices[vertexIndex + 2].color = c;
uiVertices[vertexIndex + 3].color = c;
}
m_TextMeshPro.canvasRenderer.SetVertices(uiVertices, uiVertices.Length);
m_selectedWord = -1;
}
// Handle word selection
if (wordIndex != -1 && wordIndex != m_selectedWord)
{
m_selectedWord = wordIndex;
TMP_WordInfo wInfo = m_TextMeshPro.textInfo.wordInfo[wordIndex];
// Get a reference to the uiVertices array.
UIVertex[] uiVertices = m_TextMeshPro.textInfo.meshInfo.uiVertices;
// Iterate through each of the characters of the word.
for (int i = 0; i < wInfo.characterCount; i++)
{
int vertexIndex = m_TextMeshPro.textInfo.characterInfo[wInfo.firstCharacterIndex + i].vertexIndex;
Color32 c = uiVertices[vertexIndex + 0].color.Tint(0.75f);
uiVertices[vertexIndex + 0].color = c;
uiVertices[vertexIndex + 1].color = c;
uiVertices[vertexIndex + 2].color = c;
uiVertices[vertexIndex + 3].color = c;
}
m_TextMeshPro.canvasRenderer.SetVertices(uiVertices, uiVertices.Length);
}
*/
#endregion
#region Link Selection Handling
/*
// Check if Mouse intersects any words and if so assign a random color to that word.
int linkIndex = TMP_TextUtilities.FindIntersectingLink(m_TextMeshPro, Input.mousePosition, m_Camera);
if (linkIndex != -1)
{
TMP_LinkInfo linkInfo = m_TextMeshPro.textInfo.linkInfo[linkIndex];
int linkHashCode = linkInfo.hashCode;
//Debug.Log(TMP_TextUtilities.GetSimpleHashCode("id_02"));
switch (linkHashCode)
{
case 291445: // id_01
if (m_LinkObject01 == null)
m_LinkObject01 = Instantiate(Link_01_Prefab);
else
{
m_LinkObject01.gameObject.SetActive(true);
}
break;
case 291446: // id_02
break;
}
// Example of how to modify vertex attributes like colors
#region Vertex Attribute Modification Example
UIVertex[] uiVertices = m_TextMeshPro.textInfo.meshInfo.uiVertices;
Color32 c = new Color32((byte)Random.Range(0, 255), (byte)Random.Range(0, 255), (byte)Random.Range(0, 255), 255);
for (int i = 0; i < linkInfo.characterCount; i++)
{
TMP_CharacterInfo cInfo = m_TextMeshPro.textInfo.characterInfo[linkInfo.firstCharacterIndex + i];
if (!cInfo.isVisible) continue; // Skip invisible characters.
int vertexIndex = cInfo.vertexIndex;
uiVertices[vertexIndex + 0].color = c;
uiVertices[vertexIndex + 1].color = c;
uiVertices[vertexIndex + 2].color = c;
uiVertices[vertexIndex + 3].color = c;
}
m_TextMeshPro.canvasRenderer.SetVertices(uiVertices, uiVertices.Length);
#endregion
}
*/
#endregion
}
public void OnPointerEnter(PointerEventData eventData)
{
//Debug.Log("OnPointerEnter()");
isHoveringObject = true;
}
public void OnPointerExit(PointerEventData eventData)
{
//Debug.Log("OnPointerExit()");
isHoveringObject = false;
}
public void OnPointerUp(PointerEventData eventData)
{
//Debug.Log("OnPointerUp()");
}
private void ON_TEXT_CHANGED(Object obj)
{
if (obj == m_TextMeshPro)
// Update cached vertex data.
m_cachedMeshInfoVertexData = m_TextMeshPro.textInfo.CopyMeshInfoVertexData();
}
private void RestoreCachedVertexAttributes(int index)
{
if (index == -1 || index > m_TextMeshPro.textInfo.characterCount - 1) return;
// Get the index of the material / sub text object used by this character.
var materialIndex = m_TextMeshPro.textInfo.characterInfo[index].materialReferenceIndex;
// Get the index of the first vertex of the selected character.
var vertexIndex = m_TextMeshPro.textInfo.characterInfo[index].vertexIndex;
// Restore Vertices
// Get a reference to the cached / original vertices.
var src_vertices = m_cachedMeshInfoVertexData[materialIndex].vertices;
// Get a reference to the vertices that we need to replace.
var dst_vertices = m_TextMeshPro.textInfo.meshInfo[materialIndex].vertices;
// Restore / Copy vertices from source to destination
dst_vertices[vertexIndex + 0] = src_vertices[vertexIndex + 0];
dst_vertices[vertexIndex + 1] = src_vertices[vertexIndex + 1];
dst_vertices[vertexIndex + 2] = src_vertices[vertexIndex + 2];
dst_vertices[vertexIndex + 3] = src_vertices[vertexIndex + 3];
// Restore Vertex Colors
// Get a reference to the vertex colors we need to replace.
var dst_colors = m_TextMeshPro.textInfo.meshInfo[materialIndex].colors32;
// Get a reference to the cached / original vertex colors.
var src_colors = m_cachedMeshInfoVertexData[materialIndex].colors32;
// Copy the vertex colors from source to destination.
dst_colors[vertexIndex + 0] = src_colors[vertexIndex + 0];
dst_colors[vertexIndex + 1] = src_colors[vertexIndex + 1];
dst_colors[vertexIndex + 2] = src_colors[vertexIndex + 2];
dst_colors[vertexIndex + 3] = src_colors[vertexIndex + 3];
// Restore UV0S
// UVS0
var src_uv0s = m_cachedMeshInfoVertexData[materialIndex].uvs0;
var dst_uv0s = m_TextMeshPro.textInfo.meshInfo[materialIndex].uvs0;
dst_uv0s[vertexIndex + 0] = src_uv0s[vertexIndex + 0];
dst_uv0s[vertexIndex + 1] = src_uv0s[vertexIndex + 1];
dst_uv0s[vertexIndex + 2] = src_uv0s[vertexIndex + 2];
dst_uv0s[vertexIndex + 3] = src_uv0s[vertexIndex + 3];
// UVS2
var src_uv2s = m_cachedMeshInfoVertexData[materialIndex].uvs2;
var dst_uv2s = m_TextMeshPro.textInfo.meshInfo[materialIndex].uvs2;
dst_uv2s[vertexIndex + 0] = src_uv2s[vertexIndex + 0];
dst_uv2s[vertexIndex + 1] = src_uv2s[vertexIndex + 1];
dst_uv2s[vertexIndex + 2] = src_uv2s[vertexIndex + 2];
dst_uv2s[vertexIndex + 3] = src_uv2s[vertexIndex + 3];
// Restore last vertex attribute as we swapped it as well
var lastIndex = (src_vertices.Length / 4 - 1) * 4;
// Vertices
dst_vertices[lastIndex + 0] = src_vertices[lastIndex + 0];
dst_vertices[lastIndex + 1] = src_vertices[lastIndex + 1];
dst_vertices[lastIndex + 2] = src_vertices[lastIndex + 2];
dst_vertices[lastIndex + 3] = src_vertices[lastIndex + 3];
// Vertex Colors
src_colors = m_cachedMeshInfoVertexData[materialIndex].colors32;
dst_colors = m_TextMeshPro.textInfo.meshInfo[materialIndex].colors32;
dst_colors[lastIndex + 0] = src_colors[lastIndex + 0];
dst_colors[lastIndex + 1] = src_colors[lastIndex + 1];
dst_colors[lastIndex + 2] = src_colors[lastIndex + 2];
dst_colors[lastIndex + 3] = src_colors[lastIndex + 3];
// UVS0
src_uv0s = m_cachedMeshInfoVertexData[materialIndex].uvs0;
dst_uv0s = m_TextMeshPro.textInfo.meshInfo[materialIndex].uvs0;
dst_uv0s[lastIndex + 0] = src_uv0s[lastIndex + 0];
dst_uv0s[lastIndex + 1] = src_uv0s[lastIndex + 1];
dst_uv0s[lastIndex + 2] = src_uv0s[lastIndex + 2];
dst_uv0s[lastIndex + 3] = src_uv0s[lastIndex + 3];
// UVS2
src_uv2s = m_cachedMeshInfoVertexData[materialIndex].uvs2;
dst_uv2s = m_TextMeshPro.textInfo.meshInfo[materialIndex].uvs2;
dst_uv2s[lastIndex + 0] = src_uv2s[lastIndex + 0];
dst_uv2s[lastIndex + 1] = src_uv2s[lastIndex + 1];
dst_uv2s[lastIndex + 2] = src_uv2s[lastIndex + 2];
dst_uv2s[lastIndex + 3] = src_uv2s[lastIndex + 3];
// Need to update the appropriate
m_TextMeshPro.UpdateVertexData(TMP_VertexDataUpdateFlags.All);
}
}
}

View File

@ -0,0 +1,14 @@
fileFormatVersion: 2
guid: a05dcd8be7ec4ccbb35c26219884aa37
timeCreated: 1435531209
licenseType: Store
MonoImporter:
serializedVersion: 2
defaultReferences:
- TextPopup_Prefab_01: {fileID: 22450954, guid: b06f0e6c1dfa4356ac918da1bb32c603,
type: 2}
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,129 @@
using UnityEngine;
namespace TMPro.Examples
{
public class TMP_UiFrameRateCounter : MonoBehaviour
{
public enum FpsCounterAnchorPositions
{
TopLeft,
BottomLeft,
TopRight,
BottomRight
}
private const string fpsLabel = "{0:2}</color> <#8080ff>FPS \n<#FF8000>{1:2} <#8080ff>MS";
public float UpdateInterval = 5.0f;
public FpsCounterAnchorPositions AnchorPosition = FpsCounterAnchorPositions.TopRight;
private string htmlColorTag;
private FpsCounterAnchorPositions last_AnchorPosition;
private RectTransform m_frameCounter_transform;
private int m_Frames;
private float m_LastInterval;
private TextMeshProUGUI m_TextMeshPro;
private void Awake()
{
if (!enabled)
return;
Application.targetFrameRate = 1000;
var frameCounter = new GameObject("Frame Counter");
m_frameCounter_transform = frameCounter.AddComponent<RectTransform>();
m_frameCounter_transform.SetParent(transform, false);
m_TextMeshPro = frameCounter.AddComponent<TextMeshProUGUI>();
m_TextMeshPro.font = Resources.Load<TMP_FontAsset>("Fonts & Materials/LiberationSans SDF");
m_TextMeshPro.fontSharedMaterial =
Resources.Load<Material>("Fonts & Materials/LiberationSans SDF - Overlay");
m_TextMeshPro.enableWordWrapping = false;
m_TextMeshPro.fontSize = 36;
m_TextMeshPro.isOverlay = true;
Set_FrameCounter_Position(AnchorPosition);
last_AnchorPosition = AnchorPosition;
}
private void Start()
{
m_LastInterval = Time.realtimeSinceStartup;
m_Frames = 0;
}
private void Update()
{
if (AnchorPosition != last_AnchorPosition)
Set_FrameCounter_Position(AnchorPosition);
last_AnchorPosition = AnchorPosition;
m_Frames += 1;
var timeNow = Time.realtimeSinceStartup;
if (timeNow > m_LastInterval + UpdateInterval)
{
// display two fractional digits (f2 format)
var fps = m_Frames / (timeNow - m_LastInterval);
var ms = 1000.0f / Mathf.Max(fps, 0.00001f);
if (fps < 30)
htmlColorTag = "<color=yellow>";
else if (fps < 10)
htmlColorTag = "<color=red>";
else
htmlColorTag = "<color=green>";
m_TextMeshPro.SetText(htmlColorTag + fpsLabel, fps, ms);
m_Frames = 0;
m_LastInterval = timeNow;
}
}
private void Set_FrameCounter_Position(FpsCounterAnchorPositions anchor_position)
{
switch (anchor_position)
{
case FpsCounterAnchorPositions.TopLeft:
m_TextMeshPro.alignment = TextAlignmentOptions.TopLeft;
m_frameCounter_transform.pivot = new Vector2(0, 1);
m_frameCounter_transform.anchorMin = new Vector2(0.01f, 0.99f);
m_frameCounter_transform.anchorMax = new Vector2(0.01f, 0.99f);
m_frameCounter_transform.anchoredPosition = new Vector2(0, 1);
break;
case FpsCounterAnchorPositions.BottomLeft:
m_TextMeshPro.alignment = TextAlignmentOptions.BottomLeft;
m_frameCounter_transform.pivot = new Vector2(0, 0);
m_frameCounter_transform.anchorMin = new Vector2(0.01f, 0.01f);
m_frameCounter_transform.anchorMax = new Vector2(0.01f, 0.01f);
m_frameCounter_transform.anchoredPosition = new Vector2(0, 0);
break;
case FpsCounterAnchorPositions.TopRight:
m_TextMeshPro.alignment = TextAlignmentOptions.TopRight;
m_frameCounter_transform.pivot = new Vector2(1, 1);
m_frameCounter_transform.anchorMin = new Vector2(0.99f, 0.99f);
m_frameCounter_transform.anchorMax = new Vector2(0.99f, 0.99f);
m_frameCounter_transform.anchoredPosition = new Vector2(1, 1);
break;
case FpsCounterAnchorPositions.BottomRight:
m_TextMeshPro.alignment = TextAlignmentOptions.BottomRight;
m_frameCounter_transform.pivot = new Vector2(1, 0);
m_frameCounter_transform.anchorMin = new Vector2(0.99f, 0.01f);
m_frameCounter_transform.anchorMax = new Vector2(0.99f, 0.01f);
m_frameCounter_transform.anchoredPosition = new Vector2(1, 0);
break;
}
}
}
}

View File

@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: 24b0dc2d1d494adbbec1f4db26b4cf83
timeCreated: 1448607572
licenseType: Pro
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,84 @@
using UnityEngine;
namespace TMPro.Examples
{
public class TMPro_InstructionOverlay : MonoBehaviour
{
public enum FpsCounterAnchorPositions
{
TopLeft,
BottomLeft,
TopRight,
BottomRight
}
private const string instructions =
"Camera Control - <#ffff00>Shift + RMB\n</color>Zoom - <#ffff00>Mouse wheel.";
public FpsCounterAnchorPositions AnchorPosition = FpsCounterAnchorPositions.BottomLeft;
private Camera m_camera;
private Transform m_frameCounter_transform;
private TextContainer m_textContainer;
private TextMeshPro m_TextMeshPro;
//private FpsCounterAnchorPositions last_AnchorPosition;
private void Awake()
{
if (!enabled)
return;
m_camera = Camera.main;
var frameCounter = new GameObject("Frame Counter");
m_frameCounter_transform = frameCounter.transform;
m_frameCounter_transform.parent = m_camera.transform;
m_frameCounter_transform.localRotation = Quaternion.identity;
m_TextMeshPro = frameCounter.AddComponent<TextMeshPro>();
m_TextMeshPro.font = Resources.Load<TMP_FontAsset>("Fonts & Materials/LiberationSans SDF");
m_TextMeshPro.fontSharedMaterial =
Resources.Load<Material>("Fonts & Materials/LiberationSans SDF - Overlay");
m_TextMeshPro.fontSize = 30;
m_TextMeshPro.isOverlay = true;
m_textContainer = frameCounter.GetComponent<TextContainer>();
Set_FrameCounter_Position(AnchorPosition);
//last_AnchorPosition = AnchorPosition;
m_TextMeshPro.text = instructions;
}
private void Set_FrameCounter_Position(FpsCounterAnchorPositions anchor_position)
{
switch (anchor_position)
{
case FpsCounterAnchorPositions.TopLeft:
//m_TextMeshPro.anchor = AnchorPositions.TopLeft;
m_textContainer.anchorPosition = TextContainerAnchors.TopLeft;
m_frameCounter_transform.position = m_camera.ViewportToWorldPoint(new Vector3(0, 1, 100.0f));
break;
case FpsCounterAnchorPositions.BottomLeft:
//m_TextMeshPro.anchor = AnchorPositions.BottomLeft;
m_textContainer.anchorPosition = TextContainerAnchors.BottomLeft;
m_frameCounter_transform.position = m_camera.ViewportToWorldPoint(new Vector3(0, 0, 100.0f));
break;
case FpsCounterAnchorPositions.TopRight:
//m_TextMeshPro.anchor = AnchorPositions.TopRight;
m_textContainer.anchorPosition = TextContainerAnchors.TopRight;
m_frameCounter_transform.position = m_camera.ViewportToWorldPoint(new Vector3(1, 1, 100.0f));
break;
case FpsCounterAnchorPositions.BottomRight:
//m_TextMeshPro.anchor = AnchorPositions.BottomRight;
m_textContainer.anchorPosition = TextContainerAnchors.BottomRight;
m_frameCounter_transform.position = m_camera.ViewportToWorldPoint(new Vector3(1, 0, 100.0f));
break;
}
}
}
}

View File

@ -0,0 +1,10 @@
fileFormatVersion: 2
guid: c3c1afeda5e545e0b19add5373896d2e
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,78 @@
using System.Collections;
using UnityEngine;
namespace TMPro.Examples
{
public class TeleType : MonoBehaviour
{
//[Range(0, 100)]
//public int RevealSpeed = 50;
private readonly string label01 =
"Example <sprite=2> of using <sprite=7> <#ffa000>Graphics Inline</color> <sprite=5> with Text in <font=\"Bangers SDF\" material=\"Bangers SDF - Drop Shadow\">TextMesh<#40a0ff>Pro</color></font><sprite=0> and Unity<sprite=1>";
private readonly string label02 =
"Example <sprite=2> of using <sprite=7> <#ffa000>Graphics Inline</color> <sprite=5> with Text in <font=\"Bangers SDF\" material=\"Bangers SDF - Drop Shadow\">TextMesh<#40a0ff>Pro</color></font><sprite=0> and Unity<sprite=2>";
private TMP_Text m_textMeshPro;
private void Awake()
{
// Get Reference to TextMeshPro Component
m_textMeshPro = GetComponent<TMP_Text>();
m_textMeshPro.text = label01;
m_textMeshPro.enableWordWrapping = true;
m_textMeshPro.alignment = TextAlignmentOptions.Top;
//if (GetComponentInParent(typeof(Canvas)) as Canvas == null)
//{
// GameObject canvas = new GameObject("Canvas", typeof(Canvas));
// gameObject.transform.SetParent(canvas.transform);
// canvas.GetComponent<Canvas>().renderMode = RenderMode.ScreenSpaceOverlay;
// // Set RectTransform Size
// gameObject.GetComponent<RectTransform>().sizeDelta = new Vector2(500, 300);
// m_textMeshPro.fontSize = 48;
//}
}
private IEnumerator Start()
{
// Force and update of the mesh to get valid information.
m_textMeshPro.ForceMeshUpdate();
var totalVisibleCharacters =
m_textMeshPro.textInfo.characterCount; // Get # of Visible Character in text object
var counter = 0;
var visibleCount = 0;
while (true)
{
visibleCount = counter % (totalVisibleCharacters + 1);
m_textMeshPro.maxVisibleCharacters = visibleCount; // How many characters should TextMeshPro display?
// Once the last character has been revealed, wait 1.0 second and start over.
if (visibleCount >= totalVisibleCharacters)
{
yield return new WaitForSeconds(1.0f);
m_textMeshPro.text = label02;
yield return new WaitForSeconds(1.0f);
m_textMeshPro.text = label01;
yield return new WaitForSeconds(1.0f);
}
counter += 1;
yield return new WaitForSeconds(0.05f);
}
//Debug.Log("Done revealing the text.");
}
}
}

View File

@ -0,0 +1,10 @@
fileFormatVersion: 2
guid: e32c266ee6204b21a427753cb0694c81
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,117 @@
using System.Collections;
using UnityEngine;
namespace TMPro.Examples
{
public class TextConsoleSimulator : MonoBehaviour
{
private bool hasTextChanged;
private TMP_Text m_TextComponent;
private void Awake()
{
m_TextComponent = gameObject.GetComponent<TMP_Text>();
}
private void Start()
{
StartCoroutine(RevealCharacters(m_TextComponent));
//StartCoroutine(RevealWords(m_TextComponent));
}
private void OnEnable()
{
// Subscribe to event fired when text object has been regenerated.
TMPro_EventManager.TEXT_CHANGED_EVENT.Add(ON_TEXT_CHANGED);
}
private void OnDisable()
{
TMPro_EventManager.TEXT_CHANGED_EVENT.Remove(ON_TEXT_CHANGED);
}
// Event received when the text object has changed.
private void ON_TEXT_CHANGED(Object obj)
{
hasTextChanged = true;
}
/// <summary>
/// Method revealing the text one character at a time.
/// </summary>
/// <returns></returns>
private IEnumerator RevealCharacters(TMP_Text textComponent)
{
textComponent.ForceMeshUpdate();
var textInfo = textComponent.textInfo;
var totalVisibleCharacters = textInfo.characterCount; // Get # of Visible Character in text object
var visibleCount = 0;
while (true)
{
if (hasTextChanged)
{
totalVisibleCharacters = textInfo.characterCount; // Update visible character count.
hasTextChanged = false;
}
if (visibleCount > totalVisibleCharacters)
{
yield return new WaitForSeconds(1.0f);
visibleCount = 0;
}
textComponent.maxVisibleCharacters = visibleCount; // How many characters should TextMeshPro display?
visibleCount += 1;
yield return null;
}
}
/// <summary>
/// Method revealing the text one word at a time.
/// </summary>
/// <returns></returns>
private IEnumerator RevealWords(TMP_Text textComponent)
{
textComponent.ForceMeshUpdate();
var totalWordCount = textComponent.textInfo.wordCount;
var totalVisibleCharacters =
textComponent.textInfo.characterCount; // Get # of Visible Character in text object
var counter = 0;
var currentWord = 0;
var visibleCount = 0;
while (true)
{
currentWord = counter % (totalWordCount + 1);
// Get last character index for the current word.
if (currentWord == 0) // Display no words.
visibleCount = 0;
else if (currentWord < totalWordCount) // Display all other words with the exception of the last one.
visibleCount = textComponent.textInfo.wordInfo[currentWord - 1].lastCharacterIndex + 1;
else if (currentWord == totalWordCount) // Display last word and all remaining characters.
visibleCount = totalVisibleCharacters;
textComponent.maxVisibleCharacters = visibleCount; // How many characters should TextMeshPro display?
// Once the last character has been revealed, wait 1.0 second and start over.
if (visibleCount >= totalVisibleCharacters) yield return new WaitForSeconds(1.0f);
counter += 1;
yield return new WaitForSeconds(0.1f);
}
}
}
}

View File

@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: 43bcd35a1c0c40ccb6d472893fe2093f
timeCreated: 1435298333
licenseType: Store
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,220 @@
using System.Collections;
using UnityEngine;
namespace TMPro.Examples
{
public class TextMeshProFloatingText : MonoBehaviour
{
//private int m_frame = 0;
private static readonly WaitForEndOfFrame k_WaitForEndOfFrame = new();
private static readonly WaitForSeconds[] k_WaitForSecondsRandom =
{
new(0.05f), new(0.1f), new(0.15f), new(0.2f), new(0.25f),
new(0.3f), new(0.35f), new(0.4f), new(0.45f), new(0.5f),
new(0.55f), new(0.6f), new(0.65f), new(0.7f), new(0.75f),
new(0.8f), new(0.85f), new(0.9f), new(0.95f), new(1.0f)
};
public Font TheFont;
public int SpawnType;
public bool IsTextObjectScaleStatic;
private Vector3 lastPOS = Vector3.zero;
private Quaternion lastRotation = Quaternion.identity;
private Transform m_cameraTransform;
private GameObject m_floatingText;
private Transform m_floatingText_Transform;
private TextMesh m_textMesh;
private TextMeshPro m_textMeshPro;
private Transform m_transform;
private void Awake()
{
m_transform = transform;
m_floatingText = new GameObject(name + " floating text");
// Reference to Transform is lost when TMP component is added since it replaces it by a RectTransform.
//m_floatingText_Transform = m_floatingText.transform;
//m_floatingText_Transform.position = m_transform.position + new Vector3(0, 15f, 0);
m_cameraTransform = Camera.main.transform;
}
private void Start()
{
if (SpawnType == 0)
{
// TextMesh Pro Implementation
m_textMeshPro = m_floatingText.AddComponent<TextMeshPro>();
m_textMeshPro.rectTransform.sizeDelta = new Vector2(3, 3);
m_floatingText_Transform = m_floatingText.transform;
m_floatingText_Transform.position = m_transform.position + new Vector3(0, 15f, 0);
//m_textMeshPro.fontAsset = Resources.Load("Fonts & Materials/JOKERMAN SDF", typeof(TextMeshProFont)) as TextMeshProFont; // User should only provide a string to the resource.
//m_textMeshPro.fontSharedMaterial = Resources.Load("Fonts & Materials/LiberationSans SDF", typeof(Material)) as Material;
m_textMeshPro.alignment = TextAlignmentOptions.Center;
m_textMeshPro.color = new Color32((byte)Random.Range(0, 255), (byte)Random.Range(0, 255),
(byte)Random.Range(0, 255), 255);
m_textMeshPro.fontSize = 24;
//m_textMeshPro.enableExtraPadding = true;
//m_textMeshPro.enableShadows = false;
m_textMeshPro.enableKerning = false;
m_textMeshPro.text = string.Empty;
m_textMeshPro.isTextObjectScaleStatic = IsTextObjectScaleStatic;
StartCoroutine(DisplayTextMeshProFloatingText());
}
else if (SpawnType == 1)
{
//Debug.Log("Spawning TextMesh Objects.");
m_floatingText_Transform = m_floatingText.transform;
m_floatingText_Transform.position = m_transform.position + new Vector3(0, 15f, 0);
m_textMesh = m_floatingText.AddComponent<TextMesh>();
m_textMesh.font = Resources.Load<Font>("Fonts/ARIAL");
m_textMesh.GetComponent<Renderer>().sharedMaterial = m_textMesh.font.material;
m_textMesh.color = new Color32((byte)Random.Range(0, 255), (byte)Random.Range(0, 255),
(byte)Random.Range(0, 255), 255);
m_textMesh.anchor = TextAnchor.LowerCenter;
m_textMesh.fontSize = 24;
StartCoroutine(DisplayTextMeshFloatingText());
}
else if (SpawnType == 2)
{
}
}
//void Update()
//{
// if (SpawnType == 0)
// {
// m_textMeshPro.SetText("{0}", m_frame);
// }
// else
// {
// m_textMesh.text = m_frame.ToString();
// }
// m_frame = (m_frame + 1) % 1000;
//}
public IEnumerator DisplayTextMeshProFloatingText()
{
var CountDuration = 2.0f; // How long is the countdown alive.
var starting_Count = Random.Range(5f, 20f); // At what number is the counter starting at.
var current_Count = starting_Count;
var start_pos = m_floatingText_Transform.position;
Color32 start_color = m_textMeshPro.color;
float alpha = 255;
var int_counter = 0;
var fadeDuration = 3 / starting_Count * CountDuration;
while (current_Count > 0)
{
current_Count -= Time.deltaTime / CountDuration * starting_Count;
if (current_Count <= 3)
//Debug.Log("Fading Counter ... " + current_Count.ToString("f2"));
alpha = Mathf.Clamp(alpha - Time.deltaTime / fadeDuration * 255, 0, 255);
int_counter = (int)current_Count;
m_textMeshPro.text = int_counter.ToString();
//m_textMeshPro.SetText("{0}", (int)current_Count);
m_textMeshPro.color = new Color32(start_color.r, start_color.g, start_color.b, (byte)alpha);
// Move the floating text upward each update
m_floatingText_Transform.position += new Vector3(0, starting_Count * Time.deltaTime, 0);
// Align floating text perpendicular to Camera.
if (!lastPOS.Compare(m_cameraTransform.position, 1000) ||
!lastRotation.Compare(m_cameraTransform.rotation, 1000))
{
lastPOS = m_cameraTransform.position;
lastRotation = m_cameraTransform.rotation;
m_floatingText_Transform.rotation = lastRotation;
var dir = m_transform.position - lastPOS;
m_transform.forward = new Vector3(dir.x, 0, dir.z);
}
yield return k_WaitForEndOfFrame;
}
//Debug.Log("Done Counting down.");
yield return k_WaitForSecondsRandom[Random.Range(0, 19)];
m_floatingText_Transform.position = start_pos;
StartCoroutine(DisplayTextMeshProFloatingText());
}
public IEnumerator DisplayTextMeshFloatingText()
{
var CountDuration = 2.0f; // How long is the countdown alive.
var starting_Count = Random.Range(5f, 20f); // At what number is the counter starting at.
var current_Count = starting_Count;
var start_pos = m_floatingText_Transform.position;
Color32 start_color = m_textMesh.color;
float alpha = 255;
var int_counter = 0;
var fadeDuration = 3 / starting_Count * CountDuration;
while (current_Count > 0)
{
current_Count -= Time.deltaTime / CountDuration * starting_Count;
if (current_Count <= 3)
//Debug.Log("Fading Counter ... " + current_Count.ToString("f2"));
alpha = Mathf.Clamp(alpha - Time.deltaTime / fadeDuration * 255, 0, 255);
int_counter = (int)current_Count;
m_textMesh.text = int_counter.ToString();
//Debug.Log("Current Count:" + current_Count.ToString("f2"));
m_textMesh.color = new Color32(start_color.r, start_color.g, start_color.b, (byte)alpha);
// Move the floating text upward each update
m_floatingText_Transform.position += new Vector3(0, starting_Count * Time.deltaTime, 0);
// Align floating text perpendicular to Camera.
if (!lastPOS.Compare(m_cameraTransform.position, 1000) ||
!lastRotation.Compare(m_cameraTransform.rotation, 1000))
{
lastPOS = m_cameraTransform.position;
lastRotation = m_cameraTransform.rotation;
m_floatingText_Transform.rotation = lastRotation;
var dir = m_transform.position - lastPOS;
m_transform.forward = new Vector3(dir.x, 0, dir.z);
}
yield return k_WaitForEndOfFrame;
}
//Debug.Log("Done Counting down.");
yield return k_WaitForSecondsRandom[Random.Range(0, 20)];
m_floatingText_Transform.position = start_pos;
StartCoroutine(DisplayTextMeshFloatingText());
}
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: a4d4c76e63944cba8c7d00f56334b98c
MonoImporter:
serializedVersion: 2
defaultReferences:
- TheFont: {instanceID: 0}
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,68 @@
using UnityEngine;
namespace TMPro.Examples
{
public class TextMeshSpawner : MonoBehaviour
{
public int SpawnType;
public int NumberOfNPC = 12;
public Font TheFont;
private TextMeshProFloatingText floatingText_Script;
private void Awake()
{
}
private void Start()
{
for (var i = 0; i < NumberOfNPC; i++)
if (SpawnType == 0)
{
// TextMesh Pro Implementation
//go.transform.localScale = new Vector3(2, 2, 2);
var go = new GameObject(); //"NPC " + i);
go.transform.position = new Vector3(Random.Range(-95f, 95f), 0.5f, Random.Range(-95f, 95f));
//go.transform.position = new Vector3(0, 1.01f, 0);
//go.renderer.castShadows = false;
//go.renderer.receiveShadows = false;
//go.transform.rotation = Quaternion.Euler(0, Random.Range(0, 360), 0);
var textMeshPro = go.AddComponent<TextMeshPro>();
//textMeshPro.FontAsset = Resources.Load("Fonts & Materials/LiberationSans SDF", typeof(TextMeshProFont)) as TextMeshProFont;
//textMeshPro.anchor = AnchorPositions.Bottom;
textMeshPro.fontSize = 96;
textMeshPro.text = "!";
textMeshPro.color = new Color32(255, 255, 0, 255);
//textMeshPro.Text = "!";
// Spawn Floating Text
floatingText_Script = go.AddComponent<TextMeshProFloatingText>();
floatingText_Script.SpawnType = 0;
}
else
{
// TextMesh Implementation
var go = new GameObject(); //"NPC " + i);
go.transform.position = new Vector3(Random.Range(-95f, 95f), 0.5f, Random.Range(-95f, 95f));
//go.transform.position = new Vector3(0, 1.01f, 0);
var textMesh = go.AddComponent<TextMesh>();
textMesh.GetComponent<Renderer>().sharedMaterial = TheFont.material;
textMesh.font = TheFont;
textMesh.anchor = TextAnchor.LowerCenter;
textMesh.fontSize = 96;
textMesh.color = new Color32(255, 255, 0, 255);
textMesh.text = "!";
// Spawn Floating Text
floatingText_Script = go.AddComponent<TextMeshProFloatingText>();
floatingText_Script.SpawnType = 1;
}
}
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 76c11bbcfddf44e0ba17d6c2751c8d84
MonoImporter:
serializedVersion: 2
defaultReferences:
- TheFont: {instanceID: 0}
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,81 @@
using System.Collections;
using UnityEngine;
namespace TMPro.Examples
{
public class VertexColorCycler : MonoBehaviour
{
private TMP_Text m_TextComponent;
private void Awake()
{
m_TextComponent = GetComponent<TMP_Text>();
}
private void Start()
{
StartCoroutine(AnimateVertexColors());
}
/// <summary>
/// Method to animate vertex colors of a TMP Text object.
/// </summary>
/// <returns></returns>
private IEnumerator AnimateVertexColors()
{
// Force the text object to update right away so we can have geometry to modify right from the start.
m_TextComponent.ForceMeshUpdate();
var textInfo = m_TextComponent.textInfo;
var currentCharacter = 0;
Color32[] newVertexColors;
Color32 c0 = m_TextComponent.color;
while (true)
{
var characterCount = textInfo.characterCount;
// If No Characters then just yield and wait for some text to be added
if (characterCount == 0)
{
yield return new WaitForSeconds(0.25f);
continue;
}
// Get the index of the material used by the current character.
var materialIndex = textInfo.characterInfo[currentCharacter].materialReferenceIndex;
// Get the vertex colors of the mesh used by this text element (character or sprite).
newVertexColors = textInfo.meshInfo[materialIndex].colors32;
// Get the index of the first vertex used by this text element.
var vertexIndex = textInfo.characterInfo[currentCharacter].vertexIndex;
// Only change the vertex color if the text element is visible.
if (textInfo.characterInfo[currentCharacter].isVisible)
{
c0 = new Color32((byte)Random.Range(0, 255), (byte)Random.Range(0, 255), (byte)Random.Range(0, 255),
255);
newVertexColors[vertexIndex + 0] = c0;
newVertexColors[vertexIndex + 1] = c0;
newVertexColors[vertexIndex + 2] = c0;
newVertexColors[vertexIndex + 3] = c0;
// New function which pushes (all) updated vertex data to the appropriate meshes when using either the Mesh Renderer or CanvasRenderer.
m_TextComponent.UpdateVertexData(TMP_VertexDataUpdateFlags.Colors32);
// This last process could be done to only update the vertex data that has changed as opposed to all of the vertex data but it would require extra steps and knowing what type of renderer is used.
// These extra steps would be a performance optimization but it is unlikely that such optimization will be necessary.
}
currentCharacter = (currentCharacter + 1) % characterCount;
yield return new WaitForSeconds(0.05f);
}
}
}
}

View File

@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: 91b8ba3d52e041fab2d0e0f169855539
timeCreated: 1457047157
licenseType: Pro
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,176 @@
using System.Collections;
using UnityEngine;
namespace TMPro.Examples
{
public class VertexJitter : MonoBehaviour
{
public float AngleMultiplier = 1.0f;
public float SpeedMultiplier = 1.0f;
public float CurveScale = 1.0f;
private bool hasTextChanged;
private TMP_Text m_TextComponent;
private void Awake()
{
m_TextComponent = GetComponent<TMP_Text>();
}
private void Start()
{
StartCoroutine(AnimateVertexColors());
}
private void OnEnable()
{
// Subscribe to event fired when text object has been regenerated.
TMPro_EventManager.TEXT_CHANGED_EVENT.Add(ON_TEXT_CHANGED);
}
private void OnDisable()
{
TMPro_EventManager.TEXT_CHANGED_EVENT.Remove(ON_TEXT_CHANGED);
}
private void ON_TEXT_CHANGED(Object obj)
{
if (obj == m_TextComponent)
hasTextChanged = true;
}
/// <summary>
/// Method to animate vertex colors of a TMP Text object.
/// </summary>
/// <returns></returns>
private IEnumerator AnimateVertexColors()
{
// We force an update of the text object since it would only be updated at the end of the frame. Ie. before this code is executed on the first frame.
// Alternatively, we could yield and wait until the end of the frame when the text object will be generated.
m_TextComponent.ForceMeshUpdate();
var textInfo = m_TextComponent.textInfo;
Matrix4x4 matrix;
var loopCount = 0;
hasTextChanged = true;
// Create an Array which contains pre-computed Angle Ranges and Speeds for a bunch of characters.
var vertexAnim = new VertexAnim[1024];
for (var i = 0; i < 1024; i++)
{
vertexAnim[i].angleRange = Random.Range(10f, 25f);
vertexAnim[i].speed = Random.Range(1f, 3f);
}
// Cache the vertex data of the text object as the Jitter FX is applied to the original position of the characters.
var cachedMeshInfo = textInfo.CopyMeshInfoVertexData();
while (true)
{
// Get new copy of vertex data if the text has changed.
if (hasTextChanged)
{
// Update the copy of the vertex data for the text object.
cachedMeshInfo = textInfo.CopyMeshInfoVertexData();
hasTextChanged = false;
}
var characterCount = textInfo.characterCount;
// If No Characters then just yield and wait for some text to be added
if (characterCount == 0)
{
yield return new WaitForSeconds(0.25f);
continue;
}
for (var i = 0; i < characterCount; i++)
{
var charInfo = textInfo.characterInfo[i];
// Skip characters that are not visible and thus have no geometry to manipulate.
if (!charInfo.isVisible)
continue;
// Retrieve the pre-computed animation data for the given character.
var vertAnim = vertexAnim[i];
// Get the index of the material used by the current character.
var materialIndex = textInfo.characterInfo[i].materialReferenceIndex;
// Get the index of the first vertex used by this text element.
var vertexIndex = textInfo.characterInfo[i].vertexIndex;
// Get the cached vertices of the mesh used by this text element (character or sprite).
var sourceVertices = cachedMeshInfo[materialIndex].vertices;
// Determine the center point of each character at the baseline.
//Vector2 charMidBasline = new Vector2((sourceVertices[vertexIndex + 0].x + sourceVertices[vertexIndex + 2].x) / 2, charInfo.baseLine);
// Determine the center point of each character.
Vector2 charMidBasline = (sourceVertices[vertexIndex + 0] + sourceVertices[vertexIndex + 2]) / 2;
// Need to translate all 4 vertices of each quad to aligned with middle of character / baseline.
// This is needed so the matrix TRS is applied at the origin for each character.
Vector3 offset = charMidBasline;
var destinationVertices = textInfo.meshInfo[materialIndex].vertices;
destinationVertices[vertexIndex + 0] = sourceVertices[vertexIndex + 0] - offset;
destinationVertices[vertexIndex + 1] = sourceVertices[vertexIndex + 1] - offset;
destinationVertices[vertexIndex + 2] = sourceVertices[vertexIndex + 2] - offset;
destinationVertices[vertexIndex + 3] = sourceVertices[vertexIndex + 3] - offset;
vertAnim.angle = Mathf.SmoothStep(-vertAnim.angleRange, vertAnim.angleRange,
Mathf.PingPong(loopCount / 25f * vertAnim.speed, 1f));
var jitterOffset = new Vector3(Random.Range(-.25f, .25f), Random.Range(-.25f, .25f), 0);
matrix = Matrix4x4.TRS(jitterOffset * CurveScale,
Quaternion.Euler(0, 0, Random.Range(-5f, 5f) * AngleMultiplier), Vector3.one);
destinationVertices[vertexIndex + 0] =
matrix.MultiplyPoint3x4(destinationVertices[vertexIndex + 0]);
destinationVertices[vertexIndex + 1] =
matrix.MultiplyPoint3x4(destinationVertices[vertexIndex + 1]);
destinationVertices[vertexIndex + 2] =
matrix.MultiplyPoint3x4(destinationVertices[vertexIndex + 2]);
destinationVertices[vertexIndex + 3] =
matrix.MultiplyPoint3x4(destinationVertices[vertexIndex + 3]);
destinationVertices[vertexIndex + 0] += offset;
destinationVertices[vertexIndex + 1] += offset;
destinationVertices[vertexIndex + 2] += offset;
destinationVertices[vertexIndex + 3] += offset;
vertexAnim[i] = vertAnim;
}
// Push changes into meshes
for (var i = 0; i < textInfo.meshInfo.Length; i++)
{
textInfo.meshInfo[i].mesh.vertices = textInfo.meshInfo[i].vertices;
m_TextComponent.UpdateGeometry(textInfo.meshInfo[i].mesh, i);
}
loopCount += 1;
yield return new WaitForSeconds(0.1f);
}
}
/// <summary>
/// Structure to hold pre-computed animation data.
/// </summary>
private struct VertexAnim
{
public float angleRange;
public float angle;
public float speed;
}
}
}

View File

@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: 2ed57967c52645d390a89dcf8f61ba73
timeCreated: 1461286718
licenseType: Pro
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,161 @@
using System.Collections;
using UnityEngine;
namespace TMPro.Examples
{
public class VertexShakeA : MonoBehaviour
{
public float AngleMultiplier = 1.0f;
public float SpeedMultiplier = 1.0f;
public float ScaleMultiplier = 1.0f;
public float RotationMultiplier = 1.0f;
private bool hasTextChanged;
private TMP_Text m_TextComponent;
private void Awake()
{
m_TextComponent = GetComponent<TMP_Text>();
}
private void Start()
{
StartCoroutine(AnimateVertexColors());
}
private void OnEnable()
{
// Subscribe to event fired when text object has been regenerated.
TMPro_EventManager.TEXT_CHANGED_EVENT.Add(ON_TEXT_CHANGED);
}
private void OnDisable()
{
TMPro_EventManager.TEXT_CHANGED_EVENT.Remove(ON_TEXT_CHANGED);
}
private void ON_TEXT_CHANGED(Object obj)
{
if (obj = m_TextComponent)
hasTextChanged = true;
}
/// <summary>
/// Method to animate vertex colors of a TMP Text object.
/// </summary>
/// <returns></returns>
private IEnumerator AnimateVertexColors()
{
// We force an update of the text object since it would only be updated at the end of the frame. Ie. before this code is executed on the first frame.
// Alternatively, we could yield and wait until the end of the frame when the text object will be generated.
m_TextComponent.ForceMeshUpdate();
var textInfo = m_TextComponent.textInfo;
Matrix4x4 matrix;
var copyOfVertices = new Vector3[0][];
hasTextChanged = true;
while (true)
{
// Allocate new vertices
if (hasTextChanged)
{
if (copyOfVertices.Length < textInfo.meshInfo.Length)
copyOfVertices = new Vector3[textInfo.meshInfo.Length][];
for (var i = 0; i < textInfo.meshInfo.Length; i++)
{
var length = textInfo.meshInfo[i].vertices.Length;
copyOfVertices[i] = new Vector3[length];
}
hasTextChanged = false;
}
var characterCount = textInfo.characterCount;
// If No Characters then just yield and wait for some text to be added
if (characterCount == 0)
{
yield return new WaitForSeconds(0.25f);
continue;
}
var lineCount = textInfo.lineCount;
// Iterate through each line of the text.
for (var i = 0; i < lineCount; i++)
{
var first = textInfo.lineInfo[i].firstCharacterIndex;
var last = textInfo.lineInfo[i].lastCharacterIndex;
// Determine the center of each line
var centerOfLine =
(textInfo.characterInfo[first].bottomLeft + textInfo.characterInfo[last].topRight) / 2;
var rotation = Quaternion.Euler(0, 0, Random.Range(-0.25f, 0.25f) * RotationMultiplier);
// Iterate through each character of the line.
for (var j = first; j <= last; j++)
{
// Skip characters that are not visible and thus have no geometry to manipulate.
if (!textInfo.characterInfo[j].isVisible)
continue;
// Get the index of the material used by the current character.
var materialIndex = textInfo.characterInfo[j].materialReferenceIndex;
// Get the index of the first vertex used by this text element.
var vertexIndex = textInfo.characterInfo[j].vertexIndex;
// Get the vertices of the mesh used by this text element (character or sprite).
var sourceVertices = textInfo.meshInfo[materialIndex].vertices;
// Need to translate all 4 vertices of each quad to aligned with center of character.
// This is needed so the matrix TRS is applied at the origin for each character.
copyOfVertices[materialIndex][vertexIndex + 0] = sourceVertices[vertexIndex + 0] - centerOfLine;
copyOfVertices[materialIndex][vertexIndex + 1] = sourceVertices[vertexIndex + 1] - centerOfLine;
copyOfVertices[materialIndex][vertexIndex + 2] = sourceVertices[vertexIndex + 2] - centerOfLine;
copyOfVertices[materialIndex][vertexIndex + 3] = sourceVertices[vertexIndex + 3] - centerOfLine;
// Determine the random scale change for each character.
var randomScale = Random.Range(0.995f - 0.001f * ScaleMultiplier,
1.005f + 0.001f * ScaleMultiplier);
// Setup the matrix rotation.
matrix = Matrix4x4.TRS(Vector3.one, rotation, Vector3.one * randomScale);
// Apply the matrix TRS to the individual characters relative to the center of the current line.
copyOfVertices[materialIndex][vertexIndex + 0] =
matrix.MultiplyPoint3x4(copyOfVertices[materialIndex][vertexIndex + 0]);
copyOfVertices[materialIndex][vertexIndex + 1] =
matrix.MultiplyPoint3x4(copyOfVertices[materialIndex][vertexIndex + 1]);
copyOfVertices[materialIndex][vertexIndex + 2] =
matrix.MultiplyPoint3x4(copyOfVertices[materialIndex][vertexIndex + 2]);
copyOfVertices[materialIndex][vertexIndex + 3] =
matrix.MultiplyPoint3x4(copyOfVertices[materialIndex][vertexIndex + 3]);
// Revert the translation change.
copyOfVertices[materialIndex][vertexIndex + 0] += centerOfLine;
copyOfVertices[materialIndex][vertexIndex + 1] += centerOfLine;
copyOfVertices[materialIndex][vertexIndex + 2] += centerOfLine;
copyOfVertices[materialIndex][vertexIndex + 3] += centerOfLine;
}
}
// Push changes into meshes
for (var i = 0; i < textInfo.meshInfo.Length; i++)
{
textInfo.meshInfo[i].mesh.vertices = copyOfVertices[i];
m_TextComponent.UpdateGeometry(textInfo.meshInfo[i].mesh, i);
}
yield return new WaitForSeconds(0.1f);
}
}
}
}

View File

@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: f7cfa58e417a46ea8889989684c2522e
timeCreated: 1462089320
licenseType: Pro
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,188 @@
using System.Collections;
using UnityEngine;
namespace TMPro.Examples
{
public class VertexShakeB : MonoBehaviour
{
public float AngleMultiplier = 1.0f;
public float SpeedMultiplier = 1.0f;
public float CurveScale = 1.0f;
private bool hasTextChanged;
private TMP_Text m_TextComponent;
private void Awake()
{
m_TextComponent = GetComponent<TMP_Text>();
}
private void Start()
{
StartCoroutine(AnimateVertexColors());
}
private void OnEnable()
{
// Subscribe to event fired when text object has been regenerated.
TMPro_EventManager.TEXT_CHANGED_EVENT.Add(ON_TEXT_CHANGED);
}
private void OnDisable()
{
TMPro_EventManager.TEXT_CHANGED_EVENT.Remove(ON_TEXT_CHANGED);
}
private void ON_TEXT_CHANGED(Object obj)
{
if (obj = m_TextComponent)
hasTextChanged = true;
}
/// <summary>
/// Method to animate vertex colors of a TMP Text object.
/// </summary>
/// <returns></returns>
private IEnumerator AnimateVertexColors()
{
// We force an update of the text object since it would only be updated at the end of the frame. Ie. before this code is executed on the first frame.
// Alternatively, we could yield and wait until the end of the frame when the text object will be generated.
m_TextComponent.ForceMeshUpdate();
var textInfo = m_TextComponent.textInfo;
Matrix4x4 matrix;
var copyOfVertices = new Vector3[0][];
hasTextChanged = true;
while (true)
{
// Allocate new vertices
if (hasTextChanged)
{
if (copyOfVertices.Length < textInfo.meshInfo.Length)
copyOfVertices = new Vector3[textInfo.meshInfo.Length][];
for (var i = 0; i < textInfo.meshInfo.Length; i++)
{
var length = textInfo.meshInfo[i].vertices.Length;
copyOfVertices[i] = new Vector3[length];
}
hasTextChanged = false;
}
var characterCount = textInfo.characterCount;
// If No Characters then just yield and wait for some text to be added
if (characterCount == 0)
{
yield return new WaitForSeconds(0.25f);
continue;
}
var lineCount = textInfo.lineCount;
// Iterate through each line of the text.
for (var i = 0; i < lineCount; i++)
{
var first = textInfo.lineInfo[i].firstCharacterIndex;
var last = textInfo.lineInfo[i].lastCharacterIndex;
// Determine the center of each line
var centerOfLine =
(textInfo.characterInfo[first].bottomLeft + textInfo.characterInfo[last].topRight) / 2;
var rotation = Quaternion.Euler(0, 0, Random.Range(-0.25f, 0.25f));
// Iterate through each character of the line.
for (var j = first; j <= last; j++)
{
// Skip characters that are not visible and thus have no geometry to manipulate.
if (!textInfo.characterInfo[j].isVisible)
continue;
// Get the index of the material used by the current character.
var materialIndex = textInfo.characterInfo[j].materialReferenceIndex;
// Get the index of the first vertex used by this text element.
var vertexIndex = textInfo.characterInfo[j].vertexIndex;
// Get the vertices of the mesh used by this text element (character or sprite).
var sourceVertices = textInfo.meshInfo[materialIndex].vertices;
// Determine the center point of each character at the baseline.
var charCenter = (sourceVertices[vertexIndex + 0] + sourceVertices[vertexIndex + 2]) / 2;
// Need to translate all 4 vertices of each quad to aligned with center of character.
// This is needed so the matrix TRS is applied at the origin for each character.
copyOfVertices[materialIndex][vertexIndex + 0] = sourceVertices[vertexIndex + 0] - charCenter;
copyOfVertices[materialIndex][vertexIndex + 1] = sourceVertices[vertexIndex + 1] - charCenter;
copyOfVertices[materialIndex][vertexIndex + 2] = sourceVertices[vertexIndex + 2] - charCenter;
copyOfVertices[materialIndex][vertexIndex + 3] = sourceVertices[vertexIndex + 3] - charCenter;
// Determine the random scale change for each character.
var randomScale = Random.Range(0.95f, 1.05f);
// Setup the matrix for the scale change.
matrix = Matrix4x4.TRS(Vector3.one, Quaternion.identity, Vector3.one * randomScale);
// Apply the scale change relative to the center of each character.
copyOfVertices[materialIndex][vertexIndex + 0] =
matrix.MultiplyPoint3x4(copyOfVertices[materialIndex][vertexIndex + 0]);
copyOfVertices[materialIndex][vertexIndex + 1] =
matrix.MultiplyPoint3x4(copyOfVertices[materialIndex][vertexIndex + 1]);
copyOfVertices[materialIndex][vertexIndex + 2] =
matrix.MultiplyPoint3x4(copyOfVertices[materialIndex][vertexIndex + 2]);
copyOfVertices[materialIndex][vertexIndex + 3] =
matrix.MultiplyPoint3x4(copyOfVertices[materialIndex][vertexIndex + 3]);
// Revert the translation change.
copyOfVertices[materialIndex][vertexIndex + 0] += charCenter;
copyOfVertices[materialIndex][vertexIndex + 1] += charCenter;
copyOfVertices[materialIndex][vertexIndex + 2] += charCenter;
copyOfVertices[materialIndex][vertexIndex + 3] += charCenter;
// Need to translate all 4 vertices of each quad to aligned with the center of the line.
// This is needed so the matrix TRS is applied from the center of the line.
copyOfVertices[materialIndex][vertexIndex + 0] -= centerOfLine;
copyOfVertices[materialIndex][vertexIndex + 1] -= centerOfLine;
copyOfVertices[materialIndex][vertexIndex + 2] -= centerOfLine;
copyOfVertices[materialIndex][vertexIndex + 3] -= centerOfLine;
// Setup the matrix rotation.
matrix = Matrix4x4.TRS(Vector3.one, rotation, Vector3.one);
// Apply the matrix TRS to the individual characters relative to the center of the current line.
copyOfVertices[materialIndex][vertexIndex + 0] =
matrix.MultiplyPoint3x4(copyOfVertices[materialIndex][vertexIndex + 0]);
copyOfVertices[materialIndex][vertexIndex + 1] =
matrix.MultiplyPoint3x4(copyOfVertices[materialIndex][vertexIndex + 1]);
copyOfVertices[materialIndex][vertexIndex + 2] =
matrix.MultiplyPoint3x4(copyOfVertices[materialIndex][vertexIndex + 2]);
copyOfVertices[materialIndex][vertexIndex + 3] =
matrix.MultiplyPoint3x4(copyOfVertices[materialIndex][vertexIndex + 3]);
// Revert the translation change.
copyOfVertices[materialIndex][vertexIndex + 0] += centerOfLine;
copyOfVertices[materialIndex][vertexIndex + 1] += centerOfLine;
copyOfVertices[materialIndex][vertexIndex + 2] += centerOfLine;
copyOfVertices[materialIndex][vertexIndex + 3] += centerOfLine;
}
}
// Push changes into meshes
for (var i = 0; i < textInfo.meshInfo.Length; i++)
{
textInfo.meshInfo[i].mesh.vertices = copyOfVertices[i];
m_TextComponent.UpdateGeometry(textInfo.meshInfo[i].mesh, i);
}
yield return new WaitForSeconds(0.1f);
}
}
}
}

View File

@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: e4e0d9ccee5f4950be8979268c9014e0
timeCreated: 1462093319
licenseType: Pro
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,191 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
namespace TMPro.Examples
{
public class VertexZoom : MonoBehaviour
{
public float AngleMultiplier = 1.0f;
public float SpeedMultiplier = 1.0f;
public float CurveScale = 1.0f;
private bool hasTextChanged;
private TMP_Text m_TextComponent;
private void Awake()
{
m_TextComponent = GetComponent<TMP_Text>();
}
private void Start()
{
StartCoroutine(AnimateVertexColors());
}
private void OnEnable()
{
// Subscribe to event fired when text object has been regenerated.
TMPro_EventManager.TEXT_CHANGED_EVENT.Add(ON_TEXT_CHANGED);
}
private void OnDisable()
{
// UnSubscribe to event fired when text object has been regenerated.
TMPro_EventManager.TEXT_CHANGED_EVENT.Remove(ON_TEXT_CHANGED);
}
private void ON_TEXT_CHANGED(Object obj)
{
if (obj == m_TextComponent)
hasTextChanged = true;
}
/// <summary>
/// Method to animate vertex colors of a TMP Text object.
/// </summary>
/// <returns></returns>
private IEnumerator AnimateVertexColors()
{
// We force an update of the text object since it would only be updated at the end of the frame. Ie. before this code is executed on the first frame.
// Alternatively, we could yield and wait until the end of the frame when the text object will be generated.
m_TextComponent.ForceMeshUpdate();
var textInfo = m_TextComponent.textInfo;
Matrix4x4 matrix;
var cachedMeshInfoVertexData = textInfo.CopyMeshInfoVertexData();
// Allocations for sorting of the modified scales
var modifiedCharScale = new List<float>();
var scaleSortingOrder = new List<int>();
hasTextChanged = true;
while (true)
{
// Allocate new vertices
if (hasTextChanged)
{
// Get updated vertex data
cachedMeshInfoVertexData = textInfo.CopyMeshInfoVertexData();
hasTextChanged = false;
}
var characterCount = textInfo.characterCount;
// If No Characters then just yield and wait for some text to be added
if (characterCount == 0)
{
yield return new WaitForSeconds(0.25f);
continue;
}
// Clear list of character scales
modifiedCharScale.Clear();
scaleSortingOrder.Clear();
for (var i = 0; i < characterCount; i++)
{
var charInfo = textInfo.characterInfo[i];
// Skip characters that are not visible and thus have no geometry to manipulate.
if (!charInfo.isVisible)
continue;
// Get the index of the material used by the current character.
var materialIndex = textInfo.characterInfo[i].materialReferenceIndex;
// Get the index of the first vertex used by this text element.
var vertexIndex = textInfo.characterInfo[i].vertexIndex;
// Get the cached vertices of the mesh used by this text element (character or sprite).
var sourceVertices = cachedMeshInfoVertexData[materialIndex].vertices;
// Determine the center point of each character at the baseline.
//Vector2 charMidBasline = new Vector2((sourceVertices[vertexIndex + 0].x + sourceVertices[vertexIndex + 2].x) / 2, charInfo.baseLine);
// Determine the center point of each character.
Vector2 charMidBasline = (sourceVertices[vertexIndex + 0] + sourceVertices[vertexIndex + 2]) / 2;
// Need to translate all 4 vertices of each quad to aligned with middle of character / baseline.
// This is needed so the matrix TRS is applied at the origin for each character.
Vector3 offset = charMidBasline;
var destinationVertices = textInfo.meshInfo[materialIndex].vertices;
destinationVertices[vertexIndex + 0] = sourceVertices[vertexIndex + 0] - offset;
destinationVertices[vertexIndex + 1] = sourceVertices[vertexIndex + 1] - offset;
destinationVertices[vertexIndex + 2] = sourceVertices[vertexIndex + 2] - offset;
destinationVertices[vertexIndex + 3] = sourceVertices[vertexIndex + 3] - offset;
//Vector3 jitterOffset = new Vector3(Random.Range(-.25f, .25f), Random.Range(-.25f, .25f), 0);
// Determine the random scale change for each character.
var randomScale = Random.Range(1f, 1.5f);
// Add modified scale and index
modifiedCharScale.Add(randomScale);
scaleSortingOrder.Add(modifiedCharScale.Count - 1);
// Setup the matrix for the scale change.
//matrix = Matrix4x4.TRS(jitterOffset, Quaternion.Euler(0, 0, Random.Range(-5f, 5f)), Vector3.one * randomScale);
matrix = Matrix4x4.TRS(new Vector3(0, 0, 0), Quaternion.identity, Vector3.one * randomScale);
destinationVertices[vertexIndex + 0] =
matrix.MultiplyPoint3x4(destinationVertices[vertexIndex + 0]);
destinationVertices[vertexIndex + 1] =
matrix.MultiplyPoint3x4(destinationVertices[vertexIndex + 1]);
destinationVertices[vertexIndex + 2] =
matrix.MultiplyPoint3x4(destinationVertices[vertexIndex + 2]);
destinationVertices[vertexIndex + 3] =
matrix.MultiplyPoint3x4(destinationVertices[vertexIndex + 3]);
destinationVertices[vertexIndex + 0] += offset;
destinationVertices[vertexIndex + 1] += offset;
destinationVertices[vertexIndex + 2] += offset;
destinationVertices[vertexIndex + 3] += offset;
// Restore Source UVS which have been modified by the sorting
var sourceUVs0 = cachedMeshInfoVertexData[materialIndex].uvs0;
var destinationUVs0 = textInfo.meshInfo[materialIndex].uvs0;
destinationUVs0[vertexIndex + 0] = sourceUVs0[vertexIndex + 0];
destinationUVs0[vertexIndex + 1] = sourceUVs0[vertexIndex + 1];
destinationUVs0[vertexIndex + 2] = sourceUVs0[vertexIndex + 2];
destinationUVs0[vertexIndex + 3] = sourceUVs0[vertexIndex + 3];
// Restore Source Vertex Colors
var sourceColors32 = cachedMeshInfoVertexData[materialIndex].colors32;
var destinationColors32 = textInfo.meshInfo[materialIndex].colors32;
destinationColors32[vertexIndex + 0] = sourceColors32[vertexIndex + 0];
destinationColors32[vertexIndex + 1] = sourceColors32[vertexIndex + 1];
destinationColors32[vertexIndex + 2] = sourceColors32[vertexIndex + 2];
destinationColors32[vertexIndex + 3] = sourceColors32[vertexIndex + 3];
}
// Push changes into meshes
for (var i = 0; i < textInfo.meshInfo.Length; i++)
{
//// Sort Quads based modified scale
scaleSortingOrder.Sort((a, b) => modifiedCharScale[a].CompareTo(modifiedCharScale[b]));
textInfo.meshInfo[i].SortGeometry(scaleSortingOrder);
// Updated modified vertex attributes
textInfo.meshInfo[i].mesh.vertices = textInfo.meshInfo[i].vertices;
textInfo.meshInfo[i].mesh.uv = textInfo.meshInfo[i].uvs0;
textInfo.meshInfo[i].mesh.colors32 = textInfo.meshInfo[i].colors32;
m_TextComponent.UpdateGeometry(textInfo.meshInfo[i].mesh, i);
}
yield return new WaitForSeconds(0.1f);
}
}
}
}

View File

@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: 52ec835d14bd486f900952b77698b7eb
timeCreated: 1466280202
licenseType: Pro
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,148 @@
using System.Collections;
using UnityEngine;
namespace TMPro.Examples
{
public class WarpTextExample : MonoBehaviour
{
public AnimationCurve VertexCurve = new(new Keyframe(0, 0), new Keyframe(0.25f, 2.0f), new Keyframe(0.5f, 0),
new Keyframe(0.75f, 2.0f), new Keyframe(1, 0f));
public float AngleMultiplier = 1.0f;
public float SpeedMultiplier = 1.0f;
public float CurveScale = 1.0f;
private TMP_Text m_TextComponent;
private void Awake()
{
m_TextComponent = gameObject.GetComponent<TMP_Text>();
}
private void Start()
{
StartCoroutine(WarpText());
}
private AnimationCurve CopyAnimationCurve(AnimationCurve curve)
{
var newCurve = new AnimationCurve();
newCurve.keys = curve.keys;
return newCurve;
}
/// <summary>
/// Method to curve text along a Unity animation curve.
/// </summary>
/// <param name="textComponent"></param>
/// <returns></returns>
private IEnumerator WarpText()
{
VertexCurve.preWrapMode = WrapMode.Clamp;
VertexCurve.postWrapMode = WrapMode.Clamp;
//Mesh mesh = m_TextComponent.textInfo.meshInfo[0].mesh;
Vector3[] vertices;
Matrix4x4 matrix;
m_TextComponent.havePropertiesChanged = true; // Need to force the TextMeshPro Object to be updated.
CurveScale *= 10;
var old_CurveScale = CurveScale;
var old_curve = CopyAnimationCurve(VertexCurve);
while (true)
{
if (!m_TextComponent.havePropertiesChanged && old_CurveScale == CurveScale &&
old_curve.keys[1].value == VertexCurve.keys[1].value)
{
yield return null;
continue;
}
old_CurveScale = CurveScale;
old_curve = CopyAnimationCurve(VertexCurve);
m_TextComponent
.ForceMeshUpdate(); // Generate the mesh and populate the textInfo with data we can use and manipulate.
var textInfo = m_TextComponent.textInfo;
var characterCount = textInfo.characterCount;
if (characterCount == 0) continue;
//vertices = textInfo.meshInfo[0].vertices;
//int lastVertexIndex = textInfo.characterInfo[characterCount - 1].vertexIndex;
var boundsMinX = m_TextComponent.bounds.min.x; //textInfo.meshInfo[0].mesh.bounds.min.x;
var boundsMaxX = m_TextComponent.bounds.max.x; //textInfo.meshInfo[0].mesh.bounds.max.x;
for (var i = 0; i < characterCount; i++)
{
if (!textInfo.characterInfo[i].isVisible)
continue;
var vertexIndex = textInfo.characterInfo[i].vertexIndex;
// Get the index of the mesh used by this character.
var materialIndex = textInfo.characterInfo[i].materialReferenceIndex;
vertices = textInfo.meshInfo[materialIndex].vertices;
// Compute the baseline mid point for each character
Vector3 offsetToMidBaseline =
new Vector2((vertices[vertexIndex + 0].x + vertices[vertexIndex + 2].x) / 2,
textInfo.characterInfo[i].baseLine);
//float offsetY = VertexCurve.Evaluate((float)i / characterCount + loopCount / 50f); // Random.Range(-0.25f, 0.25f);
// Apply offset to adjust our pivot point.
vertices[vertexIndex + 0] += -offsetToMidBaseline;
vertices[vertexIndex + 1] += -offsetToMidBaseline;
vertices[vertexIndex + 2] += -offsetToMidBaseline;
vertices[vertexIndex + 3] += -offsetToMidBaseline;
// Compute the angle of rotation for each character based on the animation curve
var x0 = (offsetToMidBaseline.x - boundsMinX) /
(boundsMaxX - boundsMinX); // Character's position relative to the bounds of the mesh.
var x1 = x0 + 0.0001f;
var y0 = VertexCurve.Evaluate(x0) * CurveScale;
var y1 = VertexCurve.Evaluate(x1) * CurveScale;
var horizontal = new Vector3(1, 0, 0);
//Vector3 normal = new Vector3(-(y1 - y0), (x1 * (boundsMaxX - boundsMinX) + boundsMinX) - offsetToMidBaseline.x, 0);
var tangent = new Vector3(x1 * (boundsMaxX - boundsMinX) + boundsMinX, y1) -
new Vector3(offsetToMidBaseline.x, y0);
var dot = Mathf.Acos(Vector3.Dot(horizontal, tangent.normalized)) * 57.2957795f;
var cross = Vector3.Cross(horizontal, tangent);
var angle = cross.z > 0 ? dot : 360 - dot;
matrix = Matrix4x4.TRS(new Vector3(0, y0, 0), Quaternion.Euler(0, 0, angle), Vector3.one);
vertices[vertexIndex + 0] = matrix.MultiplyPoint3x4(vertices[vertexIndex + 0]);
vertices[vertexIndex + 1] = matrix.MultiplyPoint3x4(vertices[vertexIndex + 1]);
vertices[vertexIndex + 2] = matrix.MultiplyPoint3x4(vertices[vertexIndex + 2]);
vertices[vertexIndex + 3] = matrix.MultiplyPoint3x4(vertices[vertexIndex + 3]);
vertices[vertexIndex + 0] += offsetToMidBaseline;
vertices[vertexIndex + 1] += offsetToMidBaseline;
vertices[vertexIndex + 2] += offsetToMidBaseline;
vertices[vertexIndex + 3] += offsetToMidBaseline;
}
// Upload the mesh with the revised information
m_TextComponent.UpdateVertexData();
yield return new WaitForSeconds(0.025f);
}
}
}
}

View File

@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: 790744c462254b7ba8038e6ed28b3db2
timeCreated: 1458801336
licenseType: Pro
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant: