update sample

This commit is contained in:
Kirill Chikalin
2025-02-13 17:50:04 +03:00
parent 275dc598c7
commit bd35a522da
242 changed files with 940850 additions and 33728 deletions

View File

@@ -0,0 +1,156 @@
using System.Linq;
using TMPro;
using Unity.Mathematics;
using UnityEngine;
using UnityEngine.Splines;
namespace space.chikalin.textdecal
{
/// <summary>
///
/// Should execute after <c>space.chikalin.textdecal.TextMeshProDecal</c> script
/// </summary>
[ExecuteAlways]
[DisallowMultipleComponent]
[DefaultExecutionOrder(-90)]
[AddComponentMenu("Mesh/TextMeshPro - Spline")]
#if UNITY_2021_2_OR_NEWER
[Icon("Packages/com.unity.splines/Editor/Resources/Icons/SplineComponent.png")]
#endif
[RequireComponent(typeof(SplineContainer), typeof(TMP_Text))]
public class TextMeshProSpline : MonoBehaviour
{
private TMP_Text _text;
private SplineContainer _spline;
private Spline DefaultSpline(float3 start, float3 end)
{
var spline = new Spline
{
{ start, TangentMode.Linear },
{ end, TangentMode.Linear }
};
return spline;
}
private void Awake()
{
_text = GetComponent<TMP_Text>();
_spline = GetComponent<SplineContainer>();
}
private void OnEnable()
{
_text.OnPreRenderText += OnPreRenderText;
}
private void OnDisable()
{
_text.OnPreRenderText -= OnPreRenderText;
_text.ClearMesh();
_text.mesh.RecalculateBounds();
_text.ForceMeshUpdate();
}
private void OnPreRenderText(TMP_TextInfo textInfo)
{
FitSpline(textInfo);
}
private void FitSpline(TMP_TextInfo textInfo)
{
FixSpline();
var splineLength = _spline.CalculateLength();
if (splineLength <= 0) return;
for (var i = 0; i < textInfo.characterCount; i++)
{
if (!textInfo.characterInfo[i].isVisible)
continue;
var vertexIndex = textInfo.characterInfo[i].vertexIndex;
var materialIndex = textInfo.characterInfo[i].materialReferenceIndex;
var vertices = textInfo.meshInfo[materialIndex].vertices;
var bl = vertices[vertexIndex + 0];
var tr = vertices[vertexIndex + 2];
var charCenter = bl + (tr - bl) / 2;
Evaluate(splineLength, charCenter.x, out var position, out var xAxis, out var yAxis);
xAxis = transform.InverseTransformDirection(math.normalize(xAxis));
yAxis = transform.InverseTransformDirection(math.normalize(yAxis));
position = transform.InverseTransformPoint(position);
var newCenter = position + yAxis * charCenter.y;
for (var v = 0; v < 4; v++)
{
var d = vertices[vertexIndex + v] - charCenter;
vertices[vertexIndex + v] = newCenter + xAxis * d.x + yAxis * d.y;
}
}
}
private void FixSpline()
{
var textRectTransform = _text.rectTransform;
if (_spline.Spline.Count >= 2) return;
var rect = textRectTransform.rect;
var position = textRectTransform.position;
var start = new float3(rect.xMin, rect.yMin, position.z);
var end = new float3(rect.xMax, rect.yMax, position.z);
_spline.Spline = DefaultSpline(start, end);
}
private void Evaluate(float length, float xPos, out float3 position, out float3 xAxis, out float3 yAxis)
{
var s = (xPos / length) * transform.localScale.x + .5f; // centered
_spline.Evaluate(math.clamp(s, 0.01f, .99f), out position, out xAxis, out yAxis);
}
private Quaternion ReflectRotation(Quaternion source, Vector3 normal)
{
return Quaternion.LookRotation(Vector3.Reflect(source * Vector3.forward, normal),
Vector3.Reflect(source * Vector3.up, normal));
}
#if UNITY_EDITOR
[ExecuteAlways]
[ContextMenu("Mirror")]
public void Mirror()
{
var rectTransform = _text.rectTransform;
rectTransform.GetPositionAndRotation(out var position, out var rotation);
var max = position + _text.transform.right * rectTransform.rect.width * rectTransform.localScale.x;
max.x = -max.x;
var angles = rotation.eulerAngles;
rotation = Quaternion.Euler(angles.x, 180 - (angles.y - 180), -angles.z);
rectTransform.SetPositionAndRotation(max, rotation);
var spline = _spline.Splines[0];
var array = spline.Knots.ToArray();
var lastX = array[^1].Position.x;
var r = array.Length - 1;
for (int i = 0; i < array.Length; i++)
{
var knot = array[i];
knot.Position.x = -knot.Position.x + lastX;
spline.SetKnot(r - i, knot);
}
}
#endif
#if UNITY_EDITOR
private void OnValidate()
{
ForceUpdate();
}
#endif
[ExecuteAlways]
public void ForceUpdate()
{
if (_text != null)
{
_text.ForceMeshUpdate();
}
}
}
}