onFillVBO to OnPopulateMesh help?

Upgrading to 5.2 my onFillVBO’s are no longer working.

I have a script based on the one posted here:

Within “protected override void OnFillVBO (List vbo){” I’m calculating positions and UV coords for vertices and then adding them to the list.

I’m still getting the polygons drawn to the screen, but they’re no longer in the correct position and have incorrect UV coords.

So is there a quick fix or do I need to change the entire thing to a mesh? If so, can someone point me in the right direction to replicate my current functionality? Everything I’ve tried has resulted in nothing being drawn to the screen.

Oh, and also from 5.1 to 5.2 my frame rate has dropped from 300fps to 75fps with only a few UI objects in the scene :frowning:

Same here ; we are using override for MaskableGraphic.OnFillVBO(List vbo) to draw lines and it seems that it’s no more called ???

Is there a quick workaround ?

Its all been replaced with Mesh rendering… use OnPopulateMesh instead

1 Like

Check out the updated image control for the best way to handle the update.
https://bitbucket.org/Unity-Technologies/ui/src/cc791b3335d2d46b70d932fc70e6ec6c4ea6d561/UnityEngine.UI/UI/Core/Image.cs?at=5.2&fileviewer=file-view-default
You can dif the 5.2 version with a previous version to see the exact changes needed

5 Likes

Thanks Simon. I looked for this yesterday, but didn’t find the 5.2 version.

Was working late last night finishing the 5.2 updates. The LineRenderer especially caused me some grief, the new vertex drawing way of doing things in 5.2 is very different. (but there are helpers)

Much appreciated :slight_smile:

Is there any chance you could help me out with this? I’m not sure why this isn’t filling. There seem to be the correct number of vertices being generated, but it’s not creating the mesh…

using UnityEngine;
using UnityEngine.UI;
using System.Collections.Generic;


[ExecuteInEditMode]
public class UICircle2 : Graphic
{
    [Range(0, 100)]
    public int fillPercent;
    public bool fill = true;
    public int thikness = 5;
    [Range(0, 360)]
    public int segments = 360;

    void Update()
    {
        this.thikness = (int)Mathf.Clamp(this.thikness, 0, rectTransform.rect.width / 2);
    }

    //    protected override void OnFillVBO(List<UIVertex> vbo)
    protected override void OnPopulateMesh(Mesh toFill)
    {
        float outer = -rectTransform.pivot.x * rectTransform.rect.width;
        float inner = -rectTransform.pivot.x * rectTransform.rect.width + this.thikness;

        //        vbo.Clear();
        toFill.Clear();
        var vbo = new VertexHelper(toFill);


        UIVertex vert = UIVertex.simpleVert;
        Vector2 prevX = Vector2.zero;
        Vector2 prevY = Vector2.zero;

        float f = (this.fillPercent / 100f);
        float degrees = 360f / segments;
        int fa = (int)((segments + 1) * f);


        for (int i = 0; i < fa; i++)
        {
            float rad = Mathf.Deg2Rad * (i * degrees);
            float c = Mathf.Cos(rad);
            float s = Mathf.Sin(rad);
            float x = outer * c;
            float y = inner * c;
            vert.color = color;
            vert.position = prevX;
            vbo.AddVert(vert);
            prevX = new Vector2(outer * c, outer * s);
            vert.position = prevX;
            vbo.AddVert(vert);
            if (this.fill)
            {
                vert.position = Vector2.zero;
                vbo.AddVert(vert);
                vbo.AddVert(vert);
            }
            else
            {
                vert.position = new Vector2(inner * c, inner * s); ;
                vbo.AddVert(vert);
                vert.position = prevY;
                vbo.AddVert(vert);
                prevY = new Vector2(inner * c, inner * s);
            }
        }
        vbo.FillMesh(toFill);
        int verts = vbo.currentVertCount;
        Debug.Log(verts);
    }
}

I figured it out with some more major rewrites:

using UnityEngine;
using UnityEngine.UI;
using System.Collections.Generic;


[ExecuteInEditMode]
public class UICircle2 : Graphic
{
    [SerializeField]
    Texture m_Texture;
    [Range(0, 100)]
    public int fillPercent;
    public bool fill = true;
    public int thikness = 5;
    [Range(0, 360)]
    public int segments = 360;

    public override Texture mainTexture
    {
        get
        {
            return m_Texture == null ? s_WhiteTexture : m_Texture;
        }
    }


    /// <summary>
    /// Texture to be used.
    /// </summary>
    public Texture texture
    {
        get
        {
            return m_Texture;
        }
        set
        {
            if (m_Texture == value)
                return;

            m_Texture = value;
            SetVerticesDirty();
            SetMaterialDirty();
        }
    }


    void Update()
    {
        this.thikness = (int)Mathf.Clamp(this.thikness, 0, rectTransform.rect.width / 2);
    }

    protected UIVertex[] SetVbo(Vector2[] vertices, Vector2[] uvs)
    {
        UIVertex[] vbo = new UIVertex[4];
        for (int i = 0; i < vertices.Length; i++)
        {
            var vert = UIVertex.simpleVert;
            vert.color = color;
            vert.position = vertices[i];
            vert.uv0 = uvs[i];
            vbo[i] = vert;
        }
        return vbo;
    }


    //    protected override void OnFillVBO(List<UIVertex> vbo)
    protected override void OnPopulateMesh(Mesh toFill)
    {
        float outer = -rectTransform.pivot.x * rectTransform.rect.width;
        float inner = -rectTransform.pivot.x * rectTransform.rect.width + this.thikness;

        //        vbo.Clear();
        toFill.Clear();
        var vbo = new VertexHelper(toFill);


        UIVertex vert = UIVertex.simpleVert;
        Vector2 prevX = Vector2.zero;
        Vector2 prevY = Vector2.zero;
        Vector2 uv0 = new Vector2(0, 0);
        Vector2 uv1 = new Vector2(0, 1);
        Vector2 uv2 = new Vector2(1, 1);
        Vector2 uv3 = new Vector2(1, 0);
        Vector2 pos0;
        Vector2 pos1;
        Vector2 pos2;
        Vector2 pos3;

        float f = (this.fillPercent / 100f);
        float degrees = 360f / segments;
        int fa = (int)((segments + 1) * f);


        for (int i = 0; i < fa; i++)
        {
            float rad = Mathf.Deg2Rad * (i * degrees);
            float c = Mathf.Cos(rad);
            float s = Mathf.Sin(rad);
            float x = outer * c;
            float y = inner * c;

            uv0 = new Vector2(0, 1);
            uv1 = new Vector2(1, 1);
            uv2 = new Vector2(1, 0);
            uv3 = new Vector2(0, 0);

            pos0 = prevX;
            pos1 = new Vector2(outer * c, outer * s);

            if (fill)
            {
                pos2 = Vector2.zero;
                pos3 = Vector2.zero;
            }
            else
            {
                pos2 = new Vector2(inner * c, inner * s);
                pos3 = prevY;
            }

            prevX = pos1;
            prevY = pos2;

            vbo.AddUIVertexQuad(SetVbo(new[] { pos0, pos1, pos2, pos3 }, new[] { uv0, uv1, uv2, uv3 }));

        }

        if (vbo.currentVertCount > 3)
        {
            vbo.FillMesh(toFill);
        }

    }
}

Thank you again for your LineRenderer example. But I’m still not sure why the previous one wasn’t working?

I had the same issue updating the LineRenderer, had to use DrawQuad instead of AddVert. no idea why it failed but the mesh was reporting a valid number of vertices, possibly a winding order issue maybe?
Looks like you did the same thing.

Now back to work for the other primitives :smile:

Did a miss a version where OnFillVBO was deprecated? I’m sort of astounded that it was Obsoleted like this and that the doc page still has an example using OnFillVBO.

That was the issue I came up against. Once again, I just copied your code and it worked :stuck_out_tongue:

@ddf OnFillVBO was depreciated in 5.2. Documentation still needs to catch up, but you can find examples at bitbucket linked to by Simon earlier in the thread.

1 Like

@ddf it was deprecated for a fairly good reason, they moved from a custom vertices approach to using regular Unity 3D meshes, so the old functions (from 5.2 onwards) didn’t make sense any more.
So all the functions are now mesh based and all the vertext / color / uv information is now stored in separate arrays. kind of makes sense to unify it so there is less to manage / maintain going forward. Docs will take a while to update as @zge stated

I agree with @SimonDarksideJ , and this seems to be a great move so far, but I also think @ddf has a point in that an “in-between” version where both methods worked would have been nice and less abrupt, giving us some more leeway to adapt. I mean, we’re not totally unified yet anyway, as UIVertex still exists. So no, you didn’t miss a version, it just went straight to Obsolete. =)

1 Like

I had same problem.
I solved it.

[ExecuteInEditMode]
public class DiamondGraph : Graphic
{
public float a;
public float b;
public float c;
public float d;

protected override void OnPopulateMesh(Mesh m)
{
List<UIVertex> verts = new List<UIVertex>();

float wHalf = rectTransform.rect.width / 2;
float hHalf = rectTransform.rect.height / 2;
a = Math.Min(1, Math.Max(0, a));
b = Math.Min(1, Math.Max(0, b));
c = Math.Min(1, Math.Max(0, c));
d = Math.Min(1, Math.Max(0, d));

Color32 color32 = color;
using (var vh = new VertexHelper())
{
vh.AddVert(new Vector3(-wHalf * a, 0), color32, new Vector2(0f, 0f));
vh.AddVert(new Vector3(0, wHalf * b), color32, new Vector2(0f, 1f));
vh.AddVert(new Vector3(wHalf * c, 0), color32, new Vector2(1f, 1f));
vh.AddVert(new Vector3(0, -wHalf * d), color32, new Vector2(1f, 0f));

vh.AddTriangle(0, 1, 2);
vh.AddTriangle(2, 3, 0);
vh.FillMesh(m);
}
}
}
1 Like

Ah, thanks koohddang.

I suspected triangles weren’t being automatically generated as with onFillVBO. There’s probably more control your way but I was too lazy to find out…

You ok with your diamond primitive being added to the UI Extensions @koohddang ?
Great work digging out that little nugget.

1 Like

Good luck with this guys, they just changed the API for OnPopulateMesh() in 5.2.1p1

Go back to 5.1

^^^ OnPopulateMesh(Mesh tofill) is now obsolete too. It lasted all of two weeks! Thanks Unity.

Wait, for real…?! In the meantime, I adopted my Asset to be both 4.6-5.0 and 5.1+ compatible before submitting. I s*** you not, they actually managed to change the API before my Asset even got approved… sigh Guess I’ll have to take a look at this new API then… Thanks for the heads-up @wikmanyo .