Jump to content

  • Log In with Google      Sign In   
  • Create Account

We're offering banner ads on our site from just $5!

1. Details HERE. 2. GDNet+ Subscriptions HERE. 3. Ad upload HERE.


Don't forget to read Tuesday's email newsletter for your chance to win a free copy of Construct 2!


Struct with child struct


Old topic!
Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.

  • You cannot reply to this topic
13 replies to this topic

#1 Tispe   Members   -  Reputation: 1039

Like
0Likes
Like

Posted 15 January 2013 - 08:47 AM

Hi

 

I am pondering how I should implement a GUI class. I figured I should have a root parent and then have child windows attached to that root parent. But how should the parent and the child be connected? Should I "new" each child and put a pointer to the child on the vector? Should the vector itself be a pointer to a vector which can hold children? What makes more sense, heap or stack or something in between?

 

struct GuiWindow
{
WinParam parameters;
std::vector<WindowObject> WindowObjects;
std::vector<GuiWindow> ChildWindows;
}
struct GuiWindow
{
WinParam parameters;
std::vector<*WindowObject> WindowObjects;
std::vector<*GuiWindow> ChildWindows;
}
struct GuiWindow
{
WinParam parameters;
std::vector<WindowObject> *WindowObjects;
std::vector<GuiWindow> *ChildWindows;
}
struct GuiWindow
{
WinParam parameters;
std::vector<*WindowObject> *WindowObjects;
std::vector<*GuiWindow> *ChildWindows;
}

 



Sponsor:

#2 SiCrane   Moderators   -  Reputation: 9627

Like
2Likes
Like

Posted 15 January 2013 - 09:16 AM

Chances are very small that your child elements will actually all be of the same type. You might have child buttons, child text boxes, child scrollbars, etc. Since you can't stuff different derived objects into a vector of base objects by value, you need to make a vector of (smart) pointers. And since a window with child elements is a pretty common use case, I'd go with holding the vector by value rather than by pointer.

#3 rip-off   Moderators   -  Reputation: 8517

Like
0Likes
Like

Posted 15 January 2013 - 09:32 AM

I presume where you've written *Type you actually meant Type*.

 

The simplest solution is the first. If you need polymorphism, then the second option (corrected for the above) is what you want - though use smart pointers if possible. Making the vectors pointers is unnecessary.

 

What makes more sense, heap or stack or something in between?

If you can allocate objects on the stack, do. However, don't bend over backwards to achieve this, the heap is fine too. Particularly for a GUI, you aren't likely to be allocating often so performance probably isn't a concern.

 

The main thing is to ensure you leverage RAII where possible so your GUI doesn't leak - hence the smart pointer suggestion.



#4 swiftcoder   Senior Moderators   -  Reputation: 10238

Like
1Likes
Like

Posted 15 January 2013 - 10:16 AM

You might also consider going with some form of immediate mode GUI, and doing away with the class structure altogether.

 

It's not necessarily a panacea, but it's a concept well worth wrapping your mind around. IMGUIs also tend to be much simpler than traditional retained GUI frameworks, especially for small-scale projects.


Tristam MacDonald - Software Engineer @Amazon - [swiftcoding]


#5 Servant of the Lord   Crossbones+   -  Reputation: 20316

Like
0Likes
Like

Posted 15 January 2013 - 11:49 AM

As rip-off mentioned, it's Type* not *Type. Also, a vector of pointers is completely proper, but a pointer to a vector is definitely not what you want.
 
struct GuiWindow
{
WinParam parameters;
std::vector<WindowObject*> WindowObjects;
std::vector<GuiWindow*> ChildWindows;
}

But isn't a Window a type of object itself? Most widget-based GUIs have buttons and text entry fields and pop-up windows and child-windows and toolbars and tooltips are inherit from the same base class. Either 'inherit' in the C++ sense, or in just the 'concept' of inheritance, without C++ inheritance.

So:
class WindowObject //Also often called 'widgets', but not always.
{
    public:
    WindowObject(WindowObject *parent);

    //Overridable function to handle a mouse click. The default implementation forwards it to whatever child window
    //at that location, and that child returns true if it handled the event, or false if it ignored it, letting
    //the event propagate to the bottom of the child hierarchy (which is visibly the widgets 'on top' of everything), before
    //bubbling back up through all the parent windows.
    virtual bool onMouseClick(const MouseClickEvent &mouseClick);
    virtual bool onMouseMove(const MouseMoveEvent &mouseMove);
    virtual bool onKeyPress(const KeyPressEvent &keyPress);
    virtual bool onShow();
    virtual bool onHide(); 
    
