Is there a Gui collection object?

You are an experienced programmer and have a problem with the engine, shaders, or advanced effects? Here you'll get answers.
No questions about C++ programming or topics which are answered in the tutorials!
Post Reply
keless
Posts: 805
Joined: Mon Dec 15, 2003 10:37 pm
Location: Los Angeles, California, USA

Is there a Gui collection object?

Post by keless »

I'm trying to create a GUI XML file. My problem is that I want to have some static text and some buttons be a child of an invisible parent object that encases them. However, none of the GUI elements that I can see in the API are pure container classes.

At the moment, I plan on using a staticText box with no text in it as the parent class, but this is a hack. Is there a better way of containing a set of XML GUI elements in a root element that I can then manipulate when loaded? Or does this functionality not yet exist.

For those of you wondering why someone would want to do this, its very simple: if you create an XML for say, the Health/MP bar portion of a game HUD, you can load the XML file and move the root of it to different portions of the screen depending on where you actually want to place it (instead of having to move each element individually).
a screen cap is worth 0x100000 DWORDS
Carnafex
Posts: 15
Joined: Wed Sep 05, 2007 1:32 am
Location: Sydney, Australia

Post by Carnafex »

I actually ran into this with my program as well. Instead of text though I used an image that I set its colour to completely transparent. The image is usually something like a single black pixel gif or so.

It's something like the following:

Code: Select all

IGUIImage* container = driver->environment->addImage(rectangle);
container->setScaleImage(true);
container->setImage(driver->getTexture("smallblackgraphic"));
container->setColor(video::SColor(0,255,255,255));
It's still a bit of a hack, but I think it's a bit more elegant compared to the text node.

Of course, you could just write your own GUI element that is simply a rectangle and just draws any children in it. Takes a bit more code to setup (since you need to make a CGUIContainer.cpp, etc), but is probably the best solution if you don't mind a bit more code.
CuteAlien
Admin
Posts: 9734
Joined: Mon Mar 06, 2006 2:25 pm
Location: Tübingen, Germany
Contact:

Post by CuteAlien »

That's also one of my feature wishes for the next irrlicht version :-)
Like the empty scene node we need an empty gui element.

At the moment I create a class for that myself. But there are a few things you have to care about when you need it for serialization. First you need to use a guifactory for it, otherwise you can't load it.
Then you should overwrite CGUIEmptyElement::isPointInside and return false in it (that's why I don't use a static or image). And I think the last problem is unfortunately not solvable that way: You still will have clipping for that empty scene node. My only solution for that so far is to make it either very large or as large as the biggest element. Which has it's own problems as alignment will no longer function as expected (this element should be ignored in alignment).
IRC: #irrlicht on irc.libera.chat
Code snippet repository: https://github.com/mzeilfelder/irr-playground-micha
Free racer made with Irrlicht: http://www.irrgheist.com/hcraftsource.htm
keless
Posts: 805
Joined: Mon Dec 15, 2003 10:37 pm
Location: Los Angeles, California, USA

Post by keless »

Using the gui editor its easy to set the size of the area for a staticText element that encompasses all of its children (the gui editor will even render its children cut off if they go out of bounds) so its fairly easy to make sure it encompasses them using that tool.

I agree; I look forward to having an empty gui container element like the empty scene node. Here's hoping its in the next version. :D
a screen cap is worth 0x100000 DWORDS
bitplane
Admin
Posts: 3204
Joined: Mon Mar 28, 2005 3:45 am
Location: England
Contact:

Post by bitplane »

I can't check at the moment, but I didn't think IGUIElement has any pure virtuals. You should be able to just use "new IGUIElement(...)".
I'm sure I saw Travis do that in an example post once, and he's rarely (if ever) wrong :D
Submit bugs/patches to the tracker!
Need help right now? Visit the chat room
keless
Posts: 805
Joined: Mon Dec 15, 2003 10:37 pm
Location: Los Angeles, California, USA

Post by keless »

Is that exposed in the XML format? Its definately not available in the GUI Editor that comes with the latest version of IrrLicht, which is what I'd like to use.
a screen cap is worth 0x100000 DWORDS
vitek
Bug Slayer
Posts: 3919
Joined: Mon Jan 16, 2006 10:52 am
Location: Corvallis, OR

Post by vitek »

I'm sure I saw Travis do that in an example post once
I was going to suggest that, but I haven't had a chance to look over the changes to the gui stuff since you added the gui serialization and positioning code. If there are no pure virtuals, that would be the way to go.

If there are, then you can write a very thin wrapper around IGUIElement and then define the necessary serialization hooks so that the serialization framework will work with it. The only additional requirement would be that the gui editor allow you to create any node type that is supported by the gui element factory.
and he's rarely (if ever) wrong
Ha. Thanks for the compliment. You should see all the mistakes I make at my day job. :)

Travis
keless
Posts: 805
Joined: Mon Dec 15, 2003 10:37 pm
Location: Los Angeles, California, USA

Post by keless »

Taking the thread in a slightly different (but still parallel) direction:

I'm trying to switch to a sub-state where I have a window pop up, and then switch back. The window that pops up does _not_ remove the gui elements behind it. Both the previous state's elements AND the sub-state's window are loaded using guienv->loadGUI( xxx, guienv->getRootGUIElement());

This seems to cause the sub-state's gui elements to clobber the previous elements. What I think I'm realizing is that both the guienv->loadGUI() and smgr->loadScene() are hacks to load the current scene/gui with the assumption that it is empty to begin with. Furthermore, there is no way to cull a portion of a scene/gui tree without writing your own recursive ->remove() function.

IMO these should be generalized to load a scene/gui heirarchy and return the root node of that heirarchy. That root node can then be manipulated appropriately.

For example: say you have a complex 'mini-scene' that represents a the sun, earth and moon, in their orbits. It consists of 1 root node, 3 textured sphere nodes, 2 rotation animators, and possibly a light source. You save this to file. (I'm not actually trying to do this, but its a good example of the robust functionality I'm talking about with the GUI stuff)

Lets say you then want to load that 'mini-scene' and use it somewhere in your game-- you should be able to do something like:

Code: Select all

 ISceneNode* snUniverse = smgr->loadSceneNodes(/*path*/"miniUniverse1.xml", /*node to attach to, current root node by default*/ -1);
  sn_starwarsHologramProjector->addChild( snUniverse ); //set the currently loaded universe to represent a projected hologram
Of course you can argue that the mini-universe thing should just be a real animation/mesh file and you may be right. But the idea still applies to the GUI elements: you should be able to do something like:

Code: Select all

 //on app initialization
 guienv->loadGUInodes("mainMenu.xml", guienv->getRootGUIElement());
 
 //user selects 'sound options' from menu
 gui_VidOptsWindow = loadGUInodes("soundOptions.xml", guienv->getRootGUIElement());

 //user quits/applies sound options
  gui_VidOptsWindow->removeRecursive(); //remove this and its children

Of course I could load every single gui element the app will have and simply toggle visible/active on them as I need, but thats a waste of memory and a hack. I should be able to load/unload portions from a file and attach/unattach them from the scene as needed.
a screen cap is worth 0x100000 DWORDS
CuteAlien
Admin
Posts: 9734
Joined: Mon Mar 06, 2006 2:25 pm
Location: Tübingen, Germany
Contact:

Post by CuteAlien »

A call to remove for gui elements should be recursive. As long as you did not grab() the children additionally they will all get dropped in the destructor of the parent element.

Loading a new window while keeping parts of the background gui is possible, though a little tricky. The way I'm doing it is that I use the knowledge which top element the loaded xml's do have. I create first a dummy element as parent. Then after loading I know (but certainly still check it to be sure) the type of my first child. Each of my dialogs always has one topElement of this type. So now I set this child as new topElement. Before doing so I remember certainly the parent of my old topElement so my dialogs can have parents (and be subdialogs that way).

Btw. - once I loaded a guidialog I usually keep it in memory. Loading times for complex dialogs can get so large that they are noticeable. And the memory usage doesn't really matter too much (but this certainly depends on your dialogs).

Can't tell much about a good way to handle scenenodes. My solution in H-Craft sucked. I couldn't release scenenodes anymore and after doing some calculations I found out that the memory usage after loading all levels was bearable (but hardly...) so I did ignore that. Will have to think of that some more this time.
IRC: #irrlicht on irc.libera.chat
Code snippet repository: https://github.com/mzeilfelder/irr-playground-micha
Free racer made with Irrlicht: http://www.irrgheist.com/hcraftsource.htm
Post Reply