Author Topic: Positioning Objects Relative to a Scaling Background  (Read 3180 times)

doggan

  • Newbie
  • *
  • Thank You
  • -Given: 0
  • -Receive: 0
  • Posts: 13
    • View Profile
Positioning Objects Relative to a Scaling Background
« on: February 20, 2014, 03:26:53 AM »
I have a 2d background that stretches with the screen size, while maintaining it's aspect ration (using aspectRation = BasedOnWidth, and an Advanced Anchor anchoring to the left/right sides of the screen).

I need to position/scale many other UI objects relative to this background.

For example, an object is positioned at (x = 100, y = 100) with a scale of (1.0, 1.0, 1.0) when the screen resolution is 960x640. When the screen is resized to 640x960, the background shrinks by 0.66 (changeInWidth = newWidth / prevWidth = 640 / 960 = 0.66). Therefore the new position of my object will be at (x = 66, y = 66) with a scale of (0.66, 0.66, 0.66).

I am wondering what the best way to do this in NGUI is?

I've tried creating a custom script and hooking in to the OnDimensionsChanged of the background's UIWidget, and then adjusting the positions/scales of the relatively positioned objects following the calculation above... while also handling edit mode screen resizes + remembering the previous settings before the screen change... etc. It seems to be getting overly complicated, so I'm wondering if there's a better way this. I'm thinking there may be some way to handle this with the new anchor system with Advanced / Custom settings, but I can't seem to figure it out.

Thanks in advance.


Edit:

I simplified the code and came up with the solution below to calculate my positions relative to the background (_target widget). Still not sure what the best way to handle scale is though, since NGUI automatically scales the sprites due to the use of FixedSize (which is based on height). But in this case, I want to scale based on the width of the background texture, and not the height of the window...

  1.         [ExecuteInEditMode]
  2.         public class Positioner : MonoBehaviour
  3.         {
  4.                 /// <summary>
  5.                 /// The background target widget.
  6.                 /// </summary>
  7.                 [SerializeField]
  8.                 private UIWidget _target;
  9.                 [SerializeField]
  10.                 private Vector2 _relativePosition;
  11.  
  12.                 private void Update ()
  13.                 {
  14.                         if (_target != null) {
  15.                                 Vector3 bottomLeft = _target.worldCorners [0];
  16.                                 Vector3 topRight = _target.worldCorners [2];
  17.                                 float width = topRight.x - bottomLeft.x;
  18.                                 float height = topRight.y - bottomLeft.y;
  19.  
  20.                                 // Calculate world coordinates relative to bottom left of target widget.
  21.                                 Vector3 worldPos = new Vector3 (
  22.                                         bottomLeft.x + width * _relativePosition.x,
  23.                                         bottomLeft.y + height * _relativePosition.y,
  24.                                         0.0f);
  25.  
  26.                                 this.transform.position = worldPos;
  27.                         }
  28.                 }
  29.         }
« Last Edit: February 20, 2014, 09:38:25 AM by doggan »

ArenMook

  • Administrator
  • Hero Member
  • *****
  • Thank You
  • -Given: 337
  • -Receive: 1171
  • Posts: 22,128
  • Toronto, Canada
    • View Profile
Re: Positioning Objects Relative to a Scaling Background
« Reply #1 on: February 20, 2014, 09:45:22 AM »
Why are you doing this at all? Why don't you just use anchors?

charliehelman

  • Newbie
  • *
  • Thank You
  • -Given: 3
  • -Receive: 2
  • Posts: 16
    • View Profile
Re: Positioning Objects Relative to a Scaling Background
« Reply #2 on: February 20, 2014, 04:06:19 PM »
Why are you doing this at all? Why don't you just use anchors?

Can you provide an example where anchors would solve the problem with this use case? I've been working on a similar problem with no luck so far using anchors.

My problem is: I have a row of buttons that do not fit on iPhone 4 screens. Previously, the buttons were just anchored legacy style to the bottom left corner of the screen. Now, I need them to scale down in size so that all of the buttons fit on screen.

My thought was to make all the buttons a child object of a container (empty widget) or a panel, anchor that container so that it fits the screen correctly where the buttons should be, then I expected all the child objects to scale to fit inside that widget (because they're child objects, and... huh, as I type this I'm not sure I anchored the buttons to the container widget correctly. I'll try again, but had trouble getting this solution to work.)

Does that make sense?

Anyway, I'm sure the OP and I would both benefit from a quick example. I'll check back in once I give my idea another try (to verify I did it correctly before). Do I have the right idea? Is that what you meant by "just use anchors!"?

EDIT: In this case OP would just anchor his widgets to the "scaling background", which would make it work correctly as in this example: https://www.youtube.com/watch?v=P8JTTE0JBXQ

In retrospect, I must have anchored my buttons incorrectly. Let me give it another try and I'll check back.

doggan

  • Newbie
  • *
  • Thank You
  • -Given: 0
  • -Receive: 0
  • Posts: 13
    • View Profile
Re: Positioning Objects Relative to a Scaling Background
« Reply #3 on: February 20, 2014, 09:10:31 PM »
Thanks for the replies.

I was correctly able to anchor my objects relative to the scaling background texture. I used the Unified anchor type with the background texture as the target, and custom anchor points specifying the relative offsets.

This still doesn't solve the scaling issue, though, since I need these objects to scale based on the background texture's width. I probably need to do something similar to manually adjusting the UIRoot as shown here: http://www.tasharen.com/forum/index.php?topic=2397.0

Will post back when/if I figure it out.

doggan

  • Newbie
  • *
  • Thank You
  • -Given: 0
  • -Receive: 0
  • Posts: 13
    • View Profile
Re: Positioning Objects Relative to a Scaling Background
« Reply #4 on: February 20, 2014, 09:39:27 PM »
Based off ArenMook's original script, the following code solves my problem, by making the manual height calculate based on the width of the screen:

  1. using UnityEngine;
  2.  
  3. [RequireComponent(typeof(UIRoot))]
  4. public class UIRootAdjustment : MonoBehaviour
  5. {
  6.         public int targetHeight = 720;
  7.        
  8.         UIRoot mRoot;
  9.        
  10.         void Awake () { mRoot = GetComponent<UIRoot>(); }
  11.        
  12.         void Update ()
  13.         {
  14.                 mRoot.manualHeight = Mathf.RoundToInt(targetHeight * ((float)Screen.height / Screen.width));
  15.         }
  16. }

Thanks for leading me in the right direction :)

ArenMook

  • Administrator
  • Hero Member
  • *****
  • Thank You
  • -Given: 337
  • -Receive: 1171
  • Posts: 22,128
  • Toronto, Canada
    • View Profile
Re: Positioning Objects Relative to a Scaling Background
« Reply #5 on: February 21, 2014, 03:20:32 PM »
All widgets have an "Aspect Ratio" field that you can set. If set, it can automatically resize the widget based on width or height.