window::hide() unexpected behaviour

For help with general CEGUI usage:
- Questions about the usage of CEGUI and its features, if not explained in the documentation.
- Problems with the CMAKE configuration or problems occuring during the build process/compilation.
- Errors or unexpected behaviour.

Moderators: CEGUI MVP, CEGUI Team

drsly
Just popping in
Just popping in
Posts: 7
Joined: Mon Jun 08, 2015 10:58

window::hide() unexpected behaviour

Postby drsly » Fri Dec 18, 2015 13:49

Maybe I'm missing something, but when I call the hide function on "TaharezLook/Menubar", it remains on the screen, in a deactivated state (not responding to mouseover / click). It remains this way until another object (eg a button) is hovered over, at which point it finally disappears.

This is my keypressed handler. Pressing escape should toggle the menubar:

Code: Select all

bool BasicTutorial7::keyPressed(const OIS::KeyEvent &arg)
{
   CEGUI::GUIContext& context = CEGUI::System::getSingleton().getDefaultGUIContext();
   context.injectKeyDown((CEGUI::Key::Scan)arg.key);
   context.injectChar((CEGUI::Key::Scan)arg.text);

   if (arg.key == OIS::KC_ESCAPE)
   {
      if (context.getRootWindow()->getChild("Menubar")->isVisible())
         context.getRootWindow()->getChild("Menubar")->hide();
      else
         context.getRootWindow()->getChild("Menubar")->show();
   }

   mCameraMan->injectKeyDown(arg);
   return true;
}



This is my initialisation. I create 3 buttons in code, load the menu from layout:

Code: Select all

   mRenderer = &CEGUI::OgreRenderer::bootstrapSystem();

   CEGUI::ImageManager::setImagesetDefaultResourceGroup("Imagesets");
   CEGUI::Font::setDefaultResourceGroup("Fonts");
   CEGUI::Scheme::setDefaultResourceGroup("Schemes");
   CEGUI::WidgetLookManager::setDefaultResourceGroup("LookNFeel");
   CEGUI::WindowManager::setDefaultResourceGroup("Layouts");

   CEGUI::SchemeManager::getSingleton().createFromFile("TaharezLook.scheme");
   CEGUI::System::getSingleton().getDefaultGUIContext().getMouseCursor().setDefaultImage("TaharezLook/MouseArrow");

   CEGUI::WindowManager &wmgr = CEGUI::WindowManager::getSingleton();
   CEGUI::Window *sheet = wmgr.createWindow("DefaultWindow", "CEGUIDemo/Sheet");

   // button
   CEGUI::Window *quit = wmgr.createWindow("TaharezLook/Button", "CEGUIDemo/QuitButton");
   quit->setText("Quit");
   quit->setPosition(CEGUI::UVector2(CEGUI::UDim(0, 0), CEGUI::UDim(0.05, 0)));
   quit->setSize(CEGUI::USize(CEGUI::UDim(0.15, 0), CEGUI::UDim(0.05, 0)));
   sheet->addChild(quit);

   // button
   CEGUI::Window *showbtn = wmgr.createWindow("TaharezLook/Button", "CEGUIDemo/ShowButton");
   showbtn->setText("Show");
   showbtn->setPosition(CEGUI::UVector2(CEGUI::UDim(0, 0), CEGUI::UDim(0.10, 0)));
   showbtn->setSize(CEGUI::USize(CEGUI::UDim(0.15, 0), CEGUI::UDim(0.05, 0)));
   sheet->addChild(showbtn);

   // button
   CEGUI::Window *hidebtn = wmgr.createWindow("TaharezLook/Button", "CEGUIDemo/ShowButton");
   hidebtn->setText("Hide");
   hidebtn->setPosition(CEGUI::UVector2(CEGUI::UDim(0, 0), CEGUI::UDim(0.15, 0)));
   hidebtn->setSize(CEGUI::USize(CEGUI::UDim(0.15, 0), CEGUI::UDim(0.05, 0)));
   sheet->addChild(hidebtn);

   CEGUI::System::getSingleton().getDefaultGUIContext().setRootWindow(sheet);

   quit->subscribeEvent(CEGUI::PushButton::EventClicked,
      CEGUI::Event::Subscriber(&BasicTutorial7::quit, this));

   showbtn->subscribeEvent(CEGUI::PushButton::EventClicked,
      CEGUI::Event::Subscriber(&BasicTutorial7::showWindow, this));

   hidebtn->subscribeEvent(CEGUI::PushButton::EventClicked,
      CEGUI::Event::Subscriber(&BasicTutorial7::hideWindow, this));

   // Load a layout
   // menu code based from http://cegui.org.uk/wiki/Menu_and_Popup
   CEGUI::Window* guiLayout = CEGUI::WindowManager::getSingleton().loadLayoutFromFile("test1.layout");
   guiLayout->setVisible(false);
   sheet->addChild(guiLayout);
   // subscribe events
   CEGUI::System::getSingleton().getDefaultGUIContext().getRootWindow()->getChild("Menubar/MenuItem_opt1/PopupMenu/MenuItem_show")->subscribeEvent(CEGUI::MenuItem::EventClicked,
      CEGUI::Event::Subscriber(&BasicTutorial7::onMenuItemClicked, this));
   CEGUI::System::getSingleton().getDefaultGUIContext().getRootWindow()->getChild("Menubar/MenuItem_opt1/PopupMenu/MenuItem_hide")->subscribeEvent(CEGUI::MenuItem::EventClicked,
      CEGUI::Event::Subscriber(&BasicTutorial7::onMenuItemClicked, this));
   CEGUI::System::getSingleton().getDefaultGUIContext().getRootWindow()->getChild("Menubar/MenuItem_opt1/PopupMenu/MenuItem_quit")->subscribeEvent(CEGUI::MenuItem::EventClicked,
      CEGUI::Event::Subscriber(&BasicTutorial7::onMenuItemClicked, this));


