121 lines
4.6 KiB
C#
121 lines
4.6 KiB
C#
using UnityEngine;
|
|
using TMPro;
|
|
|
|
//根据Unity动画曲线来变形
|
|
public class TMP_AnimationCurve : TMP_Curve
|
|
{
|
|
public AnimationCurve animationCurveY = new AnimationCurve(new Keyframe(0, -1f),
|
|
new Keyframe(0.5f, 0f),
|
|
new Keyframe(1, -1f));
|
|
public AnimationCurve animationCurveZ = new AnimationCurve(new Keyframe(0, 0),
|
|
new Keyframe(0.25f, .5f),
|
|
new Keyframe(0.5f, 1.0f),
|
|
new Keyframe(0.75f, .5f),
|
|
new Keyframe(1, 0f));
|
|
public float curveScaleY = 1.0f;
|
|
public float useForWidth = 10;
|
|
|
|
private float cacheScaleY = 1.0f;
|
|
private float cacheUseForWidth = 10f;
|
|
|
|
public float curveScaleZ = 1.0f;
|
|
public bool enableZ;
|
|
|
|
protected override bool ParametersHaveChanged()
|
|
{
|
|
if (cacheScaleY != curveScaleY || cacheUseForWidth != useForWidth)
|
|
{
|
|
cacheScaleY = curveScaleY;
|
|
cacheUseForWidth = useForWidth;
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
protected override Matrix4x4 ComputeTransformationMatrix(Vector3 charMidBaselinePos, float zeroToOnePos, TMP_TextInfo textInfo,
|
|
int charIdx, float totalLength)
|
|
{
|
|
animationCurveY.preWrapMode = WrapMode.Clamp;
|
|
animationCurveY.postWrapMode = WrapMode.Clamp;
|
|
animationCurveZ.preWrapMode = WrapMode.Clamp;
|
|
animationCurveZ.postWrapMode = WrapMode.Clamp;
|
|
|
|
float ty, ry, tz, rz;
|
|
|
|
GetUpTR(charMidBaselinePos, zeroToOnePos, totalLength,out ty, out ry);
|
|
GetForwardTR(charMidBaselinePos, zeroToOnePos, totalLength,out tz, out rz);
|
|
return Matrix4x4.TRS(new Vector3(0, ty, -tz), Quaternion.Euler(0, rz, ry), Vector3.one);
|
|
}
|
|
|
|
private void GetUpTR(Vector3 charMidBaselinePos, float zeroToOnePos, float total, out float t, out float r)
|
|
{
|
|
//float boundsMinX = m_TextComponent.bounds.min.x;
|
|
//float boundsMaxX = m_TextComponent.bounds.max.x;
|
|
// Compute the angle of rotation for each character based on the animation curve
|
|
|
|
float x0 = 0f;
|
|
if (zeroToOnePos >= 0.5f)
|
|
{
|
|
x0 = (0.5f * useForWidth + (zeroToOnePos - 0.5f) * total) / useForWidth;
|
|
}
|
|
else if (zeroToOnePos < 0.5f)
|
|
{
|
|
x0 = ((useForWidth - total) *0.5f + zeroToOnePos * total) / useForWidth;
|
|
}
|
|
|
|
float x1 = x0 + 0.0001f;
|
|
float y0 = animationCurveY.Evaluate(x0) * curveScaleY;
|
|
float y1 = animationCurveY.Evaluate(x1) * curveScaleY;
|
|
|
|
Vector3 horizontal = new Vector3(1, 0, 0);
|
|
//Vector3 tangent = new Vector3(x1 * total, y1) - new Vector3(charMidBaselinePos.x, y0);
|
|
Vector3 tangent = new Vector3(x1 * curveScaleY, y1) - new Vector3(x0 * curveScaleY, y0);
|
|
|
|
float dot = Mathf.Acos(Vector3.Dot(horizontal, tangent.normalized)) * 57.2957795f;
|
|
Vector3 cross = Vector3.Cross(horizontal, tangent);
|
|
float angle = cross.z > 0 ? dot : 360 - dot;
|
|
|
|
t = y0;
|
|
r = angle;
|
|
}
|
|
|
|
private void GetForwardTR(Vector3 charMidBaselinePos, float zeroToOnePos, float total, out float t, out float r)
|
|
{
|
|
if (!enableZ)
|
|
{
|
|
t = r = 0;
|
|
return;
|
|
}
|
|
|
|
float boundsMinX = m_TextComponent.bounds.min.x;
|
|
float boundsMaxX = m_TextComponent.bounds.max.x;
|
|
// Compute the angle of rotation for each character based on the animation curve
|
|
float x0 = 0f;
|
|
if (zeroToOnePos >= 0.5f)
|
|
{
|
|
x0 = (0.5f * useForWidth + (zeroToOnePos - 0.5f) * total) / useForWidth;
|
|
}
|
|
else if (zeroToOnePos < 0.5f)
|
|
{
|
|
x0 = ((useForWidth - total) *0.5f + zeroToOnePos * total) / useForWidth;
|
|
}
|
|
// Character's position relative to the bounds of the mesh.
|
|
|
|
float x1 = x0 + 0.0001f;
|
|
float z0 = animationCurveZ.Evaluate(x0) * curveScaleZ;
|
|
float z1 = animationCurveZ.Evaluate(x1) * curveScaleZ;
|
|
|
|
Vector3 horizontal = new Vector3(1, 0, 0);
|
|
//Vector3 normal = new Vector3(-(y1 - y0), (x1 * (boundsMaxX - boundsMinX) + boundsMinX) - charMidBaselinePos.x, 0);
|
|
Vector3 tangent = new Vector3(x1 * (boundsMaxX - boundsMinX) + boundsMinX, z1) - new Vector3(charMidBaselinePos.x, z0);
|
|
|
|
float dot = Mathf.Acos(Vector3.Dot(horizontal, tangent.normalized)) * 57.2957795f;
|
|
Vector3 cross = Vector3.Cross(horizontal, tangent);
|
|
float angle = cross.z > 0 ? dot : 360 - dot;
|
|
|
|
t = z0;
|
|
r = angle;
|
|
}
|
|
}
|
|
|