Skip to content

Instantly share code, notes, and snippets.

@mopsicus
Last active April 8, 2023 20:49
Show Gist options
  • Star 5 You must be signed in to star a gist
  • Fork 2 You must be signed in to fork a gist
  • Save mopsicus/9d344451ca614d7e9937bc0c6da2b21d to your computer and use it in GitHub Desktop.
Save mopsicus/9d344451ca614d7e9937bc0c6da2b21d to your computer and use it in GitHub Desktop.
Apply gradient to whole TMP text, but no for each character
// ----------------------------------------------------------------------------
// The MIT License
// TextGradient https://gist.github.com/mopsicus/9d344451ca614d7e9937bc0c6da2b21d
// Copyright (c) 2020 Mopsicus <mail@mopsicus.ru>
// ----------------------------------------------------------------------------
using System.Collections;
using System.Collections.Generic;
using TMPro;
using UnityEngine;
/// <summary>
/// Apply gradient to whole text
/// </summary>
public class TextGradient : MonoBehaviour {
/// <summary>
/// Do gradient text
/// </summary>
private void Start () {
ApplyGradient ();
}
/// <summary>
/// Gradient method
/// Get gradient by steps, and make vertext gradient array from colors
/// Apply to each character
/// </summary>
void ApplyGradient () {
TMP_Text textComponent = GetComponent<TMP_Text> ();
textComponent.ForceMeshUpdate ();
TMP_TextInfo textInfo = textComponent.textInfo;
int count = textInfo.characterCount;
Color[] steps = GetGradients (textComponent.colorGradient.topLeft, textComponent.colorGradient.topRight, count + 1);
VertexGradient[] gradients = new VertexGradient[steps.Length];
for (int i = 0; i < steps.Length - 1; i++) {
gradients[i] = new VertexGradient (steps[i], steps[i + 1], steps[i], steps[i + 1]);
}
Color32[] colors;
int index = 0;
while (index < count) {
int materialIndex = textInfo.characterInfo[index].materialReferenceIndex;
colors = textInfo.meshInfo[materialIndex].colors32;
int vertexIndex = textInfo.characterInfo[index].vertexIndex;
if (textInfo.characterInfo[index].isVisible) {
colors[vertexIndex + 0] = gradients[index].bottomLeft;
colors[vertexIndex + 1] = gradients[index].topLeft;
colors[vertexIndex + 2] = gradients[index].bottomRight;
colors[vertexIndex + 3] = gradients[index].topRight;
textComponent.UpdateVertexData (TMP_VertexDataUpdateFlags.Colors32);
}
index++;
}
}
/// <summary>
/// Split gradient by steps from color to color
/// </summary>
/// <param name="start">Start color</param>
/// <param name="end">End color</param>
/// <param name="steps">Steps count</param>
/// <returns>Array of colors</returns>
public static Color[] GetGradients (Color start, Color end, int steps) {
Color[] result = new Color[steps];
float r = ((end.r - start.r) / (steps - 1));
float g = ((end.g - start.g) / (steps - 1));
float b = ((end.b - start.b) / (steps - 1));
float a = ((end.a - start.a) / (steps - 1));
for (int i = 0; i < steps; i++) {
result[i] = new Color (start.r + (r * i), start.g + (g * i), start.b + (b * i), start.a + (a * i));
}
return result;
}
}
@Inviasubito
Copy link

Inviasubito commented Mar 26, 2021

Hi, can it work with inputField?
I tried calling the "ApplyGradient" method in a new class

[RequireComponent(typeof(TMPro.TMP_InputField))]
    public class TextGradientInputField : MonoBehaviour
    {
        private TMPro.TMP_InputField _inputField;
        private TextGradient _gradientText;

        private void Awake()
        {
            _inputField = GetComponent<TMPro.TMP_InputField>();
            _gradientText = _inputField.textComponent.gameObject.AddComponent<TextGradient>();

            //_inputField.onValueChanged.RemoveListener(UpdateTextGradientComponent);
            _inputField.onValueChanged.AddListener(UpdateTextGradientComponent);
        }

        private void UpdateTextGradientComponent(string text)
        {
            _gradientText.ApplyGradient();
        }
    }

But it doesn't work

@AQaddora
Copy link

you can use this to apply gradient in edit mode and whenever the properties change

// ----------------------------------------------------------------------------
// The MIT License
// TextGradient https://gist.github.com/mopsicus/9d344451ca614d7e9937bc0c6da2b21d
// Copyright (c) 2020 Mopsicus <mail@mopsicus.ru>
// Modified by Qaddoura 2022
// ----------------------------------------------------------------------------
[ExecuteAlways]
[RequireComponent(typeof(TextMeshProUGUI))]
public class TextGradient : MonoBehaviour
{
    private TextMeshProUGUI textComponent;
    private void Start () {
        textComponent = GetComponent<TextMeshProUGUI> ();
        ApplyGradient ();
    }
    private void Update () {
        if (textComponent.havePropertiesChanged) {
            ApplyGradient ();
        }
    }
    /// <summary>
    /// Gradient method
    /// Get gradient by steps, and make vertext gradient array from colors
    /// Apply to each character
    /// </summary>
    void ApplyGradient () {
        textComponent.ForceMeshUpdate ();
        TMP_TextInfo textInfo = textComponent.textInfo;
        int count = textInfo.characterCount;
        Color[] steps = GetGradients (textComponent.colorGradient.topLeft, textComponent.colorGradient.topRight, count + 1);
        VertexGradient[] gradients = new VertexGradient[steps.Length];
        for (int i = 0; i < steps.Length - 1; i++) {
            gradients[i] = new VertexGradient (steps[i], steps[i + 1], steps[i], steps[i + 1]);
        }
        Color32[] colors;
        int index = 0;
        while (index < count) {
            int materialIndex = textInfo.characterInfo[index].materialReferenceIndex;
            colors = textInfo.meshInfo[materialIndex].colors32;
            int vertexIndex = textInfo.characterInfo[index].vertexIndex;
            if (textInfo.characterInfo[index].isVisible) {
                colors[vertexIndex + 0] = gradients[index].bottomLeft;
                colors[vertexIndex + 1] = gradients[index].topLeft;
                colors[vertexIndex + 2] = gradients[index].bottomRight;
                colors[vertexIndex + 3] = gradients[index].topRight;
                textComponent.UpdateVertexData (TMP_VertexDataUpdateFlags.Colors32);
            }
            index++;
        }
    }
    /// <summary>
    /// Split gradient by steps from color to color
    /// </summary>
    /// <param name="start">Start color</param>
    /// <param name="end">End color</param>
    /// <param name="steps">Steps count</param>
    /// <returns>Array of colors</returns>
    public static Color[] GetGradients (Color start, Color end, int steps) {
        Color[] result = new Color[steps];
        float r = ((end.r - start.r) / (steps - 1));
        float g = ((end.g - start.g) / (steps - 1));
        float b = ((end.b - start.b) / (steps - 1));
        float a = ((end.a - start.a) / (steps - 1));
        for (int i = 0; i < steps; i++) {
            result[i] = new Color (start.r + (r * i), start.g + (g * i), start.b + (b * i), start.a + (a * i));
        }
        return result;
    }
}

@bingxueyouwu
Copy link

Can it support normal text control?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment