当前位置:网站首页>Colorbar of using vertexehelper to customize controls (II)

Colorbar of using vertexehelper to customize controls (II)

2022-07-07 09:22:00 heater404

One 、 Realization ColorBar

What is? ColorBar??? Go straight to the renderings :
 Insert picture description here

A set of data is mapped to a set of colors , Similar to pseudo color map . First we need to prepare a set of colors , We can choose HSV Color model ,HSV The color model is not explained in detail here , Students who don't know can learn by themselves .

So how to fill the vertex with color ? We can use rectangular vertices , The two vertices on the rectangle use the same color , The two vertices under the rectangle use the same color , The two vertices below this rectangle will coincide with the two vertices above the next rectangle .

    /// <summary>
    /// 
    /// </summary>
    /// <param name="h">0-1</param>
    /// <param name="s">0-1</param>
    /// <param name="v">0-1</param>
    /// <returns></returns>
    private Color HSVToRGB(float h)
    {
    
        return Color.HSVToRGB(h, 1, 1);
    }

    protected override void OnPopulateMesh(VertexHelper vh)
    {
    
        var rect = this.GetPixelAdjustedRect();
        vh.Clear();

        var count = 15;// Define the number of rectangles , The more the number, the finer the color , But the greater the computational power . The corresponding color value will +1.
        var posStep = (rect.yMax - rect.yMin) / count;
        var colorStep = (1f - 0f) / count;// stay 0-1 Intermediate interpolation count-1 individual   It has a total of count+1 A color is worth 
        // Of course , You may not need h stay 0-1 The scope of the   You can modify the maximum and minimum values by yourself .

        for (int i = 0; i < count; i++)
        {
    
            UIVertex[] verts = new UIVertex[4];
            verts[0].position = new Vector3(rect.xMin, rect.yMin + i * posStep);
            verts[0].color = HSVToRGB(i * colorStep);
            verts[0].uv0 = Vector2.zero;

            verts[1].position = new Vector3(rect.xMax, rect.yMin + i * posStep);
            verts[1].color = HSVToRGB(i * colorStep);
            verts[1].uv0 = Vector2.zero;

            verts[2].position = new Vector3(rect.xMax, rect.yMin + (i + 1) * posStep);
            verts[2].color = HSVToRGB((i + 1) * colorStep);
            verts[2].uv0 = Vector2.zero;

            verts[3].position = new Vector3(rect.xMin, rect.yMin + (i + 1) * posStep);
            verts[3].color = HSVToRGB((i + 1) * colorStep);
            verts[3].uv0 = Vector2.zero;

            vh.AddUIVertexQuad(verts);
        }
    }

 Insert picture description here

Next, we will add a graduation mark to the color . In order to reserve a position on the left side for the graduation mark , We cannot set the vertex position to xMin, So we changed it to this :

public class CreateRectangle : Graphic
{
    
    int count = 15;// Define the number of rectangles , The more the number, the finer the color , But the greater the computational power . The corresponding color value will +1.
    float hMin = 0;
    float hMax = 1;
    float leftMargin = 60;

    protected override void Start()
    {
    
        base.Start();
        StartCoroutine(MUpdateGeometry());
    }

    IEnumerator MUpdateGeometry()
    {
    
        while (true)
        {
    
            UpdateGeometry();
            //SetVerticesDirty();
            yield return new WaitForSeconds(2);
        }
    }

    /// <summary>
    /// 
    /// </summary>
    /// <param name="h">0-1</param>
    /// <param name="s">0-1</param>
    /// <param name="v">0-1</param>
    /// <returns></returns>
    private Color HSVToRGB(float h)
    {
    
        return Color.HSVToRGB(h, 1, 1);
    }

    protected override void OnPopulateMesh(VertexHelper vh)
    {
    
        var rect = this.GetPixelAdjustedRect();
        vh.Clear();
        var posStep = (rect.yMax - rect.yMin) / count;
        var colorStep = (hMax - hMin) / count;// stay 0-1 Intermediate interpolation count-1 individual   It has a total of count+1 A color is worth 
        // Of course , You may not need h stay 0-1 The scope of the   You can modify the maximum and minimum values by yourself .

        for (int i = 0; i < count; i++)
        {
    
            UIVertex[] verts = new UIVertex[4];
            verts[0].position = new Vector3(rect.xMin + leftMargin, rect.yMin + i * posStep);
            verts[0].color = HSVToRGB(i * colorStep);
            verts[0].uv0 = Vector2.zero;

            verts[1].position = new Vector3(rect.xMax, rect.yMin + i * posStep);
            verts[1].color = HSVToRGB(i * colorStep);
            verts[1].uv0 = Vector2.zero;

            verts[2].position = new Vector3(rect.xMax, rect.yMin + (i + 1) * posStep);
            verts[2].color = HSVToRGB((i + 1) * colorStep);
            verts[2].uv0 = Vector2.zero;

            verts[3].position = new Vector3(rect.xMin + leftMargin, rect.yMin + (i + 1) * posStep);
            verts[3].color = HSVToRGB((i + 1) * colorStep);
            verts[3].uv0 = Vector2.zero;

            vh.AddUIVertexQuad(verts);
        }
    }
}

 Insert picture description here

We will use a tick mark Text On the left side , So we created a preform :

 Insert picture description here

This prefabricated body Width We will set the width of the reserved position , The height will not change , then PosX It can be calculated to be fixed , Calculated according to the actual position PosY that will do .

public class CreateRectangle : Graphic
{
    
    int count = 15;// Define the number of rectangles , The more the number, the finer the color , But the greater the computational power . The corresponding color value will +1.
    float hMin = 0;
    float hMax = 1;
    float leftMargin = 60;
    float markMax = 6000;
    float markMin = 0;
    GameObject markTextPrefab;

    protected override void Start()
    {
    
        base.Start();
        markTextPrefab = InitMarkTextPrefab();
        StartCoroutine(MUpdateGeometry());
    }

    IEnumerator MUpdateGeometry()
    {
    
        while (true)
        {
    
            UpdateGeometry();
            //SetVerticesDirty();
            yield return new WaitForSeconds(2);
        }
    }

    private GameObject InitMarkTextPrefab()
    {
    
        var prefab = (GameObject)Resources.Load("MarkText", typeof(GameObject));

        var x = this.gameObject.GetComponent<RectTransform>().rect.width / 2 - leftMargin / 2;

        prefab.GetComponent<RectTransform>().rect.Set(-x, 0, leftMargin, 20);
        return prefab;
    }

    private void CreateOneMarkText(float yPos, string msg, string name)
    {
    
        var markText = (GameObject)Instantiate(markTextPrefab);
        markText.name = "MarkText" + name;
        markText.transform.SetParent(this.transform);
        var originRect = markText.GetComponent<RectTransform>().rect;
        markText.GetComponent<RectTransform>().rect.Set(originRect.x, yPos, originRect.width, originRect.height);
    }

    /// <summary>
    /// 
    /// </summary>
    /// <param name="h">0-1</param>
    /// <param name="s">0-1</param>
    /// <param name="v">0-1</param>
    /// <returns></returns>
    private Color HSVToRGB(float h)
    {
    
        return Color.HSVToRGB(h, 1, 1);
    }

    protected override void OnPopulateMesh(VertexHelper vh)
    {
    
        var rect = this.GetPixelAdjustedRect();
        vh.Clear();
        var posStep = (rect.yMax - rect.yMin) / count;
        var colorStep = (hMax - hMin) / count;// stay 0-1 Intermediate interpolation count-1 individual   It has a total of count+1 A color is worth 
        // Of course , You may not need h stay 0-1 The scope of the   You can modify the maximum and minimum values by yourself .

        var markStep = (markMax - markMin) / count;

        for (int i = 0; i < count; i++)
        {
    
            UIVertex[] verts = new UIVertex[4];
            var y0 = rect.yMin + i * posStep;
            var h0 = i * colorStep;
            verts[0].position = new Vector3(rect.xMin + leftMargin, y0);
            verts[0].color = HSVToRGB(h0);
            verts[0].uv0 = Vector2.zero;

            verts[1].position = new Vector3(rect.xMax, y0);
            verts[1].color = HSVToRGB(h0);
            verts[1].uv0 = Vector2.zero;
            CreateOneMarkText(y0, (i * markStep).ToString(), i.ToString());

            var y1 = y0 + posStep;
            var h1 = h0 + colorStep;
            verts[2].position = new Vector3(rect.xMax, y1);
            verts[2].color = HSVToRGB(h1);
            verts[2].uv0 = Vector2.zero;

            verts[3].position = new Vector3(rect.xMin + leftMargin, y1);
            verts[3].color = HSVToRGB(h1);
            verts[3].uv0 = Vector2.zero;
            CreateOneMarkText(y1, ((i + 1) * markStep).ToString(), (i + 1).ToString());

            vh.AddUIVertexQuad(verts);
        }
    }
}

however , Something is wrong. !!!

Trying to add MarkText15 (UnityEngine.UI.Text) for graphic rebuild while we are already inside a graphic rebuild loop. This is not supported.

This is because : Instantiate a UI Control called graphic rebuild operation , and OnPopulateMesh(), The function is in graphic rebuild Called in the operation , So if in OnPopulateMesh(), Create a new UI Control, the system will prompt an error :graphic rebuild The operation is called circularly , So we need to use CO process operation (IEnumerator), After entering the process operation , Must be carried out immediately yield return new WaitForSeconds(0), Temporarily exit the current collaboration , Give Way graphic rebuild The operation is performed first .

So we need to put CreateOneMarkText It is modified as collaborative process :

    IEnumerator CreateOneMarkText(float yPos, string msg, string name)
    {
    
        yield return new WaitForSeconds(0);
        name = "MarkText" + name;
        var markText = this.transform.Find(name)?.gameObject;
        if (markText == null)
        {
    
            markText = (GameObject)Instantiate(markTextPrefab);
            markText.name = name;
        }
        markText.transform.SetParent(this.transform);
        var x = this.gameObject.GetComponent<RectTransform>().rect.width / 2 - leftMargin / 2;
        markText.GetComponent<RectTransform>().anchoredPosition = new Vector2(-x, yPos);
        markText.GetComponent<Text>().text = msg + "-";
    }

Then change the place called to :

StartCoroutine(CreateOneMarkText(y0, (i * markStep).ToString(), i.ToString()));

 Insert picture description here

Two 、 Adding unit

After the above is completed, you will find a problem , The scale information at the bottom and top exceeds the size of the control , So we also need to leave a margin , Then we need to consider the location of the unit . We still need to give ColorBar Add a background , The complete code is as follows :

public class ColorBar : Graphic
{
    
    public Color MarkTextColor;
    public int UIVertexQuadCount = 15;// Define the number of rectangles , The more the number, the finer the color , But the greater the computational power . The corresponding color value will +1.
    float hMin = 0;
    float hMax = 1;
    public float MarkTextWidth = 40;
    public float MarkTextHeight = 16;
    float markMax = 6000;
    float markMin = 0;
    GameObject markTextPrefab;

    protected override void Start()
    {
    
        base.Start();
        markTextPrefab = InitMarkTextPrefab();
    }

    IEnumerator MUpdateGeometry()
    {
    
        while (true)
        {
    
            UpdateGeometry();
            //SetVerticesDirty();
            yield return new WaitForSeconds(2);
        }
    }

    private GameObject InitMarkTextPrefab()
    {
    
        var game = (GameObject)Resources.Load("MarkText", typeof(GameObject));
        return game;
    }