    //...and a half-dozen other events.

    private:
    unsigned int posX, posY; //Relative to the parent's position.
    unsigned int width, height;
    std::vector<WindowObject*> children; //Any buttons, sub-windows, pop-up windows, side-panels, text edits, text objects, image objects, etc...
};

It's perfectly fine to abbreviate my username to 'Servant' rather than copy+pasting it all the time.
All glory be to the Man at the right hand... On David's throne the King will reign, and the Government will rest upon His shoulders. All the earth will see the salvation of God.
Of Stranger Flames - [indie turn-based rpg set in a para-historical French colony] | Indie RPG development journal

[Fly with me on Twitter] [Google+] [My broken website]

[Need web hosting? I personally like A Small Orange]


#6 Tispe   Members   -  Reputation: 1039

Like
0Likes
Like

Posted 15 January 2013 - 12:57 PM

You might also consider going with some form of immediate mode GUI, and doing away with the class structure altogether.

 

It's not necessarily a panacea, but it's a concept well worth wrapping your mind around. IMGUIs also tend to be much simpler than traditional retained GUI frameworks, especially for small-scale projects.

 

This made no sense to me at all. Is there a tutorial that explains this concept better?



#7 swiftcoder   Senior Moderators   -  Reputation: 10238

Like
0Likes
Like

Posted 15 January 2013 - 01:12 PM

This made no sense to me at all. Is there a tutorial that explains this concept better?

 

Try mollyrocket's video introducing IMGUI.


Tristam MacDonald - Software Engineer @Amazon - [swiftcoding]


#8 Servant of the Lord   Crossbones+   -  Reputation: 20316

Like
0Likes
Like

Posted 15 January 2013 - 01:40 PM

The Sol IMGUI tutorials walk you through creating some, using SDL.


It's perfectly fine to abbreviate my username to 'Servant' rather than copy+pasting it all the time.
All glory be to the Man at the right hand... On David's throne the King will reign, and the Government will rest upon His shoulders. All the earth will see the salvation of God.
Of Stranger Flames - [indie turn-based rpg set in a para-historical French colony] | Indie RPG development journal

[Fly with me on Twitter] [Google+] [My broken website]

[Need web hosting? I personally like A Small Orange]


#9 Tispe   Members   -  Reputation: 1039

Like
0Likes
Like

Posted 16 January 2013 - 08:41 AM

Looking into IMGUI I find it hard to belive it is "that much" simpler then the standard RMGUI as it claims. Because every button, window, slide, label and list still needs to be defined somewhere. IMGUI just puts that away and says "it is not my responsibility", but then IMGUI is not a GUI is it? It is just a wrapper for a sprite or text drawcall...

 

If I were to try and roll my own IMGUI class I still need a place that retains all info on the layout of the GUI, what textures different buttons have etc. And what better place to keep that information other then inside the IMGUI class? Then the IMGUI class suddenly transforms into a RMGUI class.

 

I just don't get it is what I am trying to say :P



#10 Tispe   Members   -  Reputation: 1039

Like
0Likes
Like

Posted 17 January 2013 - 08:09 AM

So... how does people do IMGUI in terms of defining the gui layout? Say I have windows that contain 20 buttons, a health bar, a text edit box, some labels, check boxes and so on. Where would I go about saving where each of these wedgets gets placed on the screen? I surely can't have each widget as a global or static variable? So is it implied that the IMGUI class should contain a std::vector<widget*> which holds this info?

 

I think it is just too easy to claim the IMGUI class is not responsible for saving this data. What am I missing here?



#11 EWClay   Members   -  Reputation: 659

Like
0Likes
Like

Posted 17 January 2013 - 10:25 AM

In IMGUI, each widget is a function call. All the information needed to create it goes into the function parameters. It isn't stored anywhere, other than in the code.

You call the function every frame, and that's your button. No initialisation, no clean-up, and no callbacks. In many cases, that really is simpler.

#12 Boogiwoogie   Members   -  Reputation: 112

Like
1Likes
Like

Posted 17 January 2013 - 11:54 AM

Hi there! Just registered in, only to shout out my 2 cents on this biggrin.png

