Page 1 of 1

Child window properties from GUILayout: problem + fix

Posted: Tue Apr 23, 2013 14:07
by marvinx
Hi,

I discovered the following problem concerning the GUILayout XML element processing in CEGUI 0.7.7. I've created a GUILayout consisting of a custom ScrollablePane widget, a "DragMeAround"-like child FrameWindow for testing (added to the ContentArea of the pane), and another "Minimap" child FrameWindow. The latter FrameWindow shall be handled as special "NonClient" window of the ScrollablePane, i.e. it should not move when the pane is scrolled. In order to realize this feature I've overloaded the ScrollablePane::addChild_impl() methods as follows

Code: Select all

void ZoomableScrollPaneWidget::addChild_impl(Window* wnd)
{
  if ( wnd == NULL )
    CEGUI_THROW(NullObjectException("Invalid handle!"));

  // Check to see if 'wnd' is a regular non-client window, e.g. a Minimap
  if ( !wnd->isAutoWindow() && wnd->isNonClientWindow() )
  {
    // Do NOT treat this window as ScrollablePane content
    Window::addChild_impl(wnd);
  }
  else
  {
    // Use base implementation to handle other types of child widgets
    ScrollablePane::addChild_impl(wnd);
  }
} //  ZoomableScrollPaneWidget::addChild_impl


The corresponding GUILayout looks like:

Code: Select all

<GUILayout>
  <Window Type="DefaultWindow" Name="Root" >
    <Property Name="UnifiedAreaRect" Value="{{0,0},{0,0},{1,0},{1,0}}" />
    <Property Name="MousePassThroughEnabled" Value="True" />

    <!-- Define a ZoomableScrollPaneWidget -->
    <Window Type="ZoomableScrollPaneWidget" Name="Root/ScrollPane">
      <Property Name="UnifiedAreaRect" Value="{{0,0},{0,0},{1,0},{1,0}}" />
      <Property Name="ContentPaneAutoSized" Value="False" /> <!-- order matters! -->
      <Property Name="ContentArea" Value="l:0.0 t:0.0 r:2048.0 b:1152.0" />
      <Property Name="ForceVertScrollbar" Value="False" />
      <Property Name="ForceHorzScrollbar" Value="False" />

      <!-- Define a Minimap overlay (as NonClient child of our pane) -->
      <Window Type="DarkLook/FrameWindow" Name="Root/ScrollPane/Minimap" >
        <Property Name="UnifiedSize" Value="{{0,256},{0,256}}" />
        <Property Name="UnifiedPosition" Value="{{0.1,0},{0.1,0}}" />
        <Property Name="Text" Value="Minimap" />
        <Property Name="NonClient" Value="True" />
        <Property Name="AlwaysOnTop" Value="True" />

        <AutoWindow NameSuffix="__auto_clientarea__" >
          <Window Type="Vanilla/StaticImage" Name="ActiveScene" >
            <Property Name="UnifiedSize" Value="{{1,0},{1,0}}" />
            <Property Name="BackgroundEnabled" Value="False" />
            <Property Name="FrameEnabled" Value="False" />
            <Property Name="MousePassThroughEnabled" Value="True" />
          </Window>

          <Window Type="Vanilla/StaticImage" Name="BirdsEye" >
            <Property Name="UnifiedSize" Value="{{0.2,0},{0.2,0}}" />
            <Property Name="BackgroundEnabled" Value="True" />
            <Property Name="FrameEnabled" Value="False" />
            <Property Name="MousePassThroughEnabled" Value="False" />
            <Property Name="Alpha" Value="0.4" />
          </Window>
        </AutoWindow>
      </Window> <!-- end Root/ScrollPane/Minimap -->

      <!-- Define "DragMeAround" - FrameWindow as ScrollPane content -->
      <Window Type="DarkLook/FrameWindow" Name="Root/ScrollPane/Test" >
        <Property Name="UnifiedSize" Value="{{0,128},{0,128}}" />
        <Property Name="UnifiedPosition" Value="{{0.3,0},{0.2,0}}" />
        <Property Name="Text" Value="DragMeAround" />
      </Window>
    </Window> <!-- End Root/ScrollPane -->
  </Window> <!-- End Root -->
</GUILayout>


What's important here is that I set the "NonClient" property of the "Root/ScrollPane/Minimap" window to "True", so this child window should be specially handled within the overloaded addChild_impl() of my custom ScrollablePane widget.

I discovered the following problem: When loading the GUILayout, the GUILayout_xmlHandler will add the "Root/ScrollPane/Minimap" as child to "Root/ScrollPane" BEFORE setting its GUILayout properties, in particular, before setting the "NonClient" property to "True". So the overloaded ScrollablePane::addChild_impl() will not work as expected.

I have applied the following changes in class GUILayout_xmlHandler from CEGUI-0.7.7:

Code: Select all

void GUILayout_xmlHandler::elementWindowStart(const XMLAttributes& attributes)
{
    // get type of window to create
    String windowType(attributes.getValueAsString(WindowTypeAttribute));
    // get name for new window
    String windowName(attributes.getValueAsString(WindowNameAttribute));

    // attempt to create window
    CEGUI_TRY
    {
        Window* wnd = WindowManager::getSingleton().createWindow(windowType, d_namingPrefix + windowName);

//        // add this window to the current parent (if any)
//        if (!d_stack.empty())
//            d_stack.back().first->addChildWindow(wnd);
//        else
//            d_root = wnd;

        // Changed 04/23/2013, KS
        if (d_stack.empty())
          d_root = wnd;

        // make this window the top of the stack
        d_stack.push_back(WindowStackEntry(wnd,true));

        // tell it that it is being initialised
        wnd->beginInitialisation();
    }
  ...
}


Code: Select all

void GUILayout_xmlHandler::elementWindowEnd()
{
    // pop a window from the window stack
    if (!d_stack.empty())
    {
//        d_stack.back().first->endInitialisation();
        Window* wnd = d_stack.back().first;
        wnd->endInitialisation();
        d_stack.pop_back();

        // Added 04/23/2013, KS
        // - see also "Changed" section in elementWindowStart

        // Add 'wnd' to its parent window (if any)
        if ( !(wnd==d_root) && !d_stack.empty() )
          d_stack.back().first->addChildWindow(wnd);
    }
}


After recompiling the library the problem was fixed. The GUILayout was successfully loaded and all child window properties are now set to their configured values BEFORE the window is added to its parent.

I am not sure about the side effects of the above changes in other parts of the CEGUI library?! Maybe there a cases where this patch is not applicable?

Re: Child window properties from GUILayout: problem + fix

Posted: Fri Apr 26, 2013 16:24
by CrazyEddie
I hate all of these temporal-like issues, where certain things depend upon something as 'simple' as when a child gets added to it's parent. These come up now and again and it royally sucks! :D

I am not sure about the side effects of the above changes in other parts of the CEGUI library?! Maybe there a cases where this patch is not applicable?

That's the major issue. We will need to sit down and weigh this very carefully and consider all the implications of such a change.

Can you add a mantis ticket (use your forum credentials) either containing the same information or at least a link back here. This way the issue will not be lost and forgotten. Thanks.

CE.

Re: Child window properties from GUILayout: problem + fix

Posted: Fri Apr 26, 2013 20:53
by marvinx
Okay, I've added a new Mantis ticked. I would appreciate any suggestions for a workaround other than the proposed patch of the core library :wink:

Re: Child window properties from GUILayout: problem + fix

Posted: Mon Apr 29, 2013 16:25
by CrazyEddie
The only thing I could come up with is to add the non-client windows as part of the looknfeel, this way it's made an autowindow and automatically gets added to the main window and not the content pane (similar to the scrollbars). I know this is not all that flexible - depending on your needs - but I could not come up with any other suggestion at the moment without requiring some modifications to the lib.

CE.

Re: Child window properties from GUILayout: problem + fix

Posted: Mon Apr 29, 2013 20:10
by marvinx
Thanks for pointing out this. I think this should work for me :D