    IEnumerator CreateOneMarkText(float yPos, string msg, string name)
    {
    
        yield return new WaitForSeconds(0);
        name = "MarkText" + name;
        var markText = this.transform.Find(name)?.gameObject;
        if (markText == null)
        {
    
            markText = (GameObject)Instantiate(markTextPrefab);
            markText.name = name;
        }
        markText.transform.SetParent(this.transform);
        var x = this.gameObject.GetComponent<RectTransform>().rect.width / 2 - MarkTextWidth / 2;
        markText.GetComponent<RectTransform>().sizeDelta = new Vector2(MarkTextWidth, MarkTextHeight);
        markText.GetComponent<RectTransform>().anchoredPosition = new Vector2(-x, yPos);
        markText.GetComponent<Text>().text = msg;
        markText.GetComponent<Text>().color = MarkTextColor;
    }

    private Color CreateOneColor(float h)
    {
    
        return Color.HSVToRGB(h, 1, 1);
    }

    protected override void OnPopulateMesh(VertexHelper vh)
    {
    
        var rect = this.GetPixelAdjustedRect();
        vh.Clear();
        float yMax, yMin;
        yMax = rect.yMax - MarkTextHeight / 2;
        // Because the company information needs to be reserved at the bottom , So add an extra space .
        yMin = rect.yMin + MarkTextHeight / 2 + MarkTextHeight / 2;

        var posStep = (yMax - yMin) / UIVertexQuadCount;
        var colorStep = (hMax - hMin) / UIVertexQuadCount;// Intermediate interpolation count-1 individual   It has a total of count+1 A color is worth 

        var markStep = (markMax - markMin) / UIVertexQuadCount;

        // Adding unit 
        StartCoroutine(CreateOneMarkText(yMin - MarkTextHeight / 2, "mm", "unit"));

        for (int i = 0; i < UIVertexQuadCount; i++)
        {
    
            UIVertex[] verts = new UIVertex[4];
            var y0 = yMin + i * posStep;
            var h0 = hMin + i * colorStep;
            verts[0] = CreateOneUIVertex(new Vector2(rect.xMin + MarkTextWidth, y0), h0);
            verts[1] = CreateOneUIVertex(new Vector2(rect.xMax, y0), h0);

            var m0 = markMin + (i * markStep);
            StartCoroutine(CreateOneMarkText(y0, m0.ToString() + "-", i.ToString()));

            var y1 = y0 + posStep;
            var h1 = h0 + colorStep;
            verts[2] = CreateOneUIVertex(new Vector2(rect.xMax, y1), h1);
            verts[3] = CreateOneUIVertex(new Vector2(rect.xMin + MarkTextWidth, y1), h1);

            var m1 = m0 + markStep;
            StartCoroutine(CreateOneMarkText(y1, m1.ToString() + "-", (i + 1).ToString()));

            vh.AddUIVertexQuad(verts);
        }
    }

    private UIVertex CreateOneUIVertex(Vector2 pos, float h)
    {
    
        UIVertex vert = new UIVertex();
        vert.position = new Vector3(pos.x, pos.y);
        vert.color = CreateOneColor(h);
        vert.uv0 = Vector2.zero;

        return vert;
    }
}

 Insert picture description here

3、 ... and 、 reflection

After adding units above, it seems to be over ??? No , In fact, we made a mistake above , That is, we drew a color band first , Then add a tick mark , How can it be wrong here ? Because the number of tick marks is not fixed , When the size of the control changes, the scale line will also need to change accordingly . therefore , Let's rearrange :

  1. We first have a mapping relationship between value and color
  2. We tile the value range linearly on the interface ( Axis ), The creation process of coordinate axis is roughly : Calculate the number of scales according to the height of a coordinate scale and the height of the coordinate axis , Then calculate the scale step with the coordinate axis range .
  3. After creating the coordinate axis, draw a color band according to the mapping relationship between value and color ( How many colors to draw depends on the number of scales )

therefore , Our code has changed a lot :

public class ColorBar : Graphic
{
    
