New UI and line drawing

Hi, we’d like to do simple line drawing working within an NGUI panel, using Vectrosity. Apparently this is a popular request. Given how difficult it is to do with the source of both NGUI and Vectrosity available, how difficult will it be once NGUI is made native in Unity 4.6? Won’t it be next to impossible?

Will Unity 4.6 have a UI system that can do simple line drawing?

You seem to have some misconceptions about the new UI. First of all, uGUI is not “NGUI made native”. It’s not NGUI and it’s not (all) native. Most of the UI elements have their source available. Second, you’re trying to combine two systems (NGUI and Vectrosity) that were never designed for each other; why would you expect it to be easy?

Now that we’re past that, line drawing ought to be simple as pie in the new system… though not with Vectrosity, at least not with a current version of vectrosity; any line drawing system would have to have uGUI. Since it supports really simple 9-slicing and can therefore correctly stretch a line texture to any size, a DrawLine(a,b,someSprite) function only needs to set the position, rotation, and scale so that each end is at one of the points. (That’s assuming that there isn’t a native one)

If you need to make UI Component that draws line, just use this one from me:

public class UILineRenderer : MaskableGraphic
    {
        public float LineThikness = 2;
        public bool UseMargins;
        public Vector2 Margin;
        public Vector2[] Points;

        protected override void OnFillVBO(List<UIVertex> vbo)
        {
            if (Points == null || Points.Length < 2)
                Points = new[] { new Vector2(0, 0), new Vector2(1, 1) };

            var sizeX = rectTransform.rect.width;
            var sizeY = rectTransform.rect.height;
            var offsetX = -rectTransform.pivot.x * rectTransform.rect.width;
            var offsetY = -rectTransform.pivot.y * rectTransform.rect.height;

            if (UseMargins)
            {
                sizeX -= Margin.x;
                sizeY -= Margin.y;
                offsetX += Margin.x/2f;
                offsetY += Margin.y/2f;
            }

            vbo.Clear();

            Vector2 prevV1 = Vector2.zero;
            Vector2 prevV2 = Vector2.zero;

            for (int i = 1; i < Points.Length; i++)
            {
                var prev = Points[i - 1];
                var cur = Points[i];
                prev = new Vector2(prev.x * sizeX + offsetX, prev.y * sizeY + offsetY);
                cur = new Vector2(cur.x * sizeX + offsetX, cur.y * sizeY + offsetY);

                float angle = Mathf.Atan2(cur.y - prev.y, cur.x - prev.x) * 180f / Mathf.PI;

                var v1 = prev + new Vector2(0, -LineThikness / 2);
                var v2 = prev + new Vector2(0, +LineThikness / 2);
                var v3 = cur + new Vector2(0, +LineThikness / 2);
                var v4 = cur + new Vector2(0, -LineThikness / 2);

                v1 = RotatePointAroundPivot(v1, prev, new Vector3(0, 0, angle));
                v2 = RotatePointAroundPivot(v2, prev, new Vector3(0, 0, angle));
                v3 = RotatePointAroundPivot(v3, cur, new Vector3(0, 0, angle));
                v4 = RotatePointAroundPivot(v4, cur, new Vector3(0, 0, angle));

                if (i > 1)
                    SetVbo(vbo, new[] { prevV1, prevV2, v1, v2 });

                SetVbo(vbo, new[] { v1, v2, v3, v4 });

                prevV1 = v3;
                prevV2 = v4;
            }
        }

        protected void SetVbo(List<UIVertex> vbo, Vector2[] vertices)
        {
            for (int i = 0; i < vertices.Length; i++)
            {
                var vert = UIVertex.simpleVert;
                vert.color = color;
                vert.position = vertices[i];
                vbo.Add(vert);
            }
        }

        public Vector3 RotatePointAroundPivot(Vector3 point, Vector3 pivot, Vector3 angles)
        {
            Vector3 dir = point - pivot; // get point direction relative to pivot
            dir = Quaternion.Euler(angles)*dir; // rotate it
            point = dir + pivot; // calculate rotated point
            return point; // return it
        }
    }
7 Likes

Unity already has a simple line renderer (in case you aren’t aware of it). For some more power in your line API, I understand the latest version of Vectrosity is designed specifically for the new Unity GUI. There is a new Vectrosity thready for this.

I am currently working on this area myself. My approach so far has been to develop a 2D drawing API. I have mostly finished a lower level path style API (e.g. LineTo(), SmoothCurveTo() etc) and a higher level DisplayList style structure which can take dynamic transform lists and allows hierarchical display/ordering of paths. I’m also working on path renderers, e.g. stroking, filling, but also distributing objects along a path, like particle effects. I’m still some way off having it ready for the asset store though. I would love to know if this sort of thing is something people would want.
/horn-tooting

1 Like

The LineRenderer component is not suitable for drawing lines in the new UI, it’s actually just irrelevant in this context.

2 Likes

Hey, I was having some difficulty with this script, and I modded it to support using textures directly (so you can drop in sprites), to support non relative positioning (so it doesn’t take in account the width/height of the rect it is in), and to support line capping (so the beginning and ends of the lines can be rounded based on a circle sprite image).

1973285–127878–UILineRenderer.cs (4.48 KB)

2 Likes

Looks like an awesome effect, will need some work documenting it to make sense of its use.

@jonbro5556 @jack.sydorenko You guys ok with this script being added to the UI extensions bitbucket repo? (link in sig)

I might have a go at making something… I have a few ideas that might be quite cool.

You can draw line scaling uImage.

@SimonDarksideJ I don’t have a problem with that at all, but @jack.sydorenko did the heavy lifting initially.

Is there any way to update the graphics (line) via script? My problem is, that when I set the points array via script the line isn’t updated. If I change a point in the editor it updates just fine.

Edit.: I just found the solution. After u set the points via script just call SetVerticesDirty() on the UILineRenderer-object.

1 Like

This script seems very interesting, thank you for sharing!

However, as said SimonDarksideJ, is it possible to comment more the code to explain how it works in practice?

Again, thank you.

Thanks a lot for the script! The @jonbro5556 version seems to have broken the relative positioning, so I used the original by @jack.sydorenko .

I’m sorry for posting in the old thread, but could someone explain me how to implement the above code? I need to draw a line between two gui elements and from what you people say this seems to be close to it, but for the life of mine I don’t understand that piece of script and how it draws a line on gui elements?

Should I mention that I am new to unity :smile: Though not new to C# and scripting…

I’m trying to draw a line between two points that I selected via the UI. How do I set that up on @jack.sydorenko 's code? o.o

The script is now part of the UI extensions project along with many other great community controls.
It is mainly for drawing lines within the bounds of the object or scene, not really for drawing a line between two RectTransforms.

But you can use the line rendering code to create a new control that takes two RectTransforms to draw a line between them, I’ve seen various request for this so far. If I get time I’ll add one to the project, or you can contribute and add your own version.

you can use this plugin to draw lines and more procedural shapes in new gui

1 Like

I mean, if we’re plugging in a revived thread anyway… :wink: Primitive UI is a similar package that supports a wide variety of shape and line drawing methods. Anyone reading this should of course pick the one they feel serves their purposes best; my asset seems to support some more primitives, but lacks rounded rectangles for instance.

(Sorry Andy!)

1 Like

Looks good @andrii-shpak although most seem to be based of the UI Extensions versions :smile: obviously with improvements :stuck_out_tongue:
Good luck with your asset.

@Senshi How are you handling the 5.2.1 / 5.2.1P issues, or have you avoided controls that are affected?

From the asset description:

I have uploaded a VBO version from 4.6.1 and a “toFill” version from 5.2.0. Once the new API is in and we get some sort of “yes, it’s finalized” message from the devs I’ll also upload a version from either P3 or 5.2.2 if the window between them is small enough.

It’s not the nicest solution, but it is the most managable.

(Slighty off-topic: There were some editor changes as well between 5.0 and 5.1 or so iirc, which I just handled using an “IF UNITY_5_0” or some-such statement.)