Game Development Community

Nesting a SceneWindow within a GuiControl

by Chris Haigler · in Torque 2D Beginner · 02/25/2013 (10:54 am) · 6 replies

I'm attempting to add a SceneWindow to a GuiControl (specifically a GuiWindowCtrl) as a child. This works correctly (the SceneWindow resizes to fit the parent control, reacts appropriately to mouse input, renders perfectly, etc.). The issue is that once the SceneWindow is added to the GuiControl, the GuiControl stops rendering. In my case, once the SceneWindow is added to the GuiWindowCtrl, the GuiWindowCtrl disappears but still reacts to input (I can resize it, drag it with the (now invisible) title bar, etc.).

I've taken a look at the SceneWindow::onRender() method but I don't see anything that should outright break parent control rendering. Anyone have any ideas?

Edit: Here's the .gui.taml file I'm using:
<GuiControl
   Name="TestWindow"
   Profile="GuiDefaultProfile"
   HorizSizing="width"
   VertSizing="height"
   Position="0 0"
   Extent="1024 768">
      <GuiWindowCtrl
         Name="SceneWindowParent"
         Profile="GuiWindowProfile"
         HorizSizing="relative"
         VertSizing="relative"
         Position="0 0"
         Extent="300 300"
         CanMove="1"
         CanClose="0"
         CanMinimize="0"
         CanMaximize="0"
         Text="This Doesnt Render">
         
            <SceneWindow
               Name="SandboxWindow"
               Profile="SandboxWindowProfile"
               HorizSizing="width"
               VertSizing="height"
               Position="10 10"
               Extent="250 250"/>
               
            <GuiButtonCtrl
               Name="SceneWindowSibling"
               Profile="GuiButtonProfile"
               HorizSizing="width"
               VertSizing="height"
               Position="10 250"
               Extent="128 82"
               IsContainer="1"
               Text="This Renders?!"/>
               
         </GuiWindowCtrl>

</GuiControl>

#1
02/25/2013 (9:24 pm)
Got it!

It turns out the issue is in Scene::sceneRender() which is called in SceneWindow::onRender(). This bit of code is the troublemaker:

// Clear the background color if requested.
    if ( mUseBackgroundColor )
    {
        glClearColor( mBackgroundColor.red, mBackgroundColor.green, mBackgroundColor.blue, mBackgroundColor.alpha );
        glClear(GL_COLOR_BUFFER_BIT);	
    }

What's happening is SandboxScene has mUseBackgroundColor set to 'true' so it's clearing the backbuffer, erasing anything drawn before it (which includes parent controls).

To fix the issue I simply set SandboxScene.UseBackgroundColor to 'false' and set Canvas.UseBackgroundColor to 'true'.

Now I've got my SceneWindow rendering as a child of a GuiWindowCtrl.
#2
02/25/2013 (9:29 pm)
Very cool, Chris. I've been trying to do something similar to that in my own project and this will help me greatly.
#3
02/26/2013 (5:14 am)
Good catch. Yes, that's not clipped so it'll cause problems when not operating over the whole window.

I'll get that fixed up.
#4
02/26/2013 (5:21 am)
I've just pushed the change to the development branch here.

I'll get the Scene background color clipping sorted ASAP.
#5
02/26/2013 (10:08 am)
@Melv: I'm not entirely sure but it might be possible to define a scissor test rect around the scene/sceneWindow and call glClear() normally. Assuming scissor tests also affect glClear() you could then have the Canvas and multiple scenes all clearing their portion of the backbuffer without interfering with each other.

As a side note, you and Mich are doing some excellent work here.

Edit: It seems glScissor() does affect glClear(). I've made the following changes to my local repo and now both the Canvas and individual Scenes can have UseBackgroundColor=true without wiping out objects rendered before them.

In SceneWindow.cc, in the SceneWindow::onRender() method I've replaced the
pScene->sceneRender( &sceneRenderState );

line with:

// Define a scissor rect if the current scene uses background color.
	 if(pScene->getUseBackgroundColor())
	 {
		 U32 screenHeight = Platform::getWindowSize().y;
		 glEnable(GL_SCISSOR_TEST);
		 glScissor(updateRect.point.x, screenHeight - (updateRect.point.y + updateRect.extent.y),
					  updateRect.extent.x, updateRect.extent.y);
	 }

    // Render View.
    pScene->sceneRender( &sceneRenderState );

	 // Disable scissor test only if it was previously enabled.
	 if(pScene->getUseBackgroundColor())
	 {
		 glDisable(GL_SCISSOR_TEST);
	 }
#6
02/27/2013 (2:06 am)
Pretty much what I had in there last night before sleep called to me with the only significant change being that I added the code to the Scene type itself.

This morning I pushed the change to the dev branch here.

This works fine on all platforms. Thanks for reporting this and your help.