    public int UIVertexQuadNumBetweenTwoMarkText = 3;
    const string MarkTextNameBase = "MarkText";
    public string unit = "unknown";
    readonly float[] MarkTabs = new float[] {
     1, 2, 5 };
    public Color MarkTextColor = Color.white;
    public float MarkTextWidth = 40;
    public float MarkTextHeight = 16;
    private float markTextMax = 6200;
    public Func<float, float, float, Color> CalcOneColor;
    public float MarkTextMax
    {
    
        get {
     return markTextMax; }
        set
        {
    
            if (value > markTextMin)
            {
    
                markTextMax = value;
                UpdateGeometry();// call OnPopulateMesh
            }
        }
    }
    private float markTextMin = 100;
    public float MarkTextMin
    {
    
        get {
     return markTextMin; }
        set
        {
    
            if (value < markTextMax)
            {
    
                markTextMin = value;
                UpdateGeometry();// call OnPopulateMesh
            }
        }
    }

    GameObject markTextPrefab;

    protected override void Start()
    {
    
        base.Start();
        markTextPrefab = InitMarkTextPrefab();
    }

    private GameObject InitMarkTextPrefab()
    {
    
        var game = (GameObject)Resources.Load("MarkText", typeof(GameObject));
        return game;
    }

    void CreateOneMarkText(float yPos, string msg)
    {
    
        string name = MarkTextNameBase + msg;
        var markText = this.transform.Find(name)?.gameObject;
        if (markText == null)
        {
    
            markText = (GameObject)Instantiate(markTextPrefab);
            markText.name = name;
        }
        markText.transform.SetParent(this.transform);
        var x = this.gameObject.GetComponent<RectTransform>().rect.width / 2 - MarkTextWidth / 2;
        var rectTransform = markText.GetComponent<RectTransform>();
        rectTransform.sizeDelta = new Vector2(MarkTextWidth, MarkTextHeight);
        rectTransform.anchoredPosition = new Vector2(-x, yPos);
        var text = markText.GetComponent<Text>();
        text.text = msg;
        text.color = MarkTextColor;
        text.enabled = true;
    }

    IEnumerator CreateMarkTextUnit(float yPos, string msg)
    {
    
        yield return new WaitForSeconds(0);
        CreateOneMarkText(yPos, msg);
    }

    IEnumerator CreateMarkText(float markTextYPos, float markText)
    {
    
        yield return new WaitForSeconds(0);
        CreateOneMarkText(markTextYPos, markText.ToString() + "-");
    }

    IEnumerator DisableAllMarkTextWithoutUnit()
    {
    
        yield return new WaitForSeconds(0);
        var children = this.GetComponentsInChildren<Text>();
        foreach (var child in children)
        {
    
            if (child.name != MarkTextNameBase + unit)
                child.enabled = false;
        }
    }

    IEnumerator DestoryAllDisabledMarkText()
    {
    
        yield return new WaitForSeconds(0);
        var children = this.GetComponentsInChildren<Text>();
        foreach (var child in children)
        {
    
            if (!child.enabled)
                DestroyImmediate(child.gameObject);
        }
    }

    private float CalcRealStartMarkText(float markText)
    {
    
        int basePrecision = 1;
        while (markText < basePrecision || markText > basePrecision * 10)
        {
    
            if (markText < basePrecision)
                basePrecision /= 10;
            else if (markText > basePrecision * 10)
                basePrecision *= 10;
            else
                break;
        }
        basePrecision /= 10;

        return Mathf.CeilToInt(markText / basePrecision) * basePrecision;
    }

