Screen to canvas space

Hi,

My problem boils down to me wanting convert from screen space to canvas space when my canvas is set to scale with screen size. I could change the canvas to not be scaled but other parts of this project require it. Any thoughts on what I’m doing wrong?

Some more detail: I want to make UI elements that the user can resize by dragging their borders, like a standard program window. So far I’m just trying to make a box whose right hand edge you can drag to resize. My set up looks like this.

I have a canvas whose UI scale mode is set to scale with screen size. In that I have a panel called Window anchored to the top left of the canvas, at a x position of 0. Inside that I have a second panel called Right Border along the right hand side of Window, anchored to it’s right hand corners.

I’ve set up a script on Right Border which should let the user drag it to resize Window horizontally. This works fine if my app window is 800 pixels wide (800 pixels is my canvas’ reference width). However if its larger the panel grows faster than the mouse moves and over takes it. I’ve attempted to take account of this but so far had no joy. My script’s OnDrag function looks like this;

    public void OnDrag()
    {
        float delta = Input.mousePosition.x - m_mainPanelRect.anchoredPosition.x;
        if (m_parentCanvasScaler.uiScaleMode == CanvasScaler.ScaleMode.ScaleWithScreenSize)
        {
            //delta = (delta / (float)Screen.width) * m_parentCanvasScaler.referenceResolution.x;
        }

        float newx = Mathf.Max(delta, 1.0f);
        m_mainPanelRect.sizeDelta = new Vector2(newx, m_mainPanelRect.rect.height);
    }

m_mainPanelRect is the rect of the Window panel and m_parentCanvasScaler is the scaler from the canvas. That commented out line is my attempt at fixing it but if I enable it the panel doesn’t grow nearly quickly enough and gets left behind the mouse.

The problem boils down to me wanting to set the size of a UI element on a scaled canvas, when I only know what size I want it to occupy on screen. I could change the canvas to not be scaled but other parts of this project require it. Any thoughts on what I’m doing wrong?

I’m not really sure why my original code didn’t work but I’ve got it working now by changing my OnDrag function to the following.

    public void OnDrag()
    {
        float delta = ((Input.mousePosition.x / (float)Screen.width) * m_canvasRect.sizeDelta.x) - m_mainPanelRect.anchoredPosition.x;
        float newx = Mathf.Max(delta, 1.0f);
        m_mainPanelRect.sizeDelta = new Vector2(newx, m_mainPanelRect.rect.height);
    }

I’m not going to mark this as answered as I’d still like to know what I was doing wrong before.

When you are scaling your canvas to the screen size, I would think you would want to define everything with values between 0 and 1 (which defines a “fraction” of the parent rect - or canvas if no other parent)

So, for for that right border adjust it’s “Rect anchors”- like this:

Min: x:0.9f y=0 // this X value will make the left side of the rect cover 10% of it’s parent’s right side. The Y value means top of the parent. Note: the xmin=0.9f is the only value you would need to change when dragging the left size of the rect.

Max: x=1.0f y=1 // this will make the right side flush with the parents right side, the Y value means bottom of the parent.

“Left” and “right” Rect values would be zero. (offset from the borders we just defined)

The advantage to using this method, is that it will work not just for a canvas, but ANY Rect with a child, even other re-sizable controls.

Scroll down to the animated Gifs on this page, they are worth a thousand words:
http://docs.unity3d.com/Manual/UIBasicLayout.html

The trickiest part will be converting your mouse position into a percentage. Let me know if you want some more help with that.