Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

New! TextProOnACylinder.cs #5

Open
aidanwolf opened this issue Feb 8, 2024 · 0 comments
Open

New! TextProOnACylinder.cs #5

aidanwolf opened this issue Feb 8, 2024 · 0 comments

Comments

@aidanwolf
Copy link

If you're looking to curve the text like it would appear around cylinder, here is a quick code edit to the original TextProOnACircle to make that happen

using UnityEngine;
using System.Collections;
using TMPro;

namespace ntw.CurvedTextMeshPro
{
    /// <summary>
    /// Class for drawing a Text Pro text following a circle arc
    /// </summary>
    [ExecuteInEditMode]
    public class TextProOnACylinder : TextProOnACurve
    {
        /// <summary>
        /// The radius of the text circle arc
        /// </summary>
        [SerializeField]
        [Tooltip("The radius of the text circle arc")]
        private float m_radius = 10.0f;

        /// <summary>
        /// How much degrees the text arc should span
        /// </summary>
        [SerializeField]
        [Tooltip("How much degrees the text arc should span")]
        private float m_arcDegrees = 90.0f;

        /// <summary>
        /// The angular offset at which the arc should be centered, in degrees.
        /// -90 degrees means that the text is centered on the heighest point
        /// </summary>
        [SerializeField]
        [Tooltip("The angular offset at which the arc should be centered, in degrees")]
        private float m_angularOffset = -90;

        /// <summary>
        /// How many maximum degrees per letters should be. For instance, if you specify
        /// 10 degrees, the distance between the letters will never be superior to 10 degrees.
        /// It is useful to create text that gracefully expands until it reaches the full arc,
        /// without making the letters to sparse when the string is short
        /// </summary>
        [SerializeField]
        [Tooltip("The maximum angular distance between letters, in degrees")]
        private int m_maxDegreesPerLetter = 360;

        /// <summary>
        /// Previous value of <see cref="m_radius"/>
        /// </summary>
        private float m_oldRadius = float.MaxValue;

        /// <summary>
        /// Previous value of <see cref="m_arcDegrees"/>
        /// </summary>
        private float m_oldArcDegrees = float.MaxValue;

        /// <summary>
        /// Previous value of <see cref="m_angularOffset"/>
        /// </summary>
        private float m_oldAngularOffset = float.MaxValue;

        /// <summary>
        /// Previous value of <see cref="m_maxDegreesPerLetter"/>
        /// </summary>
        private float m_oldMaxDegreesPerLetter = float.MaxValue;

        /// <summary>
        /// Method executed at every frame that checks if some parameters have been changed
        /// </summary>
        /// <returns></returns>
        protected override bool ParametersHaveChanged()
        {
            //check if paramters have changed and update the old values for next frame iteration
            bool retVal = m_radius != m_oldRadius || m_arcDegrees != m_oldArcDegrees || m_angularOffset != m_oldAngularOffset || m_oldMaxDegreesPerLetter != m_maxDegreesPerLetter;

            m_oldRadius = m_radius;
            m_oldArcDegrees = m_arcDegrees;
            m_oldAngularOffset = m_angularOffset;
            m_oldMaxDegreesPerLetter = m_maxDegreesPerLetter;

            return retVal;
        }

        /// <summary>
        /// Computes the transformation matrix that maps the offsets of the vertices of each single character from
        /// the character's center to the final destinations of the vertices so that the text follows a curve
        /// </summary>
        /// <param name="charMidBaselinePosfloat">Position of the central point of the character</param>
        /// <param name="zeroToOnePos">Horizontal position of the character relative to the bounds of the box, in a range [0, 1]</param>
        /// <param name="textInfo">Information on the text that we are showing</param>
        /// <param name="charIdx">Index of the character we have to compute the transformation for</param>
        /// <returns>Transformation matrix to be applied to all vertices of the text</returns>
        protected override Matrix4x4 ComputeTransformationMatrix(Vector3 charMidBaselinePos, float zeroToOnePos, TMP_TextInfo textInfo, int charIdx)      
        {
            //calculate the actual degrees of the arc considering the maximum distance between letters
            float actualArcDegrees = Mathf.Min(m_arcDegrees, textInfo.characterCount / textInfo.lineCount * m_maxDegreesPerLetter);

            //compute the angle at which to show this character.
            //We want the string to be centered at the top point of the circle, so we first convert the position from a range [0, 1]
            //to a [-0.5, 0.5] one and then add m_angularOffset degrees, to make it centered on the desired point
            float angle = ((zeroToOnePos - 0.5f) * actualArcDegrees + m_angularOffset) * Mathf.Deg2Rad; //we need radians for sin and cos

            //compute the coordinates of the new position of the central point of the character. Use sin and cos since we are on a circle.
            //Notice that we have to do some extra calculations because we have to take in count that text may be on multiple lines
            float x0 = Mathf.Cos(angle);            
            float y0 = Mathf.Sin(angle);
            float radiusForThisLine = m_radius - textInfo.lineInfo[0].lineExtents.max.y * textInfo.characterInfo[charIdx].lineNumber;
            Vector2 newMideBaselinePos = new Vector2(x0 * radiusForThisLine, -y0 * radiusForThisLine); //actual new position of the character

            //compute the trasformation matrix: move the points to the just found position, then rotate the character to fit the angle of the curve 
            //(-90 is because the text is already vertical, it is as if it were already rotated 90 degrees)
            return Matrix4x4.TRS(new Vector3(-newMideBaselinePos.x, 0, newMideBaselinePos.y), Quaternion.AngleAxis(-Mathf.Atan2(y0, x0) * Mathf.Rad2Deg + 90, Vector3.up), Vector3.one);
        }
    }
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant