It is currently Sun Oct 22, 2017 6:53 am

All times are UTC - 5 hours




 Page 1 of 1 [ 20 posts ] 
Author Message
 Post subject: Some GUI Questions
PostPosted: Fri Jan 01, 2016 9:34 pm 

Joined: Mon Mar 24, 2014 2:25 pm
Posts: 69
**EDIT** Removed a couple questions by simplifying GUICheckbox to not hold it's own GUILabel object and manually laying out Labels for each checkbox in the .gui file. Now UpdateContainerSize() doesn't need to worry about a label nor does the label need to worry about deconstructing itself which also got rid of the memory access violation I was having in deconstructing AssetManager.

Hey Marek and fellow programmers,

First Happy New Year, hope everyone is doing well! I've been working on expanding the GUI functionality we have and successfully added a checkbox style button class (missing mouse interaction) and I've really attempted to keep in inline with the existing engine's GUI architecture and have a few questions.

1) At the highest level a GUIScreen doesn't have an Enable / Disable such as a Layout's "SetVisible" functionality. For my case I'm working on building a debugging window which I beleive is correctly implemented under it's own GUIScreen object versus the main game's GUIScreen. Would it make sense to move "SetVisible" up to to the screen level or should we just use the "SetAlpha" function? When I implement mouse clicking on the GUI I need to detect whether a object is disabled (or 0 alpha I guess). Any thoughts on this would be appreciated.

2) I'm having a hard time mapping the purpose of the virtual void function "ClearTextureInfos" throughout the GUI system. Wouldn't you just delete the GUI instead of having a GUIelement without a background texture? Any help explaining the intent of this method would be appreciated.

Looking forward to extending to radio buttons and a general GUIcontrol class that I think I'll refactor the checkbox under, but baby steps first ;)

Thanks for the help in advance,

Mebourne


Last edited by Mebourne on Sat Jan 02, 2016 1:10 am, edited 1 time in total.

Offline
 Profile  
 
 Post subject: Re: Some GUI Questions
PostPosted: Sat Jan 02, 2016 12:33 am 

Joined: Mon Mar 24, 2014 2:25 pm
Posts: 69
Good evening, ran into another interesting challenge when implementing the GUICheckbox into the GUILoader. As far as I'm aware in c++ there is no way to associate the value of a string (parsed from the .gui file) as a variable name. To workaround this issue, I created a second constructor for the GUICheckbox class not requiring the associated bool value that's mapped to the checkbox which then forces all checkboxes to be manually mapped in the game code with SetMappingValue().

Here is an example of the implementation I'm using so far.

std::string StrFilename = "Assets/Gui/Test.gui";
DebugScreen = dynamic_cast<FGUIScreen*>(LoadGUI(StrFilename));
FGUICheckbox* DebugWireframe = dynamic_cast<FGUICheckbox*>(AssetStorage->GetGUIElement("DebugWireframe", FGUIType::GUI_RENDERABLE));
DebugWireframe->SetMappingValue(IsWireframe);


If there is a better alternative through the GUILoader, any thoughts would be greatly appreciated!


Offline
 Profile  
 
 Post subject: Re: Some GUI Questions
PostPosted: Sun Jan 03, 2016 10:49 pm 

Joined: Mon Mar 24, 2014 2:25 pm
Posts: 69
Evening everyone, was able to make a little bit of progress this weekend. Still don't understand the intent of the cleartextureinfo methods propagating through all the GUI classes, but things are moving along slowly. The new GUIWindow class extends from GUILayout allowing children layouts to be added inside, but expands functionality for dragging, etc. Also the GUICheckbox is working.

Currently in progress is: GUITheme class that holds basic layout information for windows and a GUIControl class that checkbox will extend from in addition to allowing buttons and other "clickable" items more uniformly.

Image


Offline
 Profile  
 
 Post subject: Re: Some GUI Questions
PostPosted: Mon Jan 04, 2016 9:36 am 
Site Admin