Around 3 years ago I have made my own IMGUI, heavily based on sol's tutorials mentioned above, but using pure OpenGL instead of SDL. It has no fancy stuff, just the usual suspects of widgets. Button, Slider, Checkbox, Group box. ID's are hardcoded, and for the layout I have a rectangle object that I offset by its height or width via rect.NextRow() or rect.NextCol(). Its pretty clear to me that this is most useless for any larger project. However, it really shines when I quickly want to try something out. Some voronoi library, a new particle system or whatever comes along while surfing the web. I simply include my IMGUI library and can most effortlessly expose variables to the GUI. Lets say I have a softbody simulation going on, and I want to have the damping variable accessible, I just put something like

gui.rect.NextRow();
gui.Slider(109, &damping, 1.0f, 50.0f, "Damping");

into the code and I am done. Nothing more neccessary. For me it kinda feels a little bit like the console for OpenGl based applications. It is ridiculously simple, but comes in too handy to be neglected smile.png

cheers, boogi

Edited by Boogiwoogie, 17 January 2013 - 12:07 PM.


#13 Tispe   Members   -  Reputation: 1039

Like
0Likes
Like

Posted 17 January 2013 - 01:27 PM

Thanks boogi for your input.

 

I have some more questions if you don't mind to answer.

 

Since you want to be able "to widget" any variable in the whole application, then you need access to the GUI instance  (i'm using C++ here) in all of the code. Meaning you need to either pass the GUI around to all parts of the code as a parameter, make a singleton or a global. People advise against the last two options. How would you get access to the GUI from any part of the application?

 

Also, before rendering the scene there is alot of stuff to be done. And in IMGUI it is before you render you pass through a variable you want to display with a widget. So in my mind, the IMGUI needs carry with it a render target and make a scene for each widget you want to draw... How  would this then affect performance when the GUI keps using drawcalls in all parts of the application?

 

The next logical solution is to defer the draws until the scene is drawn in the render code. Piling up the drawcalls into a vector to be drawn at a later time. So yet again we need to carry retained data for each widget in the GUI. That means a copy of any value, text, textures and layout info for each widget to complete the defered rendering. Only the functionality of the widget is immediate in where you place the code.

 

Is there a solution to this I don't see here?



#14 Boogiwoogie   Members   -  Reputation: 112

Like
0Likes
Like

Posted 17 January 2013 - 03:42 PM

Since you want to be able "to widget" any variable in the whole application, then you need access to the GUI instance (i'm using C++ here) in all of the code. Meaning you need to either pass the GUI around to all parts of the code as a parameter, make a singleton or a global. People advise against the last two options. How would you get access to the GUI from any part of the application?

Good point there. The good thing is that the main loop (the "update frame" method, not the "render frame") should have access to all data that is dealt with. So you would define your IMGUI object there. The bad part is all the private variables of your data. In the example above, if the softbody object has SetDamping() and GetDamping() methods around a private variable, it just won't work as easily. I can recall making variables public for that purpose, which is ugly. Maybe some pedantic OO-guru may come up with some generic-template-based-operator-overloading-behind-the-back-reflection-super-solution to this to make it look like OO where it isn't. I didn't bother tho.

 

Also, before rendering the scene there is alot of stuff to be done. And in IMGUI it is before you render you pass through a variable you want to display with a widget. So in my mind, the IMGUI needs carry with it a render target and make a scene for each widget you want to draw... How would this then affect performance when the GUI keps using drawcalls in all parts of the application?

"Make a scene" sounds like setting up a scene graph for a widget smile.png Well, It makes use of a pretty regular graphics class which provides basic drawing for OpenGL. Nothing too complex here. It uses the main (and only) OpenGL context. And its based on vertex arrays, all draw calls put vertices/colors into point/line/triangle arrays. Just for the record, its a cheap and hackish port of the http://code.google.com/p/glcanvas/ library. The 2D part of it. Strings are rendered into textures and glDeleteTexture'd when the string is not drawn for 5 frames.

 

The next logical solution is to defer the draws until the scene is drawn in the render code. Piling up the drawcalls into a vector to be drawn at a later time. So yet again we need to carry retained data for each widget in the GUI. That means a copy of any value, text, textures and layout info for each widget to complete the defered rendering. Only the functionality of the widget is immediate in where you place the code.

Well, I wouldn't say that filled up vertex and text arrays is a copy of the variables and its layouts. So "No" to that part (in my case! you may do it differently).

However, the last part is so true and is outing you as someone who has fully understood the concept. Only the interface to the GUI is immediate! Yes! In fact, it is up to you how much data is stored "behind the scenes". It is implementation details. It may even store more data than a retained mode GUI.






Old topic!
Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.



PARTNERS