PDA

View Full Version : Menu auto-scaling



BigBMan
11-11-2010, 07:05 AM
Trying to figure out how to auto scale the background in RT3DApp. It stays at iPhone resolution in Windows - even when I change the resolution in main.cpp.

More general question - can you layout Entities to auto scale/position based on resolution?

rzuf
11-11-2010, 01:32 PM
Go to App::Init() and check the SetupFakePrimaryScreenSize() function. :)

BigBMan
11-16-2010, 08:02 AM
what I'm looking for is a way just to resize the background element - not all elements. Trying to figure out how the various key controls (already in source) will set landscape mode and size in windows. It doesn't appear to be working currently.

Seth
11-16-2010, 10:30 AM
what I'm looking for is a way just to resize the background element - not all elements. Trying to figure out how the various key controls (already in source) will set landscape mode and size in windows. It doesn't appear to be working currently.

Hmm, I'm not clear on what you want to do.

The demo menu uses a bitmap bg that is 480X320. As rzuf suggested, it is possible to auto-scale it up by doing this:

in main.cpp I set the video to 1024X768 (named "Windows", but you can add your own resolutions easily)




string desiredVideoMode = "Windows"; //name needs to match one of the ones defined below
g_landScapeNoNeckHurtMode = true; //if true, will rotate the screen so we can play in landscape mode in windows without hurting ourselves


In bool App::Init() near the top I add:


SetupFakePrimaryScreenSize(320,480); //game will think its this size, and will be scaled up


See attached screenshot for the output. Yep, it's big and blurry and blown up.

483

If we actually choose a menu option we get something like this:
484

Ew! Giant blurry controls! This is because the GUI artwork is also being scaled up too from the iPhone size, and at a different aspect ratio at that.

If you comment out the SetupFakePrimaryScreenSize(320,480); command from earlier, the GUI art is not scaled and looks much better, but now the menu is too small.

For a real PC sized game you would just design new menu art and bigger fonts. If you want control on a piece-by-piece basis, you can do that, just scale the entity in question up or down.

A handy function for that is:
void EntitySetScaleBySize(Entity *pEnt, CL_Vec2f vDestSize), in EntityUtils.cpp.

You could use this line in MainMenu.cpp to scale only the BG up (I've taken the SetupFakePrimaryScreenSize out):


Entity * MainMenuCreate(Entity *pParentEnt)
{
Entity *pBG = CreateOverlayEntity(pParentEnt, "MainMenu", "interface/summary_bg.rttex", 0,0);
EntitySetScaleBySize(pBG, GetScreenSize()); //only this line is new
AddFocusIfNeeded(pBG);
...etc

Now we get this:
485

The BG is blurry and huge, but the button positions/sizes are not changed, and the examples themselves probably look better.

Anyway, hope that gives you an idea.

BigBMan
11-18-2010, 04:21 AM
Exactly was I was looking for! Thanks for the detailed response!

I realize scaling Entities is a sloppy way to go, but I'm prototyping for now ;o)

a couple of annoyances if you don't mind (Windows build):

1. Sometimes the icon is stuck as an hourglass
2. The debug output is clipped at the top of the screen (Windows XP - big window borders). How would I move this around and/or modify it? Is it an entity as well?

BigBMan
12-01-2010, 03:00 AM
So I tried doing this where SetupFakePrimaryScreenSize is not called from App::Init(). GetScreenSize() returns a zero value vector, which causes my app to crash.

How can I use the *actual* screen size to scale to what the hardware display's resolution is?

Seth
12-01-2010, 09:05 AM
Not sure I understand.. you want your 1024X768 game to scale to whatever the user's computer screen resolution is currently at?

If so, hold on a day or two, I'm about to commit some big improvements to the Windows side that may help.

For instance, I added support for 'dragging' a custom window size and and a new GetBaseApp()->SetVideoMode() to set to any specific native resolution on the fly. (Only does stuff on Windows as this wouldn't make sense on iOS/Android)

Will commit when it looks bug free.

BigBMan
12-03-2010, 04:32 AM
Not sure what I was doing wrong, but it seems to be working now. The base entity was not reporting the iPhone simulator's screen size by default. I think I'm OK now, thanks.

Seth
12-04-2010, 11:58 PM
Windows scaling/pseudo full screen toggle committed. Added a "fullscreen toggle" button to RTSimpleApp

Le Viet Bach
02-01-2011, 04:22 PM
I'm having problems with scaling too.
I want to setup a system that automatically does letterbox scaling based on screen resolution.

I thought it would just be as easy as scaling and translating the root entity.

However, it seems that an entity doesn't pass its full transformation matrix to its children, just position.

How can I setup such things based on what we have now?

Edit: I figured it out.
I can setup a fake screen resolution that preserves the aspect ratio of the real resolution but still small enough to fit the expected resolution.
UI elements that "docks" at screen borders may need some repositioning. I think I will setup some helper functions and entities for this.

This is what I'm using


float screenX = GetScreenSizeXf();
float screenY = GetScreenSizeYf();
float ratio = screenX / 480.f;//use screen X to scale so that all content lies in the screen. A black border will be shown though. May be I'll cover it with decoration?
float scaledY = screenY / ratio;
//------------------------------------------------------------
SetupFakePrimaryScreenSize(scaledY, 480);
//or for portrait mode
SetupFakePrimaryScreenSize(480, scaledY);

Le Viet Bach
02-01-2011, 06:01 PM
I'm running into some problems here.

I want movement speed of objects to be independent of resolution so I used SetupFakePrimaryScreenSize to setup automatic scaling.

However, it would be nice to have the app loads high res texture on high res devices. But AddIPADToFileName uses the fake resolution.

I can write another function/ modify AddIPADToFileName to use the original resolution but high res texture are twice as big. They are scaled up again due to the fake screen size.

I'm thinking of two approaches to this:
-Add a variable to OverlayRenderComponent ie: isHighRes. If it is true the component will scale the highres texture down ( so that when it is scaled up due to the fake resolution, it will look nice). I'm still not sure how to make the texture substitution process as intuitive as possible.
-Use a scale factor for all movement, measurement data.

What is your thought on this? Btw, what approaches did you use for Dink SmallWood HD?

Seth
02-02-2011, 12:04 AM
I want to setup a system that automatically does letterbox scaling based on screen resolution.

I thought it would just be as easy as scaling and translating the root entity.

However, it seems that an entity doesn't pass its full transformation matrix to its children, just position.

This is correct. The entity system is "pure" in that the concept of position and scale is not hardcoded into it, but this makes passing down relative attributes in a hierarchy unwieldy to do.

It works easy enough for ONE attribute at a time generically, for instance, this is how it gets relative position to its parent when rendering:


GetParent()->CallFunctionRecursivelyWithUpdatedVar("OnRender", pVList, string("pos2d"), 0, Entity::RECURSIVE_VAR_OP_ADDITION_PLUS_ALIGNMENT_O FFSET);


So, I guess I we could write a Entity::CallFunctionRecursivelyWithTwoUpdatedVars and add scale, but what do I do when we need rotation or another variable? Should I break down and sent an entire matrix? Break the generic rule and hardcode concepts like position and scale into the entity, like Irrlicht does? Hrm, hard questions.

I don't really know. For now I've been working around these limitations on a case by case basis, for instance, in the RTLooneyLadder example I wanted to be able to "zoom in and out of the world map" - I did this by creating a custom RenderOverlayComponent that handled it manually, ugly.

I'd like to add automatic letterboxing at a low level later by setting a desired aspect ratio and having it just "work".


I'm thinking of two approaches to this:
-Add a variable to OverlayRenderComponent ie: isHighRes. If it is true the component will scale the highres texture down ( so that when it is scaled up due to the fake resolution, it will look nice). I'm still not sure how to make the texture substitution process as intuitive as possible.
-Use a scale factor for all movement, measurement data.

What is your thought on this? Btw, what approaches did you use for Dink SmallWood HD?

With Dink's menus, I manually set all GUI component coordinates. I really only had to do this for two screen resolutions, 1024X768 and 480X320. The "fake screen" is set to one of those at the start, I choose it using GetEmulatedPlatformID(), and all menu code is going to look at that fake size to figure out which art media and positions to use.

As for timing, my menu movement is all based on "milliseconds to get there" so timing is independent of the pixels it has to cover. (for example, ZoomToPositionEntity or SlideScreen and all(?) of the other helpers in EntityUtils.h work this way)

Of course, because of the screensize differences when setting the positions, I use the iPhoneMap* helper functions so the screen positions are converted if needed.


-Add a variable to OverlayRenderComponent ie: isHighRes. If it is true the component will scale the highres texture down

I guess this would work, or by running a ScaleDownEntitySizeIfNeeded(pEnt) function on all of them.

In Dink, I have the game part running internally at 640X480 (the pre-port size) and manually setting the projection matrix and converting input tap/clicks to those coordinates. (the game part uses "Surface" classes directly to render everything, no components)

The menus/GUI overlays are standard components and run at 1024X768 or 480X320 and each has their own artwork. If I had to use the wrong size artwork, I'd probably scale the entity up/down on a case by case basis. I actually do scale some low res art up on the About menu. (the ads for other games.. the helper function I use is EntityRetinaRemapIfNeeded)

Hmm, long reply. In summary, I don't really have any good answers, just work around built on work around. :sweatdrop: In the end I end up having to tweak visuals and positions for each platform a bit. Otherwise the dpad is too big here, too small there, too squished there, etc.

Le Viet Bach
02-04-2011, 05:20 PM
This is correct. The entity system is "pure" in that the concept of position and scale is not hardcoded into it, but this makes passing down relative attributes in a hierarchy unwieldy to do.


So, I guess I we could write a Entity::CallFunctionRecursivelyWithTwoUpdatedVars and add scale, but what do I do when we need rotation or another variable? Should I break down and sent an entire matrix? Break the generic rule and hardcode concepts like position and scale into the entity, like Irrlicht does? Hrm, hard questions.

How about something like OpenGL matrix stack? Instead of using CallFunctionRecursivelyWithUpdatedVar, a render component will push its current transformation into a global stack, children will calculate it's absolute transformation based on the top matrix in the stack. Just like how a scenegraph is implemented.
It can also get rid of the whole eRecursiveVarOp, system.

I don't think sending a matrix will make the current system any less generic than what it is now since you are already sending position. Transformation matrix is something that is needed for a renderable object. Besides, the OnRender function is only called on renderable entities, so it's fine for those entity to be aware of transformation.

Seth
02-07-2011, 02:10 AM
Hmm, push and pop stuff on the stack directly as we walk the entity tree during render?

Yeah, I think I can see this working ok without any huge changes.

We're limited to a hw stack depth of 16 on the model view matrix on some mobile devices (I *think* that's the lowest we'll see..) , so we'd have to watch our hierarchy a bit unless we want to maintain it ourself in software.