Joined: Sun Feb 11, 2007 8:59 am
Posts: 1105
Location: Ontario Canada
Re: your gui debug window.
I would not implement the window class under GuiScreen if I were you. GuiScreen is to represent the entire view on the screen. I would instead make the GuiWindow inherit from GuiLayoutAbsolute. That way you can place it where ever you want in the screen and it can hold anything that is placed inside the window.

Re: clearTextureInfos
This function is used to release any texture ID's which were previously loaded and stored in the asset storage. This function should only be called to clean up the texture when you know that the texture is no longer needed.

When I get to showing how I implemented checkboxes in the engine, you'll see that I create a GuiControl class that inherits from GuiRenderable. Then GuiButton inherits from GuiControl. GuiControl is used to manage pressed states, enabled states, and mouse actions over any gui control. GuiButton ends up managing which images should be shown based on the current state of the button.


Offline
 Profile  
 
 Post subject: Re: Some GUI Questions
PostPosted: Mon Jan 04, 2016 10:26 am 

Joined: Mon Mar 24, 2014 2:25 pm
Posts: 69
Marek wrote:
Re: your gui debug window.
I would not implement the window class under GuiScreen if I were you. GuiScreen is to represent the entire view on the screen. I would instead make the GuiWindow inherit from GuiLayoutAbsolute. That way you can place it where ever you want in the screen and it can hold anything that is placed inside the window.

Re: clearTextureInfos
This function is used to release any texture ID's which were previously loaded and stored in the asset storage. This function should only be called to clean up the texture when you know that the texture is no longer needed.

When I get to showing how I implemented checkboxes in the engine, you'll see that I create a GuiControl class that inherits from GuiRenderable. Then GuiButton inherits from GuiControl. GuiControl is used to manage pressed states, enabled states, and mouse actions over any gui control. GuiButton ends up managing which images should be shown based on the current state of the button.


Marek, thanks for the follow-up. Since my original post, I did switch up the GUIWindow class to inherit from GUILayout so it would have OffsetFromParent built-in, etc. Should I move one layer down to GUILayoutAbsolute instead?

The GUIRenderable->GUIControl->GUICheckbox was the layout I was working this morning, so glad to hear I'm heading down the right track. Since checkboxes, radiobuttons and buttons themselves are all button types, should the key state be stored in GUIControl instead of GUIButton?

With respect to assigning variable names from the .gui parsed files, did you find a workaround for associating a parsed StrValue as a variable name? I was thinking about implementing it with a std::map of bools and std::string values and seeing if that works.

-Mebourne


Offline
 Profile  
 
 Post subject: Re: Some GUI Questions
PostPosted: Mon Jan 04, 2016 11:44 am 
Site Admin

Joined: Sun Feb 11, 2007 8:59 am
Posts: 1105
Location: Ontario Canada
Mebourne wrote:
Marek, thanks for the follow-up. Since my original post, I did switch up the GUIWindow class to inherit from GUILayout so it would have OffsetFromParent built-in, etc. Should I move one layer down to GUILayoutAbsolute instead?


I only suggested GuiLayoutAbsolute since it gives you control over where in the GuiScreen the layout will appear. If you leave it inheriting from GuiLayout then you'll have some code duplication in your GuiWindow class and the GuiLayoutAbsolute class.

Mebourne wrote:
The GUIRenderable->GUIControl->GUICheckbox was the layout I was working this morning, so glad to hear I'm heading down the right track. Since checkboxes, radiobuttons and buttons themselves are all button types, should the key state be stored in GUIControl instead of GUIButton?


Yes. Each control is going to have to keep track of its own state so it makes sense to put it there rather than inside GuiCheckbox. Once you start implementing other things that inherit from GuiControl ... then you'll also discover other things that you'll need/want to store in the GuiControl class.

Mebourne wrote:
With respect to assigning variable names from the .gui parsed files, did you find a workaround for associating a parsed StrValue as a variable name? I was thinking about implementing it with a std::map of bools and std::string values and seeing if that works.


I'm not entirely sure I understand what you are trying to do here. For all of my GuiControls, I added a new set of parameters that get parsed by the GuiLoader. These include things like "enabled_" and "pressed_" so that I know how to initialize the GuiControl when it is constructed.