    protected override void OnPopulateMesh(VertexHelper vh)
    {
    
        var rect = this.GetPixelAdjustedRect();
        vh.Clear();
        //ColorBar Coordinate position of rectangle ( Pixel unit )
        float yMax, yMin, xMin, xMax;
        yMax = rect.yMax - MarkTextHeight / 2;
        // Because the company information needs to be reserved at the bottom , So add an extra space .
        yMin = rect.yMin + MarkTextHeight / 2 + MarkTextHeight / 2;
        xMin = rect.xMin + MarkTextWidth;
        xMax = rect.xMax;

        var markTextNum = CalcMarkTextNum(MarkTextHeight, yMax - yMin);
        float markTextStep = CalcMarkTextStep(MarkTabs, markTextNum, markTextMax - markTextMin);
        var rate = (yMax - yMin) / (markTextMax - markTextMin);
        var realMarkTextMin = CalcRealStartMarkText(markTextMin);

        // Adding unit 
        StartCoroutine(CreateMarkTextUnit(yMin - MarkTextHeight / 2, unit));
        StartCoroutine(DisableAllMarkTextWithoutUnit());

        var markText = realMarkTextMin;
        while (markText <= markTextMax)
        {
    
            // Current tick mark 
            var markTextYPos = (markText - markTextMin) * rate + yMin;
            StartCoroutine(CreateMarkText(markTextYPos, markText));

            // Due to the large span between the two graduation marks , Only draw a rectangle, and the color transition is not good , So here, draw several between the two tick marks 
            var uiVertexQuadStep = markTextStep / UIVertexQuadNumBetweenTwoMarkText;
            for (int i = 0; i < UIVertexQuadNumBetweenTwoMarkText; i++)
            {
    
                // Previous tick mark 
                var markTextPre = markText - (i + 1) * uiVertexQuadStep;
                if (markTextPre < markTextMin)
                    markTextPre = markTextMin;

                var markTextYPosPre = (markTextPre - markTextMin) * rate + yMin;

                var verts = CreateUIVertexQuad(xMin, xMax, markTextYPosPre, markTextYPos, markTextPre, markText);
                vh.AddUIVertexQuad(verts);

                if (markTextPre < markTextMin)
                    break;
            }
            // Next tick mark 
            markText += markTextStep;
        }

        // Jumping here means that the scale line is greater than the maximum value , Those beyond the maximum scale line certainly do not need to be drawn 
        // The maximum scale line does not need to be drawn , It may not be the data accuracy we want 
        // But the color value corresponding to the maximum scale line needs to be drawn , It is equivalent to the minimum scale color value also needs to be drawn 
        var lastmarkText = markText - markTextStep;// This is the largest scale line drawn 
        var lastmarkTextYPos = (lastmarkText - markTextMin) * rate + yMin;

        var lastverts = CreateUIVertexQuad(xMin, xMax, lastmarkTextYPos, yMax, lastmarkText, markTextMax);
        vh.AddUIVertexQuad(lastverts);

        StartCoroutine(DestoryAllDisabledMarkText());
    }

    private UIVertex[] CreateUIVertexQuad(float xMin, float xMax,
        float yBottomPos, float yTopPos, float markBottom, float markTop)
    {
    
        UIVertex[] verts = new UIVertex[4];
        verts[0] = CreateOneUIVertex(new Vector2(xMin, yBottomPos), markBottom);
        verts[1] = CreateOneUIVertex(new Vector2(xMax, yBottomPos), markBottom);

        verts[2] = CreateOneUIVertex(new Vector2(xMax, yTopPos), markTop);
        verts[3] = CreateOneUIVertex(new Vector2(xMin, yTopPos), markTop);

        return verts;
    }

    private UIVertex CreateOneUIVertex(Vector2 pos, float h)
    {
    
        UIVertex vert = new UIVertex();
        vert.position = new Vector3(pos.x, pos.y);
        if (CalcOneColor != null)
            vert.color = CalcOneColor.Invoke(h, markTextMin, markTextMax);
        vert.uv0 = Vector2.zero;

        return vert;
    }

    /// <summary>
    ///  Calculate the number of tick marks , multiply 3 Because the interval between the scale marks is given 
    /// </summary>
    /// <param name="markTextHeigh"> The height occupied by a scale line </param>
    /// <param name="colorBarHeigh"> Length of the entire shaft </param>
    /// <returns></returns>
    private int CalcMarkTextNum(float markTextHeigh, float colorBarHeigh)
    {
    
        return Mathf.FloorToInt(colorBarHeigh / (markTextHeigh * 3));
    }