Nothing crazy in test1.layout:

Code: Select all

<?xml version="1.0" encoding="UTF-8"?>

<GUILayout version="4" >
    <Window type="TaharezLook/Menubar" name="Menubar" >
        <Property name="Area" value="{{0,0},{0,0},{1,0},{0,32}}" />
        <Window type="TaharezLook/MenuItem" name="MenuItem_opt1" >
            <Property name="Area" value="{{0,7},{0,0},{0,67},{0,19}}" />
            <Property name="Text" value="Option 1" />
            <Property name="VerticalAlignment" value="Centre" />
            <Window type="TaharezLook/PopupMenu" name="PopupMenu" >
                <Property name="Area" value="{{0,0},{0,0},{0,106},{0,66.6386}}" />
                <Property name="Visible" value="false" />
                <Property name="ItemSpacing" value="2" />
                <Property name="ClippedByParent" value="false" />
                <Property name="AutoResizeEnabled" value="true" />
                <Window type="TaharezLook/MenuItem" name="MenuItem_show" >
                    <Property name="Area" value="{{0,4},{0,4},{0,103},{0,22}}" />
                    <Property name="Text" value="Show Window" />
                </Window>
                <Window type="TaharezLook/MenuItem" name="MenuItem_hide" >
                    <Property name="Area" value="{{0,4},{0,24},{0,103},{0,42}}" />
                    <Property name="Text" value="Hide Window" />
                </Window>
                <Window type="TaharezLook/MenuItem" name="MenuItem_quit" >
                    <Property name="Area" value="{{0,4},{0,44},{0,103},{0,62}}" />
                    <Property name="Text" value="Quit" />
                </Window>
            </Window>
        </Window>
        <Window type="TaharezLook/MenuItem" name="MenuItem_opt2" >
            <Property name="Area" value="{{0,77},{0,0},{0,137},{0,19}}" />
            <Property name="Text" value="Option 2" />
            <Property name="VerticalAlignment" value="Centre" />
            <Window type="TaharezLook/PopupMenu" name="PopupMenu" >
                <Property name="Area" value="{{0,0},{0,0},{0,92},{0,46.1591}}" />
                <Property name="Visible" value="false" />
                <Property name="ItemSpacing" value="2" />
                <Property name="ClippedByParent" value="false" />
                <Property name="AutoResizeEnabled" value="true" />
                <Window type="TaharezLook/MenuItem" name="MenuItem" >
                    <Property name="Area" value="{{0,4},{0,4},{0,89},{0,22}}" />
                    <Property name="Text" value="menu item 1" />
                </Window>
                <Window type="TaharezLook/MenuItem" name="MenuItem2" >
                    <Property name="Area" value="{{0,4},{0,24},{0,89},{0,42}}" />
                    <Property name="Text" value="menu item 2" />
                </Window>
            </Window>
        </Window>
    </Window>
</GUILayout>


Do I need to do something to force the CEGUI screen refresh?

Interestingly, if I call hide() from onMenuItemClicked handler, it works as expected.

Here it is for good measure:

Code: Select all

bool BasicTutorial7::onMenuItemClicked(const CEGUI::EventArgs& e)
{
   const CEGUI::WindowEventArgs& we = static_cast<const CEGUI::WindowEventArgs&>(e);
   CEGUI::String senderID = we.window->getName();
   if (senderID == "MenuItem_show")
   {
      // do something
   }
   else if (senderID == "MenuItem_hide")
   {
      // do something different
   }
   else if (senderID == "MenuItem_quit")
   {
      mShutDown = true;
   }
   CEGUI::System::getSingleton().getDefaultGUIContext().getRootWindow()->getChild("Menubar")->hide();
   return true;
}


If you can help me :) please let me know if you need I will post more info.

Ogre v1.9
CEGUI 0.8.4
Windows 7
Visual Studio 2015

User avatar
Ident
CEGUI Team
Posts: 1998
Joined: Sat Oct 31, 2009 13:57
Location: Austria

Re: window::hide() unexpected behaviour

Postby Ident » Sat Dec 19, 2015 13:35

Did you put a breakpoint to see if it actually really calls hide() ? Did you then step into the CEGUI function (with CEGUI lib symbols loadeD) to see why it does not work?
CrazyEddie: "I don't like GUIs"

drsly
Just popping in
Just popping in
Posts: 7
Joined: Mon Jun 08, 2015 10:58

Re: window::hide() unexpected behaviour

Postby drsly » Tue Dec 22, 2015 13:28

Running in debugger, I can confirm hide() / show() is being called, as expected, in response to keyboard input.

A little more testing tells me something is up with this line in Window::setVisible()
d_visible ? onShown(args) : onHidden(args);

Code: Select all

void Window::setVisible(bool setting)
{
    // only react if setting has changed
    if (d_visible == setting)
        return;

    d_visible = setting;
    WindowEventArgs args(this);
    d_visible ? onShown(args) : onHidden(args);

    getGUIContext().updateWindowContainingMouse();
}


Seems the Window::onShown() function features a call to invalidate(), whereas the onHidden() function is overridden in the class MenuBase, such that no call to invalidate is made.

From Window.cpp

Code: Select all

void Window::onShown(WindowEventArgs& e)
{
    invalidate();
    fireEvent(EventShown, e, EventNamespace);
}

void Window::onHidden(WindowEventArgs& e)
{
    // first deactivate window if it is the active window.
    if (isActive())
        deactivate();

    invalidate();
    fireEvent(EventHidden, e, EventNamespace);
}


From Menubase.cpp

Code: Select all

void MenuBase::onHidden(WindowEventArgs&)
{
    if (!getAutoCloseNestedPopups())
        return;

    changePopupMenuItem(0);

    if (d_allowMultiplePopups)
    {
        for (size_t i = 0; i < d_listItems.size(); ++i)
        {
            if (!d_listItems[i])
                continue;

            MenuItem* menuItem = dynamic_cast<MenuItem*>(d_listItems[i]);
            if (!menuItem)
                continue;

            if (!menuItem->getPopupMenu())
                continue;

            WindowEventArgs we(menuItem->getPopupMenu());
            menuItem->closePopupMenu(false);
            onPopupClosed(we);
        }
    }
}


I have stepped through both show/hide functions and the rest of the flow of execution seems to be identical.

Ident, do you think the MenuBase::onHidden() function needs to call base class implementation?

It seems the MenuBase implementation is more concerned with hiding the menu items within it rather than hiding the menu itself. Maybe there is a workaround?

drsly
Just popping in
Just popping in
Posts: 7
Joined: Mon Jun 08, 2015 10:58

Re: window::hide() unexpected behaviour

Postby drsly » Tue Dec 22, 2015 13:54

Ignore previous post. Solution was to call deactivate just before hide()

Code: Select all

   if (arg.key == OIS::KC_ESCAPE)
   {
      if (context.getRootWindow()->getChild("Menubar")->isVisible())
      {
         context.getRootWindow()->getChild("Menubar")->deactivate();
         context.getRootWindow()->getChild("Menubar")->hide();
      }
      else
         context.getRootWindow()->getChild("Menubar")->show();
   }

User avatar
Ident
CEGUI Team
Posts: 1998
Joined: Sat Oct 31, 2009 13:57
Location: Austria

Re: window::hide() unexpected behaviour

Postby Ident » Sat Dec 26, 2015 18:01

drsly wrote:Ignore previous post. Solution was to call deactivate just before hide()

Code: Select all

   if (arg.key == OIS::KC_ESCAPE)
   {
      if (context.getRootWindow()->getChild("Menubar")->isVisible())
      {
         context.getRootWindow()->getChild("Menubar")->deactivate();
         context.getRootWindow()->getChild("Menubar")->hide();
      }
      else
         context.getRootWindow()->getChild("Menubar")->show();
   }


But would you call that an expected behavior? I wouldnt.

Ident, do you think the MenuBase::onHidden() function needs to call base class implementation?

Sounds reasonable. Are there any side-effects possible from this? I am in favour of calling the base class function from the subclass onHidden. Did you try if that fixes it?
CrazyEddie: "I don't like GUIs"


Return to “Help”

Who is online

Users browsing this forum: No registered users and 20 guests