2023-04-03 11:04:31 +08:00

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;
}
}