- Home /
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?
Answer by Guy-Corbett · Mar 07, 2015 at 05:46 PM
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.
Answer by Glurth · Mar 07, 2015 at 02:49 PM
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.
Thanks for taking a look at the problem, however I can't really see how how this helps. $$anonymous$$y canvas is set to scale with the screen size, as far as setting up the positions of my rects and anchors, everything works fine. I can resize the window and it all just works. This was never an issue.
The only problem I was ever having was with converting mouse positions to canvas space. Initially I was trying to solve that by dividing the mouse x position by the screen width then multiplying by the scaler's reference resolution's width. Like I said in my previous comment I've now got it working by dividing by the screen width then multiplying the panel's sizeDelta.x - which is almost the opposite of what I would expect to work!
If I've understood the variables correctly the reference resolution is the size of the panel in it's local space. You effectively describe a situation where the reference resolution is (1, 1). Whereas sizeDelta is it's size in pixels. But clearly I must have that wrong somewhere...