Page 1 of 1

Remove all GUI Elements

Posted: Mon Sep 11, 2006 9:37 pm
by rikyoh
Hi,

is there an easy way to remove all GUI Elements?

Bye,
Rikyoh

Posted: Mon Sep 11, 2006 10:43 pm
by zeno60
I guess you could set a flag to stop calling environment->drawAll(); in your irrlicht loop.

Code: Select all

bool removegui = false;

while(device->run())
{
     driver->beginScene(true, true, 0);
     if(!removegui)
     {
          guienvironment->drawAll();
     }

     driver->endScene();
}

//
OnEvent(SEvent event)
{
     if(KEY_SPACE)
     {
          removegui = true;
     }
}
Although this prevents you from showing other gui menus later in your game. The way I do it is just to create seperate functions. Like showmenu() will set all the menu elements visible to true, hidemenu() sets them invisible. showpausemenu() sets the pause menu items visible, hidepausemenu, etc. etc.

Posted: Mon Sep 11, 2006 10:55 pm
by JP
I also do what Zeno does as calling the remove method of GUI elements didn't work for me (using Jirr, don't know if that's just a Jirr problem or if it happens in Irrlicht too).

Posted: Wed Sep 13, 2006 6:37 am
by AlexL
I forgot where abouts I found this on the forums, and who the code is by, but it has worked for me thus far. If anyone can tell who the credits goto that would be appriciated.

Code: Select all

bool CApplication::clearGUIElements()
{
	irr::core::list<irr::gui::IGUIElement*> hElementList = g_pGlobals->pGUI->getRootGUIElement()->getChildren();
	if(hElementList.empty())
	{
		return false;
	}
	while(!hElementList.empty())
	{
		(*(hElementList.getLast()))->remove();
	}
	return true;
}

Posted: Wed Sep 13, 2006 4:26 pm
by Strong99
if you set drawall off, you can still click the buttons i would say....

Posted: Fri Sep 15, 2006 5:38 pm
by rikyoh
Hi,

tanks for your replies. In my game I have several gamestates which all need different "setups" of scenenodes and guielements, so when I switch from one state to the other I want to first delete all elements of the old state and then create the elements needed for the new state. Thats no problem with the scene because there is a "clear()" function. Not to draw the gui-elements is no solution for me, because I need gui-elemtents in every gamestate. But the function AlexL posted seems to be what I need.

Update: it doesn't work! The "remove()" removes the gui-element, but the size of the list doesn't decrement and so the list never gets empty and I have endless loop. I think there must some code be added to delete the listmember after removing the gui element. Something with iterator... but I don't get it to work :-(

Bye,
Rikyoh

Posted: Fri Sep 15, 2006 6:54 pm
by vitek
It doesn't work because you've made a copy of the list and you're iterating over the copy, but removing from the original. The code should look like this...

Code: Select all

// notice that this is a reference to the list maintained by the root element
const core::list<IGUIElement*>& children = Environment->getRootGUIElement()->getChildren();
while (!children.empty())
   (*children.getLast())->remove();
If you are going to maintain multiple sets of UI, it may make sense to do something like this...

Code: Select all

struct SGameState
{
  IGUIElement* UserInterface;
  ISceneNode* Scene;
};

enum E_GAME_STATE { EGS_INVENTORY, EGS_PLAYING, EGS_COUNT };
SGameState AvailableGameStates[EGS_COUNT];
SGameState* ActiveGameState = 0;

   // somewhere in your init code
   u32 s;
   for (s = 0; s < EGS_COUNT; ++s)
   {
      AvailableGameStates[s].UserInterface = new IGUIElement(EGUIET_ELEMENT, Environment, Environment->getRootSceneNode(), -1, FullWindowRect);
      AvailableGameStates[s].Scene = SceneManager->addEmptySceneNode();
   }
   AvailableGameStates[s].UserInterface = 0;
   AvailableGameStates[s].Scene            = 0;

   ActiveGameState = &AvailableGameStates[0];

   // add controls to each of the user interfaces...

// method for changing ui
void setActiveGameState(E_GAME_STATE egs)
{
   ActiveGameState->UserInterface->setVisible(false);
   ActiveGameState->Scene        ->setVisible(false);

   ActiveGameState = &AvailableGameStates[egs];

   ActiveGameState->UserInterface->setVisible(true);
   ActiveGameState->Scene        ->setVisible(true);
}
I would wrap all of that up into a game management class. It allows you to enable/disable an entire game state without needing to rebuild the scene/gui every time the user switches.

Posted: Sun Sep 17, 2006 9:29 pm
by rikyoh
Hello,

thanks, the removing of GUI Elements seems to work know. Your idea for maintaining multiple sets of UI and Scenenodes looks very interesting and would fit easy into my actual design, but wouldn't that have an impact on performance? If I have two very complex scenes and only deactivate the visibility of one of them for example?

Bye
Riky

Posted: Sun Sep 17, 2006 10:52 pm
by JP
Things that aren't visible don't get rendered so the frame rate should be ok, but if you have loads of stuff in memory then you could run out maybe or run into problems there.

Posted: Wed Nov 15, 2006 7:03 am
by shivanraptor
how to remove all GUI elements in C# ?? please help .

i opened a thread here :
http://irrlicht.sourceforge.net/phpBB2/ ... hp?t=16935

Posted: Wed Nov 15, 2006 7:06 am
by shivanraptor
vitek wrote:It doesn't work because you've made a copy of the list and you're iterating over the copy, but removing from the original. The code should look like this...

Code: Select all

// notice that this is a reference to the list maintained by the root element
const core::list<IGUIElement*>& children = Environment->getRootGUIElement()->getChildren();
while (!children.empty())
   (*children.getLast())->remove();
If you are going to maintain multiple sets of UI, it may make sense to do something like this...

Code: Select all

struct SGameState
{
  IGUIElement* UserInterface;
  ISceneNode* Scene;
};

enum E_GAME_STATE { EGS_INVENTORY, EGS_PLAYING, EGS_COUNT };
SGameState AvailableGameStates[EGS_COUNT];
SGameState* ActiveGameState = 0;

   // somewhere in your init code
   u32 s;
   for (s = 0; s < EGS_COUNT; ++s)
   {
      AvailableGameStates[s].UserInterface = new IGUIElement(EGUIET_ELEMENT, Environment, Environment->getRootSceneNode(), -1, FullWindowRect);
      AvailableGameStates[s].Scene = SceneManager->addEmptySceneNode();
   }
   AvailableGameStates[s].UserInterface = 0;
   AvailableGameStates[s].Scene            = 0;

   ActiveGameState = &AvailableGameStates[0];

   // add controls to each of the user interfaces...

// method for changing ui
void setActiveGameState(E_GAME_STATE egs)
{
   ActiveGameState->UserInterface->setVisible(false);
   ActiveGameState->Scene        ->setVisible(false);

   ActiveGameState = &AvailableGameStates[egs];

   ActiveGameState->UserInterface->setVisible(true);
   ActiveGameState->Scene        ->setVisible(true);
}
I would wrap all of that up into a game management class. It allows you to enable/disable an entire game state without needing to rebuild the scene/gui every time the user switches.
can u translate the code to C# ? i think some functions in C++ does not exist in Irrlicht .NET . true ?

Posted: Wed Nov 15, 2006 7:43 am
by vitek
can u translate the code to C# ? i think some functions in C++ does not exist in Irrlicht .NET . true ?
I don't know, can you? Try it and find out, it's only a few lines of code.

Posted: Wed Nov 15, 2006 8:00 am
by shivanraptor
vitek wrote:
can u translate the code to C# ? i think some functions in C++ does not exist in Irrlicht .NET . true ?
I don't know, can you? Try it and find out, it's only a few lines of code.
the constructor of IGUIElement is VERY different from C++ and it cannot be implemented in C# . it cannot follow the code as two libraries are totally differrent

public IGUIElement(
IGUIElement* element
);

Posted: Wed Nov 15, 2006 10:19 am
by vitek
Sure seems like that is enough to do it.