Offline
 Profile  
 
 Post subject: Re: Some GUI Questions
PostPosted: Mon Jan 04, 2016 12:32 pm 

Joined: Mon Mar 24, 2014 2:25 pm
Posts: 69
Marek wrote:
I'm not entirely sure I understand what you are trying to do here. For all of my GuiControls, I added a new set of parameters that get parsed by the GuiLoader. These include things like "enabled_" and "pressed_" so that I know how to initialize the GuiControl when it is constructed.


Sorry for the confusion, here is a specific example:

A checkbox needs to be referenced to some bool value. For my example, I have a bool IsWireframe that the renderer will evaluate to determine if it should switch to wireframe rendering. For a "debug" GUI I want to setup a standard interface through a GUIDebug.gui file. I've expanded the GUILoader function to read in GUICheckbox with a structure such as:

LayoutGrid Id_DebugOptions NumColumns_2 Align_Center Offset_-5,25 Padding_5 {
   Checkbox Id_DebugWireframe Size_15,14 UncheckedOrigin_6,10 CheckedOrigin_33,10 TextureRef_GUIControls
   Label Id_DebugWireframeLabel FontType_GUIFont Text_`Wireframe Mode`
}


I wanted to be able to add a required parameter "Value_" in the loader code that would let you put in for example "Value_IsWireframe" and link the parsed string value as the actual bool reference in the engine, but I couldn't think of a way to do this since it's all compiled up front except for the std::map idea.

Here is how I'm linking checkbox's to an engine variable now after loading the Debug.gui file via a new method "SetMappingValue"

auto* DebugWireframe = dynamic_cast<FGUICheckbox*>(AssetStorage->GetGUIElement("DebugWireframe", FGUIType::GUI_RENDERABLE));
DebugWireframe->SetMappingValue(IsWireframe);


Thanks in advance!


Offline
 Profile  
 
 Post subject: Re: Some GUI Questions
PostPosted: Mon Jan 04, 2016 1:28 pm 
Site Admin

Joined: Sun Feb 11, 2007 8:59 am
Posts: 1105
Location: Ontario Canada
Okay I understand now. You want to define which variable in the c++ source code should update when the checkbox is toggled by the user.

A checkbox can be "wired" to do many complicated things, not just toggle a boolean variable so what I did in my code is implemented callback functions that get triggered when the checkbox state changes. My implementation is similar to what you'll find in Java Action Listeners: https://docs.oracle.com/javase/tutorial ... index.html


Offline
 Profile  
 
 Post subject: Re: Some GUI Questions
PostPosted: Mon Jan 04, 2016 3:05 pm 

Joined: Mon Mar 24, 2014 2:25 pm
Posts: 69
Perfect, I'll dig into that. I was looking for some callback tutorials for the GUIControl class so this will help.

Regarding your earlier comment on not having GUIWindows under a GUIScreen, the GUIScreen is the only class that supports traveling the GUI tree for rendering. To prevent code duplication, should that code be moved up to the GUICompositeElement class so a separate GUIOverlay or similiar class can be constructed similiar to GUIScreen, but for windows? What I'm not able to map out in the code is LayoutAbsolute that I'm not extending Windows from and other layouts all reference back to GUIScreen with their "FGUIScreen::AddToRender" method.

Unfortunately I'm always slow in making progress coding as I always want it to be perfect the first time around versus getting it working and refactoring later, so I appreciate your help with these questions.


Offline
 Profile  
 
 Post subject: Re: Some GUI Questions
PostPosted: Mon Jan 04, 2016 3:34 pm 
Site Admin

Joined: Sun Feb 11, 2007 8:59 am
Posts: 1105
Location: Ontario Canada
Mebourne wrote:
...the GUIScreen is the only class that supports traveling the GUI tree for rendering.


I'm not sure I understand what you mean by this. Each Gui class has the ability to render all of its children when the render() function is called. The only thing that is special about GuiScreen, is that it kicks off the render queue and assigns the initial position that is used to determine where to start the series of render calls, but each layout that it finds inside of the screen then calls render on all of its children so that they too get added to the queue.