    /// <summary>
    ///  Find the best scale step 
    /// </summary>
    /// <param name="markTab"> Provide an alternative step size base </param>
    /// <param name="markNum"> Number of scales </param>
    /// <param name="MarkTextRange"> The whole range that needs to be crossed </param>
    /// <returns> Optimal step size </returns>
    private float CalcMarkTextStep(float[] markTab, int markNum, float MarkTextRange)
    {
    
        float step = MarkTextRange / (markNum > 0 ? markNum : 1);
        float markScale = 1;
        float mark = markTab[0];
        while (step < mark * markScale || step > mark * markScale * 10)
        {
    
            if (step < mark * markScale)
                markScale /= 10;
            else if (step > mark * markScale * 10)
                markScale *= 10;
            else
                break;
        }

        step /= markScale;
        for (int i = 1; i < markTab.Length; i++)
        {
    
            if (Mathf.Abs(markTab[i] - step) < Mathf.Abs(mark - step))
                mark = markTab[i];
        }

        return mark * markScale;
    }
}

Considering that you want to make controls , So we wrote the mutable things in another user script :

public class CustomColorBar : MonoBehaviour
{
    
    public ColorBar Bar;
    public float Max
    {
    
        get {
     return Bar.MarkTextMax; }
        set {
     Bar.MarkTextMax = value; }
    }

    public float Min
    {
    
        get {
     return Bar.MarkTextMin; }
        set {
     Bar.MarkTextMin = value; }
    }

    // Use this for initialization
    void Start()
    {
    
        Bar.CalcOneColor = CreateOneColor;
        StartCoroutine(UpdateMaxAndMin());
    }

    IEnumerator UpdateMaxAndMin()
    {
    
        while (true)
        {
    
            Min= Random.Range(0, 3000);
            yield return new WaitForSeconds(5);
            Max = Random.Range(Min, 7000);
            yield return new WaitForSeconds(5);
        }
    }

    // Update is called once per frame
    void Update()
    {
    

    }

    private Color CreateOneColor(float value, float min, float max)
    {
    
        float hMin = 0, hMax = 0.80f;

        var h = (hMax - hMin) / (max - min) * (value - min) + hMin;

        return Color.HSVToRGB(h, 1, 1);
    }
}

 Insert picture description here

Four 、 Custom control

 Insert picture description here

And then in Editor A script is added to the folder :

public class ColorBarMenu : MonoBehaviour
{
    
    /// If you want to make Hierarchy Inside Gameobject Right click 
    /// This option appears in the pop-up dialog , You need to add this option to "GameObject" Under the table of contents 
    [MenuItem("GameObject/UI/ColorBar")]
    public static void AddColorBarInGameObject()
    {
    

        GameObject parent = null;
        if (null != Selection.activeTransform)
        {
    
            parent = Selection.activeTransform.gameObject;
        }
        else
        {
    
            parent = null;
        }

        if ((null == parent) || (null == parent.GetComponentInParent<Canvas>()))
        {
    
            Canvas canvas = FindObjectOfType<Canvas>();
            if (null == canvas)
            {
    
                Debug.LogError("AddColorBar : can not find a canvas in scene!");
                return;
            }
            else
            {
    
                parent = FindObjectOfType<Canvas>().gameObject;
            }
        }

        GameObject prefab = Resources.Load("Prefabs/ColorBar") as GameObject;
        if (null == prefab)
        {
    
            Debug.LogError("AddColorBar : Load ColorBar Error!");
            return;
        }

        GameObject colorBar;
        if (null != parent)
            colorBar = Instantiate(prefab, parent.transform);
        else
            colorBar = Instantiate(prefab);

        if (null == colorBar)
        {
    
            Debug.LogError("AddColorBar : Instantiate ColorBar Error!");
            return;
        }

        Undo.RegisterCreatedObjectUndo(colorBar, "Created ColorBar");
        colorBar.name = "ColorBar";
    }
}

This script is to add this control directly by right clicking . All source code in :heater404/ColorBar (github.com)
There are two examples in the source code :

 Insert picture description here

原网站

版权声明
本文为[heater404]所创,转载请带上原文链接,感谢
https://yzsam.com/2022/02/202202130625200533.html