oddgames / UIToolkit

Single draw call UI solution for Unity with multi resolution support and more.
518 stars 153 forks source link

How to properly position? #105

Open frarees opened 12 years ago

frarees commented 12 years ago

Hi,

I'm trying to make a in-game menu layout, so I decide to create a simple menu containing 2 UIHorizontalLayouts "stacked" with 3 elements each, so:

but1 | but2 | but3 but4 | but5 | but6

So, I write this, that makes some sense to me:

        var layout1 = new UIHorizontalLayout(spacingBetweenItems);
        layout1.beginUpdates();
        layout1.verticalAlignMode = UIAbsoluteLayout.UIContainerVerticalAlignMode.Top;
        layout1.addChild(but1, but2, but3);
        layout1.pixelsFromTopLeft(bannerHeight + spacingBetweenItems, spacingBetweenItems);
        layout1.endUpdates();
        layout1.matchSizeToContentSize();

        var layout2 = new UIHorizontalLayout(spacingBetweenItems);
        layout2.beginUpdates();
        layout2.verticalAlignMode = UIAbsoluteLayout.UIContainerVerticalAlignMode.Top;
        layout2.addChild(but4, but5, but6);
        layout2.pixelsFromTopLeft((int)(layout1.height + Mathf.Abs(layout1.position.y)) + spacingBetweenItems, spacingBetweenItems);
        layout2.endUpdates();
        layout2.matchSizeToContentSize();

The interesting part is layout2.pixelsFromTopLeft((int)(layout1.height + Mathf.Abs(layout1.position.y)) + spacingBetweenItems, spacingBetweenItems);. In my case, layout1.position.y gives me a negative value (still don't know why, so if someone know an explanation would be appreciated), so that's why I use the absolute value (yeah, it's more like a temporal fix or something like).

I'm using iPhone's HD resolution (640x960) and things work fine, but when I do on iPhone's resolution (320x480) things doesn't seem to work the same way.

However, I've come up with something: iPhone: layout1.position.y is -59 iPhone HD: layout1.position.y is -118

This is a double size (which makes sense, IMHO). And if I hardcode 118 instead of Mathf.Abs(layout1.position.y), things work great! What's the problem? What should I do? There's a better way of doing all of this?

Note that I'm using 2x textures when switching to iPhone HD

frarees commented 12 years ago

It seems to me that there's a size factor (2:1 in that case) I'm not applying (or UIToolkit is not applying), and it affects to pixel positioning. Am I right?

FrittenKeeZ commented 12 years ago

First of all you should use the positioning methods (pixelsFromXxxYyy and positionFromXxxYyy) AFTER endUpdates and matchSizeToContentSize are called. When switching to HD all pixel positioning methods multiply the values with 2, so the positions stay relatively the same.

frarees commented 12 years ago

After doing so, I'm still having the same problem. I'm doing:

        var layout2 = new UIVerticalLayout(spacingBetweenItems);
        layout2.beginUpdates();
        layout2.verticalAlignMode = UIAbsoluteLayout.UIContainerVerticalAlignMode.Top;
        layout2.addChild(but4, but5, but6);
        layout2.endUpdates();
        layout2.matchSizeToContentSize();
        layout2.pixelsFromTopLeft((int)(layout1.height + Mathf.Abs(layout1.position.y)) + spacingBetweenItems, spacingBetweenItems);
FrittenKeeZ commented 12 years ago

Can you position the layouts without adding anything from layout1? I mean do they display correctly if you try to do, pixelsFromTopLeft, pixelsFromBottomLeft, pixelsFromTopRight and pixelsFromBottomRight?

frarees commented 12 years ago

Yes, they do. As I said, And if I hardcode 118 instead of Mathf.Abs(layout1.position.y), things work great!, so:

        var spacingBetweenItems = 9;
        ...
        var layout2 = new UIVerticalLayout(spacingBetweenItems);
        layout2.beginUpdates();
        layout2.verticalAlignMode = UIAbsoluteLayout.UIContainerVerticalAlignMode.Top;
        layout2.addChild(but4, but5, but6);
        layout2.endUpdates();
        layout2.matchSizeToContentSize();
        layout2.pixelsFromTopLeft(109 + spacingBetweenItems, spacingBetweenItems); // 118, hardcoded instead of using his layout above

Works great in both SD & HD. However, I don't want to hardcode this, but get a relative to it's above layout distance.

FrittenKeeZ commented 12 years ago

What does layout1.height report just before you begin your work on layout2? I don't think you should use the position.y value. Since the height will change whether it's in SD or HD mode, you probably need to do something like:

int factor = UI.instance.isHD ? 2 : 1;
layout2.pixelsFromTopLeft(layout1.height / factor + spacingBetweenItems, spacingBetweenItems);
frarees commented 12 years ago

That's what I thought, that there's a factor needed to be applied if using UIObject's properties. So if you don't encourage using position.y, how can I get my desired behavior? (stacked horizontal layouts, just like horizontal layouts nested inside a vertical layout would work... something like a table, let's say)

FrittenKeeZ commented 12 years ago

Thinking about you can use position.y, but you need to account for the HD factoring.

int factor = UI.instance.isHD ? 2 : 1;
layout2.pixelsFromTopLeft((int) ((Mathf.Abs(layout1.position.y) + layout1.height) / factor) + spacingBetweenItems, spacingBetweenItems);
frarees commented 12 years ago

Great, let me give it a try.