A GuiLayout object is just a container for other Gui objects which will be rendered. I see your GuiWindow class as being no different than a GuiLayout at its core. The differences would be that there might be a titlebar at the top of the "layout" which a user can use to reposition the window, some buttons to control whether the window is visible or not, and possibly some additional mouse handling to change the size of the window. Calling render() on the GuiWindow should just layout out its children and also draw these extra parts that make the GuiWindow different than a regular GuiLayout.

Does that make sense?


Offline
 Profile  
 
 Post subject: Re: Some GUI Questions
PostPosted: Mon Jan 04, 2016 3:51 pm 

Joined: Mon Mar 24, 2014 2:25 pm
Posts: 69
Marek, thanks for the taking the time to help me understand this.

What I'm hung up on with all of our Layout* classes is their Render commands have the following at the end of their Render method which seems to require a FGUIScreen to be the overall parent.

   // Add elements into render queue
   for each(FGUIRenderable* Child in Children) {
      if (Child != nullptr)
         FGUIScreen::AddToRenderQueue(Child, NewPosition + GetChildOffset(Child->GetSize()), InPriority);
   }


Offline
 Profile  
 
 Post subject: Re: Some GUI Questions
PostPosted: Mon Jan 04, 2016 4:13 pm 
Site Admin

Joined: Sun Feb 11, 2007 8:59 am
Posts: 1105
Location: Ontario Canada
Exactly. The first call to GuiScreen.render() clears the render queue and then iterates over all the GuiLayout objects found in the GuiScreen and calls render on them. Each of those render calls then add their visible components to the GuiScreen's render queue so that the batch manager can process them. If any of the renderable components have children, then they too get added to the queue appropriately.

Your GuiWindow is just another object that is going to appear somewhere on the screen. So it should be no different then a GuiLayout. That way you can add a GuiWindow object as a child to a GuiScreen and have it appear on the monitor (screen).


Offline
 Profile  
 
 Post subject: Re: Some GUI Questions
PostPosted: Mon Jan 04, 2016 4:15 pm 

Joined: Mon Mar 24, 2014 2:25 pm
Posts: 69
Ha, I fully misinterpreted,
Quote:
I would not implement the window class under GuiScreen if I were you. GuiScreen is to represent the entire view on the screen. I would instead make the GuiWindow inherit from GuiLayoutAbsolute. That way you can place it where ever you want in the screen and it can hold anything that is placed inside the window.


I thought you mean't don't add Windows to a GUIScreen parent object. Sorry for the confusion.

I'm still going in the correct direction! ;)


Offline
 Profile  
 
 Post subject: Re: Some GUI Questions
PostPosted: Mon Jan 04, 2016 4:25 pm 

Joined: Mon Mar 24, 2014 2:25 pm
Posts: 69
Alittle progress, thanks for the help Marek. GUITheme is working now as well.

GUILoader's add child looks to see if the parent is a GUIWindow object and then updates the parent reference to allow all children in the .gui file to be under the title bar area.

void FGUILoader::AddToParent(FGUIRenderable* InRenderable) const {
   FGUICompositeElement* Parent = Parents.back();
   switch (GetGUIType(Parent)) {
      case GUI_SCREEN:
      case GUI_RENDERABLE: {
         if (dynamic_cast<FGUIWindow*>(Parent)) {
            Parent = dynamic_cast<FGUIWindow*>(Parent)->GetBodyArea();
         }
         Parent->AddChild(InRenderable);
         break;
      }
      default: {
         std::ostringstream StrStream;
         StrStream << __FUNCTION__ << GetFailedLocation() << "Can not add " << InRenderable->GetId() << "as a child to "
            << Parent->GetId() << " because the parent is an unknown GUIType";
         throw FExceptionHandler(StrStream);
      }
   }
}


Image


Offline
 Profile  
 
 Post subject: Re: Some GUI Questions
PostPosted: Mon Jan 04, 2016 4:42 pm 
Site Admin

