Game Development Community

Not getting correct extents after resolution change

by Todd D. Degani · in Torque Game Engine · 05/02/2005 (9:38 am) · 8 replies

Here is the situation.

Basically I am trying to get the extents of my background. Its sizing is set to width and height. It is a GuiChunkedBitmapCtrl.

To repro this add this to the end of the startMissionGui::onWake() function in startMissionGui.gui of a stock build:
%extent = startMissionGui.getExtent();
   echo("extent = " @ %extent);

Now launch the game and go to the start mission screen.
Check the console echo, it is the current correct resolution.
Go back to the main screen, choose options, then choose a new resolution
Go to the start mission screen and check the console echo, it is the old resolution
Go back to the main screen
Go to the start mission screen and check the console echo, it is now showing the new resolution

I believe this has something to do with me checking its extents before it gets resized, but I cannot seem to locate a safe place to check the extents of the control after it has been resized. Any help would be appreciated.

Edit: The reason I am not just using the screen resolution is because this is mostly an example. Ideally I am looking for a safe place to get a controls extents.

#1
05/02/2005 (9:45 am)
Do you get the right numbers if you get the extents from the console when it is visibly at the right size?
#2
05/02/2005 (9:55 am)
Yes.

Say I start in 800x600 and use echo(startmissiongui.getextent());

At main screen - 800 600
At start mission screen - 800 600

Back to main screen, choose options, change res to 640 480

At main screen - 800 600
At start mission screen - 640 480
#3
05/02/2005 (5:34 pm)
Perhaps the gui is not being put to sleep and woken up properly again?
#4
05/02/2005 (5:46 pm)
Possibly, I don't know too much about the underpinnings of the UI yet. Is there a way to force an update/refresh on the control?
#5
05/02/2005 (11:16 pm)
Hrmm... Canvas.setContent should do it.
#6
05/03/2005 (11:59 am)
Well I figured out why this is happening, but since I am not very familiar with the engine yet I haven't come up with a solution.

The code that is actually changing the extents of the start mission screen is:
guiCanvas.cc about line 1019
//all bottom level controls should be the same dimensions as the canvas
   //this is necessary for passing mouse events accurately
   iterator i;
   for (i = begin(); i != end(); i++)
   {
      AssertFatal(static_cast<GuiControl*>((*i))->isAwake(), "GuiCanvas::renderFrame: ctrl is not awake");
      GuiControl *ctrl = static_cast<GuiControl*>(*i);
      Point2I ext = ctrl->getExtent();
      Point2I pos = ctrl->getPosition();
      
      if(pos != screenRect.point || ext != screenRect.extent)
      {
         ctrl->resize(screenRect.point, screenRect.extent);
         resetUpdateRegions();
      }
   }

Now the reason this causes a problem is because onWake actually happens BEFORE this code happens.
In the main game loop, DemoGame::main about line 506
Platform::process(); // keys, etc.
      TelConsole->process();
      TelDebugger->process();
      TimeManager::process(); // guaranteed to produce an event

onWake happens in Platform::process() while this extents resizing voodoo happens in TimeManager::process(). Thus if you are attempting to check the extents in onWake you will not get the correct result.
#7
05/03/2005 (3:12 pm)
Still working on a solution for this. I think that if whenever the canvas resizes we should check the root control of hte canvas to make sure it is the correct size. So possibly doing this on resize instead of in the rendering loop might solve the problem.

A workaround is to force a refresh before you check the extents by using Canvas.repaint(). The problem with this method though is that you get a visible flicker of the background repainting.
#8
02/27/2008 (10:14 am)
To fix this you must call repaint, but only pre-render, not render the frame.

I created a Canvas->preparePaint(); script function that you can call which organizes the objects so that they are in relation to the root object in terms of sizing. Call this before getting the size or location of any object in a gui you just loaded and is in the process of waking up (problem explained in detail above).

I added the following function to guiCanvas.cc:

//SOMATIC VISION CHANGES START
void GuiCanvas::preparePaint() {
resetUpdateRegions();

// inhibit explicit refreshes in the case we're swapped out
if (gDGLRender)
renderFrame(true);
}
//SOMATIC VISION CHANGES END

And the following console function to call it:

//SOMATIC VISION CHANGES START
ConsoleMethod( GuiCanvas, preparePaint, void, 2, 2, "Prepare the canvas by calculating and applying the location of all objects.")
{
Canvas->preparePaint();
}
//SOMATIC VISION CHANGES END

Also in guiCanvas.h we must add the function declaration:

//SOMATIC VISION CHANGES START
void preparePaint(); //sets object locations to allow script to reposition
//SOMATIC VISION CHANGES END