Joined: Sun Feb 11, 2007 8:59 am
Posts: 1105
Location: Ontario Canada
Instead of this...
Mebourne wrote:

         if (dynamic_cast<FGUIWindow*>(Parent)) {
            Parent = dynamic_cast<FGUIWindow*>(Parent)->GetBodyArea();
         }
         Parent->AddChild(InRenderable);



...I would just override the GuiWindow's AddChild function so that is always just adds things to the body area, then you don't need any special handling inside the GuiLoader class.


Offline
 Profile  
 
 Post subject: Re: Some GUI Questions
PostPosted: Mon Jan 04, 2016 8:40 pm 

Joined: Mon Mar 24, 2014 2:25 pm
Posts: 69
Thanks for the tip, got it updated. Not the most elegant solution on my end though as I build the window theme inside the GUIWindow class so it has to recognize the title area and body area first being constructed and use the parent GUILayout::AddChild for that call and then it starts using the overriden GUIWindow::AddChild for calls past these initial two to put all content under BodyArea.


Offline
 Profile  
 
 Post subject: Re: Some GUI Questions
PostPosted: Mon Jan 11, 2016 11:26 pm 

Joined: Mon Mar 24, 2014 2:25 pm
Posts: 69
Marek,

Easy question for today, but having a hard time wrapping my head around it... when creating game code, I've noticed any BaseMKO derived object must be created via new versus allowing it's creation on the stack. For example having a class member Image2D* versus Image2D. If you don't, AssetManager will assert when trying to close down as it's pointing to an object that doesn't exist when the class having the stack Image2D has already deleted it.

Is it correct practice to have all assets in game code classes be pointers? An example is below from a little Snake game I made. It properly closes with it setup this way. RectShape is a derived class from VisualMKO that just does a non textured rectangle so you don't have to send in a texture. I guess RectShape's could have been done with a GUIAbsoluteLayout, but logically it doesn't make sense to me to use a GUI object to represent visual game objects that aren't related with the user interface.

class FWorld {
private:
   glm::uvec2 WindowSize;
   glm::ivec2 Item;
   uint32 BlockSize;

   std::vector<FRectShape*> Bounds;
   FRectShape* AppleShape;


Thanks in advance,

Scott


Offline
 Profile  
 
 Post subject: Re: Some GUI Questions
PostPosted: Tue Jan 12, 2016 9:46 pm 
Site Admin

Joined: Sun Feb 11, 2007 8:59 am
Posts: 1105
Location: Ontario Canada
Mebourne wrote:
Is it correct practice to have all assets in game code classes be pointers?


Yes. The AssetManager is responsible for managing all your assets so that is why you should only access them via pointers and never try to delete the pointers yourself.


Offline
 Profile  
 
 Post subject: Re: Some GUI Questions
PostPosted: Wed Jan 13, 2016 2:17 pm 

Joined: Mon Mar 24, 2014 2:25 pm
Posts: 69
Thanks Marek, I got it, the assets are managed under the AssetManager's maps of smart pointers.

With respect to GUI elements. This is more a semantics item, but I noticed you have the Zing elements drawn under GUI items even though they aren't user interface. Is that the intended use case for all Sprites in future games under the engine design?


Offline
 Profile  
 
 Post subject: Re: Some GUI Questions
PostPosted: Wed Jan 13, 2016 2:54 pm 
Site Admin

Joined: Sun Feb 11, 2007 8:59 am
Posts: 1105
Location: Ontario Canada
Good question!

When I created Zing a few years back, the Shader Engine at the time didn't have mko objects.... it only had gui objects since that is where I started with the implementation so that is what I had to use. After the Zing series is done and I go back to showing more Shader Engine videos you'll see that the next thing that I'll be adding are real Sprite objects. These sprites are going to inherit from the mko class and not be part of the GUI. Those of the objects that you'll want to use for any real game, as those objects are meant to be "game" elements, not GUI objects.


Offline
 Profile  
 
Display posts from previous:  Sort by  
 Page 1 of 1 [ 20 posts ] 

All times are UTC - 5 hours


Who is online

Users browsing this forum: No registered users and 1 guest


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum

Jump to:  

cron