Dumb newbie problems

Stardragon

19-03-2009 10:49:26

Hi,

I'm trying to set up QuickGUI to work inside one of my projects. It's the first time I've used the GUI, and while I'm struggling with it I just want to say I really, really like it. :) I'm probably being a bit dumb, hence the subject, but I'm having problems as follows:

1. In the tutorial, it says to #include QuickGUIRoot.h. That doesn't work for me: I have to #include QuickGUI.h, else I get errors such as 'undefined type: QuickGUI::SkinManager' when I try to compile.

2. I know I'm being terminally dumb, but please could you tell me where to put the skinfiles and other bits and pieces necessary to run the GUI?

I'm using the current releases of both Ogre and QuickGUI, so I'm assuming that everything is as up-to-date as it can be. :)

Thanks for the help, from a dumb newbie. :)

magiconexxx

19-03-2009 12:06:31

First off, your not being dumb, so don't worry about asking 'newbie' questions. You've gotta start somewhere!

That being said:

1. I have read on other postings that others have had problems with including the correct headers in the latest release, especially when looking at the tutorials. I think a cleanup of both code and documentation needs to be done. If QuickGUI.h works, stick with it.

2. All the skinfiles and images can go anywhere, really: as long as you include the directory path in your Ogre resources file, and initialize the resources appropriately. Personally, I create a new resource group called "GUI" for this purpose, just to make it cleaner. I usually put them under Media/skins/qgui.

Stardragon

19-03-2009 16:50:21

Thank you for your kind reply. :)

I've put things in a media/GUI directory, pointed Resources.cfg at them and it works fine... UNTIL I try to close the application down. At that point it crashes out with an Unhandled Exception error in quickguiwindow.cpp, in the Window class dtor:


if(!mTexture.isNull())
{
>>> Ogre::String texName = mTexture->getName(); <<<
mTexture.setNull();
Ogre::TextureManager::getSingleton().remove(texName);
}


The little arrow is pointing at the line I've put pointers on. Now all I've done is set the thing up and make it run, and it does... and then it crashes. :(

kungfoomasta

19-03-2009 17:46:31

I've updated the wiki, I've recently made changes such that users should just include "QuickGUI.h" and not "QuickGUIRoot.h", like in the past. Thanks for pointing this out!

Regarding the crash on shutdown, it might be caused if you're deleting QuickGUI after deleting Ogre. QuickGUI should be deleted prior to Ogre. I will update the Wiki to point this out.

I'm glad you like the lib! If you have any suggestions or questions please post them. :)

Stardragon

19-03-2009 19:18:54

Ohfercryin'outloud... *smacks his forehead with a foreclaw* Dammit, you're quite right, I'd got the deletion order mixed up. Blast, bother and darnation! And I all meself a coder, etc., muttermuttermutter.

I do have a question that might be a bit more complex than what I've posted thus far :lol: I've designed my project to be modular and reasonably loosely coupled. There are several 'Manager' classes which are singletons, such as the Input_Manager (OIS wrapper) and Audio_Manager (SDL_Mixer wrapper), just to keep things tidy as much as anything else. I was going to write a UI_Manager class, but when I started to #include QuickGUI.h in more than one place, I started getting all sorts of angry compiler errors about Factories and other stuff... it really was not a happy bunny. It doesn't bother me too awfully much, since I'm planning a very, very pared-back UI (I mean, seriously minimalist), so I don't mind handling things from inside my Ogre_Renderer class (though I'd rather not if I don't have to), but I was curious as to what was going on between Ogre and QuickGUI that would cause a veritable chickenpox of such errors.

Something else that occurred to me as I was browsing the .sheet files... is it possible to define the basic root panel as (width, height) instead of absolute pixel widths while using that script? Say the parser reads the keyword width, it will query the renderer for the current screen width... just a thought, and something that's probably in there already. It does seem a damned, damned fine piece of codery. Really. :)

kungfoomasta

19-03-2009 20:18:00

:lol:. At least it was a simple problem!

I remember another post that mentioned the issue of Ogre and QuickGUI causing a clash over the Factory class. I'm not sure why this is; unless I made a mistake, I think QuickGUI's Factory is inside the QuickGUI namespace, and I have the #ifndef/#define/#endif conditions in all my header files. I will try to repro this issue tonight and see where it leads.

About the width, I've had some requests for this, and I didn't implement it because its possible to have Sheets that are larger than the viewports they are drawn in. For example, in the upcoming editor I'm developing, you can have an 800 x 600 window, and be creating a layout for a sheet that is 1600 x 1200. I think what I can do, is have a property of the GUIManager, such that sheets that are set as the active sheet have their dimensions changed to match viewport dimensions. However I can only do this when the active sheet is set, QuickGUI has no way of knowing when the viewport is being resized. If your code resizes the viewport, you'll have to notify the GUIManager, or update the Sheet size manually.

GUIManagerDesc d;
d.updateActiveSheetSize

void GUIManager::setUpdateActiveSheetSize(bool update);
bool GUIManager::getUpdateActiveSheetSize();


I'll have this property set true by default, since its more likely to be the popular scenario. If you can think of a more intuitive name for the property let me know.

Stardragon

19-03-2009 20:54:19

I think that would work very well. I'm really thinking of it for user option switching, between say 800x600 and 1024x768... I only want the Sheet to fit to the screen, so I'd set the dimensions to, say, WIDTH and HEIGHT respectively. Then QuickGUI, the wonderful, wizzo piece of software it is, is so clever it handles changes in size automagically ;)

Stardragon

19-03-2009 21:44:37

I think that would be really rather good, and very kind of you. Just to be picky, dare I suggest


mGUIManager->fitAllSheetsToViewport();


as well?... :?

Edit: Okay, that's weird... kungfoomasta's reply to my previous post vanished when I posted this one...

kungfoomasta

19-03-2009 22:49:02

hehehe, you're quick! I made a post, but wanted to look up some QuickGUI code before I made my suggestion. (can't get to code base until tonight)

I believe I have a function

GUIManager::notifyViewportDimensionsChanged()

or something like this, as its needed for scrollabel sheets, when sheets are larger than viewport they are on. I originally proposed a Sheet::fitToViewport method, but then I realized I may want users to go through the GUIManager API and not the Sheet API.

There is a SheetManager::resizeAllSheets(...) method, which will resize all sheets to a particular size. I try to be convenient at times, but I also don't want to make too many assumptions, especially since QuickGUI should be able to support multiple GUIManagers using different viewports of various sizes, with the ability to switch out sheets from each GUIManager. Of course this might not be realistic, maybe everybody just wants one full screen solution. :lol:

Stardragon

19-03-2009 23:08:29

*laughs* Maybe they do, but one simple solution will work for me. I'm a very simple kind of guy really :)

Here's another question... how would be the best way to do buttons that weren't? --- By which I mean... well, remember the front menu for DOOM, which was just text?... could I even do that in QuickGUI? It would be easy if you could tell the GUI not to require skins, or only load certain ones, while at the moment it has to have a skin for everything...

The other thing that I wonder is, since QuickGUI is tied in to Ogre, is it possible to have multicoloured text? I think I'm right in thinking that Ogre Overlays (which I know QuickGUI doesn't use any more! *grin*) have a way of having text coloured differently at the top to the bottom so that it cross-fades... uhm... shall I just shut up now? :oops:

Sorry to be a major pain here... :( One newbie, SO many questions...

kungfoomasta

20-03-2009 00:50:57

I didn't play doom much, but its definately possible to do what you describe. Basically you create a skin for the button or widget, and give it transparent skin elements. (Everything needs a skin, but the skin can be empty) The wiki entry on how the skins work should be a decent intro to this. If they aren't, let me know and I'll add more information to them.

QuickGUI supports multi colored text in the form of each character as a different color. I do know what you're talking about with the gradient kind of coloring, where the top of a character could be red, and the bottom yellow, for example. I didn't think anybody really used that feature... I'd have to think about how this could be added, if you really want it. I think it would be really difficult to add this in, honestly.

Questions and discussion is good, it usually brings up new ideas to consider. :)

Stardragon

20-03-2009 22:42:19

To be honest, I'd appreciate fuller information on skinning and such, and perhaps a bit more information on some of the API stuff as well. For instance, how static textures might work, buttons and bars and things... and if it's possible to inject data into QuickGUI without using OIS eventargs...

(Also, whatever happened to Tutorial 3?...)

I know you're doing this on your own and so I apologise for asking, but... I think it would be a help.

kungfoomasta

21-03-2009 00:24:53

Until the framework/interface/design is really set in stone, I probably won't fill in the wiki entry for creating a custom widget. Might be a little while longer, I'm still finding necessary changes every month.

About the skinning, I can try to add some more content for next release (11 days). The more specific you make it, the easier I can fill you in. For example, did you understand how the SkinElement definition structure works, and how Skin definitions can be made, etc? Or maybe the SkinElement properties were confusing? Or setting the skin via code, etc.

Don't worry, the list is always growing longer, but I'd still rather have some feedback instead of none. I just can't promise I can do everything in a timely manner, but I try to prioritise. :)

Stardragon

21-03-2009 14:42:54

To be honest and fair, the skinning content makes sense already: I had read it when I was tired and as a consequence I hadn't taken it in. My apologies.

Another thing (groan) which occurs to me is this: you have to set text on a Button using a std::vector of strings... which is a good idea! Me like. But could it be possible just add an overloaded function to setText() so that you can pass just a single string?... I'm just being annoying, I know, but for simple one-line buttons it would save having to fiddle around with a vector.

And... uhm... here's another idea... is it possible to set a global alpha level for a Sheet?... so you could fade them in and out as a single entity?... You could also 'stack' sheets that way, which would be quite nifty, too... the previous stuff remaining visible through the upper sheets...

... uhm. I'll just shut up now. :D

Calder

21-03-2009 16:16:42

Oooh, monthly release cycle? I can't wait for the next release, maybe I'll even be able to get it to compile!

kungfoomasta

21-03-2009 17:32:43

Calder, I would make a release right now for you to try, but I'm in the middle of making some large changes, particularly to the factory, which all the Widgets use. Working on it! (sorry)

Stardragon, thanks for the input. You don't have to keep coming up with ideas, just post when you think of something. :lol:

For Text, I've made overloads to make it easy to pass in just one line of Text:

Button* createButton(const Ogre::UTFString& text, const Rect& dimensions);

Note that the color and font are not specified, and so each widget has a default font and color. You can also change these as well. You can change the default font in QuickGUI::Root, if you want everything to use the same font. This might be a good tidbit to add onto the wiki, when I can get some time.

For Opacity:


/**
* Sets whether this widget will inherit the opacity of its parent.
* NOTE: Widgets will always inherit the opacity of their owner Window or Sheet,
* whichever comes first.
*/
void setInheritOpacity(bool inherit);

/**
* Sets the opacity of this widget. Values will be curbed within the range [0,1]
* NOTE: Widgets will always inherit the opacity of their owner Window or Sheet,
* whichever comes first.
*/
void setRelativeOpacity(float opacity);


Only the Active Sheet can accept input from the mouse/keyboard, so having stacked Sheets would only be useful if the Sheets underneath are static. Stacking of Sheets are not supported, but you can imitate this using Image widgets, and setting the skin of the Sheet, etc. This function might be useful:


/**
* Writes the windows generated texture to file.
*/
void saveTextureToFile(const Ogre::String& filename);


Keep in mind a Sheet IS a window, so you can save the Sheet's texture to file. I guess as some point I should allow people to get the Ogre::TexturePtr belonging to the Window, allowing the Texture to be used in Ogre Materials.

Stardragon

21-03-2009 20:38:25

Kungfoomasta, I'm genuinely not trying to come up with ideas... I'm just posting things when they occur to me as I'm learning my way around the API :) Since you mention the factory, did you manage to look into that glitch I posted about above?

Question: if I wanted to have a static image on a Sheet - a PNG or a TGA, say - what would be the best way to go about it? Not to have it extend across the entirety of the Sheet, but just to have it as a title bar of some sort?

kungfoomasta

21-03-2009 21:11:30

I was able to finish the work against the Factory, its a lot different now. I've posted up a link to the release in another thread, if you want to try it out. The main interface change will be the use of the "DescManager" class, to get Descs. Its not an official release, so I won't update the wiki until 9.04 is released.

If you want only an Image across the top of the Sheet, I would suggest using an Image widget, and making a skin for it. The Image skin definition is really simple:


SkinType default
{
SkinElement background
{
}
}


QuickGUI supports all the same Image types that Ogre supports, it all depends on the codecs that Ogre detects and accepts. I haven't used TGA myself, but if you wanted to make a skin for the Image, this would be the skin to create:


SkinType MyImageSkin
{
SkinElement background
{
Border_Bottom 0
Border_Left 0
Border_Right 0
Border_Top 0
Texture myimage.png
TileBackground false
TileBorders false
}
}


The other option is to create a skin for the Sheet itself, but then you would have a huge texture, ie 800 x 600, with it mostly being transparent, except for the top section. I'm not sure if this would have any kind of performance effect, I think both methods would be the same, it just depends what you want. Let me know if that helps!

Stardragon

22-03-2009 02:10:09

I know I'm being seriously dumb, but could you spare an example code snippet for setting up that Image? I haven't got much done today for all sorts of reasons, but I have installed v9.0.3b of your code, and had a tinker with the editor (which is good for what's there and will be really useful when it's done). I ended up with this:


ImageDesc* id=QuickGUI::FactoryManager::getSingleton().getWidgetFactory()->createWidget(QuickGUI::ImageDesc);


after going through numerous permutations involving dynamic_casts, <...> everywhere and then just thought, Blow it, I'll ask instead. So, this is me, dumb newbie, asking for yet more help :?

kungfoomasta

22-03-2009 04:32:18

haha, no problem.

Assuming you have your default sheet, like in the wiki examples:


QuickGUI::Image* i = mDefaultSheet->createImage(QuickGUI::Rect(0,0,800,200));
i->setSkinType("myImageSkin");


OR


QuickGUI::ImageDesc* imageDesc = QuickGUI::DescManager::getSingletonPrt()->getDefaultImageDesc();
imageDesc->widget_dimensions = QuickGUI::Rect(0,0,800,200);
imageDesc->widget_skinTypeName = "myImageSkin";
QuickGUI::Image* i = mDefaultSheet->createImage(imageDesc);


In general, you will only use the Widget/DescFactory when you want to register a type, ie a custom Widget/WidgetDesc. The DescManager is used when you need a Desc object. Widgets are created from other Widgets, starting at the Sheet. For example you can create a Panel from the Sheet, and create a Button from the Panel, etc.

The editor should be pretty slick in a week or two.. 8)

Stardragon

22-03-2009 10:02:27

Okay... now my original, copied-from-Playpen code won't compile.

Because QuickGUI is tightly integrated with Ogre, I've got the QuickGUI initialisation code in my Renderer class, although the actual UI stuff is now farmed out to a class of its own. This is what I have, and it did work:


gui_root=new QuickGUI::Root();

QuickGUI::GUIManagerDesc gui_manager_desc;

gui_manager_desc.sceneManager=scene_mgr;
gui_manager_desc.viewport=camera->getViewport();
gui_manager_desc.name="Sentinel_GUI";

gui_manager=QuickGUI::Root::getSingletonPtr()->createGUIManager(gui_manager_desc);


Now, though, it crashes out with an unhandled exception on the last line. I'm running QG 9.0.3b, as I think I said before. Any ideas? :(

kungfoomasta

22-03-2009 17:14:37

Have you run

QuickGUI::SkinTypeManager::getSingleton().loadTypes();

?

In the GUIManager constructor the Mouse cursor is created, and if it tries to set the Mouse Cursor skin to "default", but no "default" skinType exists, an exception is thrown. It's hard to say why you're getting a crash from the following code, stepping through the function would be the easiest way to see whats happening.

Stardragon

22-03-2009 19:35:56

Excuse me while I dig a VERY large hole and bury myself in it. You may all grill burgers in the heat emanating from my face...

Something which has occurred to me just this moment which is probably already on your list of Things To Do... is there any way to specify positions as decimals?... so that if the screen is resized they automatically scale up?... So, if I wanted to create an image, I could say createImage(Rect(0.2, 0.2, 0.5, 0.5))...

... I'll shut up now. Get your marshmallows and sticks at the door...

EDIT (later...)

You know, I must be as dumb as a box of rocks because NOTHING I do with this API seems to work and all around me people seem to be throwing up GUIs left, right and centre. I can't even get a simple texture to appear on the screen without all hell breaking loose. I wrote the following:


SkinClass title
{
SkinType title_skin
{
SkinElement background
{
Border_Bottom 0
Border_Left 0
Border_Right 0
Border_Top 0
Texture Sentinel.png
TileBackground false
TileBorders false
}
}
}


and the program crashes at the loadTypes() command. I remove the first level of nesting, leaving just the skinType definition, and it runs to there but crashes out spectacularly when I try to define the image using that skin. It gives me an error I've never seen before, and I've seen plenty: Run-Time Check Failure #0 - The value of ESP was not properly saved across a function call. This is usually the result of calling a function declared with one calling convention with a function pointer declared with a different calling convention. I've done some testing and found it's the second line of this code it objects to:


QuickGUI::Image* title=sheets[0]->createImage(QuickGUI::Rect(0, 0, 400, 300));
title->setSkinType("title_skin");


sheets[] is an array of Sheet* objects, just so you're aware.

I'm sorry to be a royal pain in the tail, but I just really don't know what I'm doing wrong. I've tried to create just a simple bog-standard button and it works fine... this, though... *sighs* I feel so frakkin' dumb. :(

ANOTHER EDIT (later still...)

I solved that problem, by just using


Image* title->setImage()


rather than going through the whole skinning thing. Works fine. :?

kungfoomasta

22-03-2009 23:52:29

I had to run, but I halfway typed up a response before I left:

Haha, don't beat yourself up too much, although i do get a good laugh from your statements. :lol:

The very first version of QuickGUI had percentage based positioning and sizing of widgets. I tried to incorporate absolute values, where 1.0 equals the height or width of the viewport, as well as relative (to parent), and pixel values. This all became very hard to maintain and organize, so I eventually kept pixel values and tossed the rest. Through use of Anchors you can maintain positions and sizes though. I should probably write a wiki article on this.

Now:

The skin definition problem lies with this: "SkinClass title". You need to give the class of the widget here, ie "Image", "Button", "Console", etc. Also, I currently don't support multiple SkinClass definitions of the same type, so you need to find where "SkinClass Image" is in the provided .skinTypes file, and add in your definition.

So this is what you need to do:
1. Find "SkinClass Image" in "qgui.skinTypes"
2. Add your "title_skin" definition inside the "SkinClass Image" definition.
3. Use the skin in code, by referencing "title_skin"

I'm contemplating a slight upgrade to how skin definitions should be written to disk. I don't like forcing all Image skins to be together, or all Button skins together, etc. The main problem right now is that if the parser runs into 2 instances of "SkinClass Image", it won't be able to store both of them. Kind of like having two Ogre materials with the exact same name.

Stardragon

23-03-2009 01:53:39

Well... here's an idea. Store everything as percentages, but if a definition is given in terms of pixel references then just divide it by the current WIDTH or HEIGHT specified in the Sheet size. That way the values are always correct, even if the Sheet is reloaded and then resized... if that makes any sense at all. :?

As far as the skinning parser problem is concerned, couldn't it be made simply to add definitions to a SkinClass if it encounters a second instance of that Class?... After all, arguably it's the SkinTypes that need to have unique names, not necessarily the SkinClass types... but what do I know :D

kungfoomasta

23-03-2009 23:44:48

Sorry for long delay, I'm working under some tight deadlines at the moment. In response to using relative values for size and positions, its really too much hassle to maintain. In order to follow the current API, I would need functions like this:

Widget::get/setRelativePosition, get/setRelativeSize, get/setPixelPosition, get/setPixelSize, get/setRelativeDimensions, get/setPixelDimensions, get/setAbsolutePosition, etc. and perform conversions between them. In addition to these functions, I'd have to overload them for the various widgets that do special things when their position or size is set. I used to code all my GUI using relative and abosolute values, but after I got used to pixels, and anchoring, I didn't feel the need to use relative or absolute values anymore. Besides, the average user will be using the editor in the future. :)

I wrote a wiki on Anchoring today, I hope it will be helpful to QuickGUI users:
http://www.ogre3d.org/wiki/index.php/QuickGUI_Beginner_Tutorial_3

Regarding the skinning, I use a generic parser that reads in text and organizes them as QuickGUI::ScriptDefinition instances. The first string is the "type" of the definition, and the second is the "id". I can't store duplicate ScriptDefinitions, because I won't know how to give access to them. For example, if you tell me "give me the ScriptDefinition for "SkinClass Image", and I have 5 definitions for it, which one will I give back?

I do think I have a good solution for this problem, though. I will re-write the structure so that Skin definitions look more like this:

ImageSkin default
{
...
}

ImageSkin myImageSkin
{
...
}


This way you can have these definitions in any .skinTypes file. (is that a good extension? Maybe .skinDef?)

Let me know what you think about the wiki article, if its lacking in content, or poorly explained, etc.

Stardragon

24-03-2009 00:00:19

That makes complete sense. And using Anchoring is definitely a better way. *bows deeply to the true Masta* :)

Something entirely new I'm having problems with is the font positioning in buttons and labels... Now, this could be down to me using an unusual font, though I've tried it with the Microsoft Sans Serif font and there's a similar problem. Essentially, the text isn't centred correctly, either vertically or horizontally. It looks like this:

[attachment=0]Font_error.jpg[/attachment]
(And yes, there's the first hint of my current project, right there. *grin* And yeah, behold the awfulness which is coder-art skinning...)

Not quite sure how where to begin fixing this one... :(

kungfoomasta

24-03-2009 00:07:33

Sweet, a screenshot! :D

I'd have to review the code to see the intended behavior. Have you tried making the font size smaller and seeing if it positions correctly? Also, can you show some code on how you create the buttons or labels? I can also try this when I get a chance.

I'm not really sure if this is related, but the overall font height is used when I do vertical centering. In a lot of cases, we never realize there are letters with underhanging parts, ie y,j,g,p,q. Due to the way Ogre generates the font bitmap, I am able to get the max height of a font, and use that for rendering. So even thought we see only numbers, there is space beneath the numbers that should be accounted for. But in this case, I would expect the numbers to be raised some. So like I said this might not be related.

Stardragon

24-03-2009 00:34:54

*grins* Well, since you reacted so nicely to that screenshot, here's another... a bit big, but it does answer one of your questions since it uses fonts of different sizes:

[attachment=0]Font_error_2.jpg[/attachment]
Here's the code that generates it. I've put the odd ellipsis in as it's not all in one block in the original.


renderer=Ogre_Renderer::get_renderer();

gui_root=QuickGUI::Root::getSingletonPtr();
gui_manager=gui_root->getGUIManager("Sentinel_GUI");

Ogre_Renderer::get_renderer()->get_window_size(width, height);

gui_root->setDefaultFontName("dalek.24");
gui_root->setDefaultColor(ColourValue(1, 0, 0, 1));

...

// define the Select Level sheet

sheets[2]=SheetManager::getSingletonPtr()->createSheet(Size(width, height));
sheets[2]->setName("level_sheet");

title=sheets[2]->createImage(QuickGUI::Rect(0, 0, width/3, height/4));
title->setImage("Sentinel.png");

desc->widget_dimensions=QuickGUI::Rect(50, 225, 250, 50);
desc->widget_relativeOpacity=0.75;
desc->widget_inheritOpacity=false;
desc->label_verticalTextAlignment=TEXT_ALIGNMENT_VERTICAL_CENTER;

desc->widget_dimensions=QuickGUI::Rect(50, 700, 250, 50);
desc->widget_name="level_back";
but=sheets[2]->createButton(desc);
but->addText("MAIN MENU");

char* name=new char[32];

for(int z=0; z<20; z++)
{
for(int x=0; x<5; x++)
{
int xp=(width/3)+15+(x*((width-(width/3))/5));
int zp=10+(z*35);

sprintf(name, "%d", (z*5)+x);
desc->widget_dimensions=QuickGUI::Rect(xp, zp, (width-(width/3))/6, 30);
desc->widget_name=name;

but=sheets[2]->createButton(desc);
but->setFont("dalek.18");

sprintf(name, "%d", rnd.number(0, 500000));
but->addText(name);
but->setHorizontalTextAlignment(QuickGUI::TEXT_ALIGNMENT_HORIZONTAL_CENTER);
}
}

for(int x=0; x<6; x++)
{
int xp=(width/3)+15+(x*((width-(width/3))/6));
int zp=720;

int val=1;
switch(x)
{
case 0:
case 5:
val=25;
break;
case 1:
case 4:
val=5;
break;
}
if(x<3) val=-val;

sprintf(name, "control_%d", val);
desc->widget_dimensions=QuickGUI::Rect(xp, zp, ((width-(width/3))/7)-x, 40);
desc->widget_name=name;

but=sheets[2]->createButton(desc);
if(val<0)
sprintf(name, "%d", val);
else
sprintf(name, "+%d", val);

but->addText(name);
but->setFont("dalek.24");
}

ldesc->widget_name="select_menu";
label=sheets[2]->createLabel(ldesc);
label->addText("SELECT WORLD");
label->setHorizontalTextAlignment(QuickGUI::TEXT_ALIGNMENT_HORIZONTAL_CENTER);
label->setTextColor(Ogre::ColourValue(0, 1, 0, 1));


Sorry, that came out a bit long, too. Hopefully you can get a reasonable idea of what's going on.

kungfoomasta

24-03-2009 05:08:47

I ran some simple tests.. it looks like Buttons and labels are centering correctly to me, and are vertically centered by default. Is it possible you can send me your Skin definition for the Label, as well as the textures? benjaminki at hotmail dot com

kungfoomasta

24-03-2009 17:24:38

Stardragon, I also forgot to mention.. could you try using the default label/button skin and see if vertical centering works? I think its somehow related to your skin definitions and/or your new texture images. I'm curious to know what your border thicknesses are, and how they match against the actual skin textures.

kungfoomasta

24-03-2009 18:10:55

Oh I just checked my mail and saw your files. You should try making a skin definition, instead of overwriting the default textures! :)

Here is the default provided Label Skin definitions:


SkinClass Label
{
SkinType default
{
SkinElement background
{
Border_Bottom 1
Border_Left 1
Border_Right 1
Border_Top 1
Texture qgui.label.png
TileBackground false
TileBorders true
}
}

}


The problem with re-using this Skin Definition is that your label texture actually has a border thickness of 4 pixels on all sides. So you can modify the existing one, or just create your own:


SkinClass Label
{
SkinType default
{
SkinElement background
{
Border_Bottom 1
Border_Left 1
Border_Right 1
Border_Top 1
Texture qgui.label.png
TileBackground false
TileBorders true
}
}

SkinType sentinel
{
SkinElement background
{
Border_Bottom 4
Border_Left 4
Border_Right 4
Border_Top 4
Texture sentinel.label.png
TileBackground false
TileBorders true
}
}
}


Make sure in your code you set the skin to "sentinel". This can be done before or after creation.

The same goes for the TextBox textures, it looks like they have a border of 4 pixels as well.

When I get a chance, I'll update the Skinning section more. I think it would be useful to outline what a widget's client area is, and how borders affect the client area. Basically a Widget's client area is the area inside all the borders. In the case of a Button or Label, the text should have its alignment according to the client area. If the SkinDefinition's border's don't match the texture's border, you might get undesirable results.

Try and update the SkinDefinitions to match the texture borders, and see if the results are any better.

Stardragon

24-03-2009 18:21:01

Sent this morning; many thanks for your help.

I've been working slowly on the GUI - lots of interruptions, rather frustratingly, but never mind - and it occurs to me that QuickGUI doesn't have any popup boxes... message boxes, query boxes and the like. What would be the best way to do them?... and is it worth writing a new class for them, based on the ModalWindow class?...

(What I'm trying to do is to pop up a yes/no box now and again... "Are you sure you want to quit?" and such like.)

kungfoomasta

24-03-2009 18:32:49

Ah, good input! It sounds like a wiki tutorial should be created explaining the Modal Window. The Modal Window is what you would use for a message box. In fact I think the Message Box is so common place that I might create it as a convenience for the user. I will add this to the list.

The way ModalWindow works is this: If any ModalWindow is visible, it will block all input outside of the window. So basically you have to dismiss (make invisible) the ModalWindow to be able to interact with the Sheet again. To create a Message Box you can just create a ModalWindow and give it buttons, TextBox, whatever you want. The Editor currently does this (you can use as reference, its quite simple), for Saving/Loading sheets.

Stardragon

24-03-2009 19:23:52

I think a MessageBox class would be good, and would certainly be a good thing. Might I also suggest specialisations of the MessageBox: the BinaryBox [yes/no | OK/cancel] box (two buttons) and the QueryBox yes/no/cancel style box (three buttons). That way the user could just have them pop up.

As a further possible point of interest, I was wondering if it could be possible to have 'floating' widgets, not tied to any particular Sheet? My game will need a query box to pop up in a couple of different places, and it seems pointless to have the same thing created on each Sheet it might appear on. I was going to create the boxes as necessary, programmatically, on whatever Sheet happened to be open at the time... Of course, with preprogrammed box classes this wouldn't be anywhere near so fiddly. But it's just a thought, anyway.

And yes, a Modal Window tutorial would be good. Perhaps, indeed, How To Make A Message Box... ;)

Stardragon

24-03-2009 19:36:29

On the subject of buttons and things, I've done a little test of my own. I restored the default QuickGUI textures and the skinType file to the default and ran the game. Here's a section of the screencap:

[attachment=0]Font_error_3.jpg[/attachment]
I used the default font for the buttons on the right side and the font I want to use on the left. The RHS buttons have the text up from centre, and the LHS buttons down from centre. All the text is very slightly left of centre, for where one would expect. Also something very telling: compare the 'S' of 'SELECT LEVEL' to the 'S' of 'SENTINEL': the former is clipped at the bottom, suggesting there's something odd going on with the bitmap render itself.

... sorry to be such a pain, Kungfoomasta... :( Typical dragon, I turn up and wreck whatever it was worked perfectly until I arrived... :(

kungfoomasta

24-03-2009 20:42:27

lol. I appreciate your feedback, plus I haven't had an active forum in a while. But this is mostly my fault, I haven't really advertised qgui much, because I keep making moderate interface breaking changes with each release. Things are starting to firm up tho..

As a further possible point of interest, I was wondering if it could be possible to have 'floating' widgets, not tied to any particular Sheet? My game will need a query box to pop up in a couple of different places, and it seems pointless to have the same thing created on each Sheet it might appear on. I was going to create the boxes as necessary, programmatically, on whatever Sheet happened to be open at the time... Of course, with preprogrammed box classes this wouldn't be anywhere near so fiddly. But it's just a thought, anyway.

I actually ran into this issue myself with the editor, since the editor has Widgets that have to be a part of the Sheet, and I can load in other sheets. In 9.03b you should have the following APIs:

Sheet::addWindow
Sheet::addModalWindow
Sheet::removeWindow
Sheet::removeModalWindow


Now you can move Windows between Sheets! Also keep in mind that detached Windows will not be properly destroyed unless attached to a Sheet. I currently do not allow users to delete widgets, but I will do something about this in the future, I have a good idea.

I used the default font for the buttons on the right side and the font I want to use on the left.

The buttons on the right are correctly aligned, vertically and horizontally.

The button on the left looks incorrectly centered vertically, but I wouldn't know for sure unless you put a letter in there with a bottom hanging part, ie y,j,p,g,q. As for the clipping, I generally clip everything outside the client area. The bottom part of the 'S' is clipped because it runs over the border of the button. This becomes obvious if you give the button text with a very large font size. The Characters will be clipped appropriately. You'd need to make the button slightly larger if you want to see the text unclipped. Or make the font smaller. Or alter the button's skin definition to have a smaller bottom border thickness, even 0 if needed.

Since the numbers are correctly aligned, however they look wrong to the average user, you can get around this by altering the skin definition, such that the top border is larger. By making it larger, the client area shifts downwar, causing the text to move downward as well.

Stardragon

25-03-2009 20:20:42

Well, I'm not going to argue with the boss *laughs* I've tried fiddling with the border parameters and all that does is mess up the border of the Label or TextBox. Just going from appearances, it looks wrong... if it's actually correct then I dunno. :)

Something I have come across, though, is a problem/query regarding the detection of whether or not the pointer is over a Button. Because I wanted my Buttons and Labels and things to be semitransparent, I used a partial alpha on them before saving. This has led to the Button object flickering between the up and down states whenever the pointer is not over a solid colour. I rather want to keep my GUI as it is, with semitransparent backgrounds, so... is there another solution to this?

Something else that occurs to me (groan, I'm sure). If I wanted to change the mouse pointer, I could easily do that by adding in a new texture and skinning it, yes?... But what if I wanted the hotspot of the pointer to be somewhere other than the top left-hand corner? Say I had a reticle and I wanted the centre point to be the hotspot, is there a way of doing that?

kungfoomasta

25-03-2009 21:10:20

Hm, I'll try your font and textures again, see if I can get the centering to look right. The editor hasn't gotten to a mature enough state where I can change text and fonts easily, any centering issues would probably be more obvious to me when I get to this stage.

I don't have the code on hand, I think the property you're looking for is "widget_transparencyPicking", or Widget::get/setTransparencyPicking, something like that. If its set to false, the button will be detected as soon as you enter its dimensions, regardless of the Texture. I think its set to true by default, which is why you see the flickering.

For the mouse, you can skin it just like Widgets. About the hotspot, I ran into the same issue when dealing with the resize cursors, so I made the hotspot always the center of the texture. If you look at the cursor texture you'll see its a lot bigger than it needs to be, but thats so the mouse pointer points at the center of the image. One of these days I'll update the Skinning article, but probably after a slight refactoring of the script format, as we discussed earlier. :twisted:

Stardragon

25-03-2009 22:24:36

It was widget_transparencyPicking... :)

Something that just happened as a result of setting that false, though, is that the button doesn't reset to 'over' when I release the mouse button after clicking on a button. Instead it remains in the 'down' state. I do have a mouseReleased event handler:


bool UI::mouseReleased(const OIS::MouseEvent &arg, OIS::MouseButtonID id)
{
gui_manager->injectMouseButtonUp(static_cast<QuickGUI::MouseButtonID>(id));

return true;
}


So... dunno what's (not) going on there...

kungfoomasta

25-03-2009 22:42:21

Might be a bug, I'll have to repro it to see whats up.

kungfoomasta

26-03-2009 07:04:30

I can't reproduce any issue. Can you reproduce this using PlayPen? If so, send me the code, and I can figure out whats going on. Otherwise it might be something specific to your setup, or usage.. not sure really. :(

Stardragon

26-03-2009 14:14:05

I think I know what the issue is: there is a partial alpha on the "black" colour on the button. I shaded the centre of the button to something like (32, 32, 32) or (64, 64, 64) - I can't remember which - and then set the alpha value for the image to (0, 0, 0)... so there's some partial alpha on the grey background. Oh well.

Just thought of something. Would it be possible to have a reference to the triggering widget in the EventArgs?... I know it might seem pointless, but I ask because one of my screens can have over a hundred buttons on it, a hundred of which really need to call the same handler function - but it would be useful to know which one had been pressed... What do you think? is it feasible/worthwhile?

Another question: once gui_manager->setActiveSheet has been given a value, how do you tell the UI you want it not to render anything except the mouse cursor?... I presume by passing it a blank Sheet, but I wondered if there was another way...

kungfoomasta

26-03-2009 17:45:13

Did you send me the textures you use for your buttons? I will try that out, last night I didn't have any time, I only quickly tested using the default skin. It could be the base that your skin exposes some issue, I'll check it out.

What do you think? is it feasible/worthwhile?

Definately! Its already supported! Basically the "EventArgs" is the most primitive Args QuickGUI has. Derived types are "MouseEventArgs", "WidgetEventArgs", etc. From the EventArgs you can determine the type, or if you know the type, you can simply cast it and use it. Most of the time, the Args are at least a WidgetEventArgs instance, and a lot of times it is a MouseEventArgs instance, which derives from WidgetEventArgs. Here is an example of how to get the Widget that caused the event to be fired (and thus, caused the handler to be called):


void MainForm::test1(const QuickGUI::EventArgs& args)
{
const QuickGUI::WidgetEventArgs& wea = dynamic_cast<const QuickGUI::WidgetEventArgs&>(args);
Widget* invoker = wea.widget;
...
}

Stardragon

26-03-2009 18:18:23

*bows, a la Wayne's World* I am not worthy! I am not worthy! :D

And yes, the textures of the buttons were included in the zip file I sent you.

Stardragon

27-03-2009 10:26:16

Two things I've just noticed:

1. When I click back and forth through the menus, when I return to Sheets I've already visited, buttons I've clicked on remain in the mouse-over state, even if the mouse has moved.

2. There seems to be a bit of lag on the screen with 100+ buttons... the mouse seems a bit slower on here. (No s---, Sherlock, I hear someone cry. :D ) I'd imagine UIs can get pretty big and complicated, so I just thought I'd mention it.

Although I've also posted this elsewhere I'll comment here as well: I downloaded the latest version of QG (9.03b) from the forum thread to a new machine this morning and tried to install it, and it failed. There seemed to be a file missing: QuickGUIITexWidget.h/.cpp, I think.

kungfoomasta

27-03-2009 17:27:56

@1: Interesting! I think this is a legit bug, I'll have to figure out a good solution. Basically you switched the sheets when you clicked on a button, and the sheet changed, but the state of the sheet was not set to a "default" state.

@2: 100+ buttons! What kind of GUI layout is this? :) I'm guessing the lag is from Widget detection. Every time you move the mouse, I have to sift through the 100+ widgets attached to the sheet and determine if you've moved over a widget, or left a widget, entered a widget, etc. I think the deeper your heirarchy, the more efficient detection is. Here is an example workflow:

1. Sheet: is cursor within Sheet bounds? yes
2. is cursor within Widget A bounds? no
3. is cursor within Widget B bounds? no
....
N. is cursor within Widget N bounds? yes
N+1. Iterate through children and find widget under cursor, until Widget has no children. Return Widget

If you created a few Panels to house the buttons, this would increase your efficiency. The Panels could even be invisible. I don't really know of any great way to organize my widgets in a spacial manner, so that widget detection would be more efficient. If you can think up some method, I'd be interested, but I bet its very complex and hard to implement.

Although I've also posted this elsewhere I'll comment here as well: I downloaded the latest version of QG (9.03b) from the forum thread to a new machine this morning and tried to install it, and it failed. There seemed to be a file missing: QuickGUIITexWidget.h/.cpp, I think.

Post the error messages? :) I renamed the file/class from QuickGUIITextWidget to QuickGUITextUser. I need to know which file is out of date from the zip. Either way, I will re-upload soon, this problem shouldn't exist, as I can build without this problem.

Stardragon

27-03-2009 18:55:19

@2: If you have a look at the image I uploaded towards the bottom of page 2, you'll see what I'm doing with the GUI. Essentially I have a screen that will have the levels a player is able to visit, by virtue of having unlocked them through play. Now, I can either get the player write down 10K level codes (oh, such memories I have of the old days *chortle*) or I grit my teeth and give them a nice simple clean UI that throws up a button for each available level, and they just click it.

Am I not utterly selfless and kind? :twisted:

But anyway, that's why there are up to 107 buttons on that Sheet. I could reduce the number, but it would mean more sheets... it's a trade-off.

As far as organising Widgets goes, it's something you may want to consider anyway if you're planning on allowing massive sheets. My recommendation would be for a quadtree, which allows you to divide the screen into recursively smaller sections. If you like, I can email you a demo I wrote that you could probably adapt quite easily. It has a funky little tweak built-in which makes it slightly more efficient still.

@3: There wasn't really an error message. It compiled through, then came up with something like Cannot file file QuickGUIITextWidget.obj when it got to the linker stage. This was a 100% fresh install and download, so that might have thrown up an error.

@old: Is there a way to tell the gui_manager not to draw anything, but which leaves the mouse pointer still visible?

kungfoomasta

27-03-2009 20:17:01

I would be interested in seeing your code. I can't say I'd take any action other than reading it, but I'm interested to see what its about, I've never done and spacial organizational stuff. I was just kidding about the massive GUI, I knew what you were doing. :lol: But you might consider adding in a few Panels to make detection easier.

What obj throws the error, can you paste the linker error?

Currently the only way to hide a sheet is to call

mGUIManager->setActiveSheet(NULL);

I've had two people request having invisible sheets now, I'll look into it and see if setVisible(false) works, and it not, why it doesn't work. I guess I should be keeping track of these TODO items, otherwise some may get lost. :(

Stardragon

29-03-2009 00:23:57

I've tried using gui_manager->setActiveSheet(NULL) and it doesn't work. It currently crashes out in the QuickGUISheet class at function Window* Sheet::findWindowAtPoint(). The error it gives is this: Unhandled exception at 0x004aada2 (QuickGUI.dll) in Sentinel.exe: 0xC0000005: Access violation reading location 0x00000288. The breakpoint indicator is at the start of the for loop at the beginning of the function:


Window* Sheet::findWindowAtPoint(const Point& p, bool ignoreDisabled)
{
ModalWindow* mw = NULL;

for(std::list<ModalWindow*>::reverse_iterator it = mModalWindows.rbegin(); it != mModalWindows.rend(); ++it)
{
// Visible Modal Window found at point p
if((*it)->getVisible())


To be honest, when I have collections like this I tend to throw in a line


if (STLContainer.empty()) return;


in this sort of place, just to be on the safe side. Realistically, of course, you shouldn't need one, but it's become something of a habit.

kungfoomasta

29-03-2009 10:20:05

The actual problem is that the sheet points is NULL, and using mSheet is not valid (ie mSheet->findWindowAtPoint(...));

I've went through the code and added checks to all the injection functions. Thanks for the bug report! :D

I will try to look into the two other Sheet issues tomorrow. (sheet visibility and texture not reset to default, ie button loads in 'Down' state)

kungfoomasta

29-03-2009 10:31:11

I just thought of the second issue I mentioned, about your situation where you click a button and the sheet is changed:

1. Make sure you are doing the sheet change on the MOUSE_BUTTON_RELEASED event, and not the BUTTON_PRESSED event. QuickGUI shouldn't alter the state of the Sheet, so to prevent the button from thinking it is always in a down state, have it change sheets on button released event.

2. QuickGUI will initially inject a MouseMove of (0,0) when a Sheet is set as the active Sheet. With this in place, when you reload your sheet, if the mouse is not over the button that was previously pressed, the button will not be set to the "mouse over" state.

Stardragon

29-03-2009 22:58:24

Glad to be of help with the bug report. :)

I am indeed using WIDGET_EVENT_MOUSE_BUTTON_UP as the trigger for all buttons and objects where necessary. As far as the MouseMove(0, 0) is concerned, all I know is what I can see, which is that the buttons I clicked on originally to move from that Sheet to the next remains in an Over state. Is it worth, when entering a Sheet, simply forcing all Widgets in the hierarchy to not-Over, and then allowing the GUI to pick up Over events as normal?

Thinking again about gui_manager->setActiveSheet(NULL), one thing I did notice before the program crashed was that the Sheet that was visible just before that command was still visible... all that happened was that the mouse stopped generating events. Also, when I pass Sheet objects around, the current Sheet is hidden and replaced by the newly active Sheet. Now strictly, of course, the old Sheet should still be visible behind the old one... so gui_manager->setActiveSheet() also seems to change the visibility of Sheets. So, then, is it worth having a trap in setActiveSheet() to catch NULL passed to it, in which case it makes ALL Sheets invisible, and also turns off event triggering? (It would be nice, though, if there could be a way just to turn the mouse pointer on and off separately, although I'm sure there already is.)

I'll shut up now. :D

EDIT: I know I'm being very dumb here, but what's a good Subversion client to use? :?

kungfoomasta

30-03-2009 03:05:17

Tortoise SVN, its GUI driven and easy to use. :D

Is it worth, when entering a Sheet, simply forcing all Widgets in the hierarchy to not-Over, and then allowing the GUI to pick up Over events as normal?

All I need to do is fire the WIDGET_EVENT_MOUSE_LEAVE to the WidgetUnderMouseCursor. Its working in PlayPen, from what I see

I'm not sure I understand you for the second part of your post. Here is a bad example of how Sheets and GUIManagers interact with each other:

Pretend the GUIManager is a copy machine, and a sheet is a piece of paper. If no paper is put under the scanner, no copies are being made. (No frames are rendered) If a piece of paper is inserted, copies are made. (Each copy is a rendered image of the piece of paper, ie, the GUI gets rendered) Only one piece of paper can be copied at a time, and only one piece of paper is meant to be inserted into the copy machine at any give time.

Stardragon

30-03-2009 23:28:11

Tiny bug stopping the current SVN release of QG from compiling - I've fixed it in my copy :)


1>d:\quickgui_9_03\quickgui\src\quickguisheet.cpp(532) : error C2561: 'QuickGUI::Sheet::findWindowAtPoint' : function must return a value
1> d:\quickgui_9_03\quickgui\include\quickguisheet.h(174) : see declaration of 'QuickGUI::Sheet::findWindowAtPoint'


Fix: add NULL after the return keyword on the third line, as below.


Window* Sheet::findWindowAtPoint(const Point& p, bool ignoreDisabled)
{
ModalWindow* mw = NULL;

if(mModalWindows.empty()) return NULL;

for(std::list<ModalWindow*>::reverse_iterator it = mModalWindows.rbegin(); it != mModalWindows.rend(); ++it)
{
// Visible Modal Window found at point p


Also, QuickGUIEditor doesn't want to compile out of the box because it doesn't have the linker dependencies set in the project properties.

That problem with the button state (remaining 'over' when the mouse has moved away from it upon return from the subordinate page) persists, I'm afraid. :(

kungfoomasta

31-03-2009 00:14:08

You added the "if empty, return NULL" line? Not only does that skip checking of non-Modal Windows, but not having that check shouldn't cause any problems. If the list is empty, the for loop won't execute at all. And just a friendly tip on coding style, I used to have one line statements on the same line as the "if", but if you do this, you cannot easily debug it. For example:

Instruction pointer ---> if(x) y;

You don't know if the "if" was entered or not. This is better:

if(x)
y;

Regarding compilation, I have my own personal include/lib paths, so I kind of expect that everybody will have to adjust their accordingly. Some people use the SDK, some compile from source, some have their code in multiple places, etc.

That problem with the button state (remaining 'over' when the mouse has moved away from it upon return from the subordinate page) persists, I'm afraid.

I can't do anything without code to reproduce this. If you can modify the PlayPen application to repro this and post the code, I can find and fix it.. I've tested this in the PlayPen and it works as expected on my end. :?

Stardragon

31-03-2009 01:18:03

The "if empty, return NULL" line was originally "if empty, return" when I downloaded it - which caused a compile error because that function has should return a Sheet pointer.

And I see your point about if(...) statements... h'm. Well, I'm not changing all the ones I've written so far, but I may well adapt my style ;) Thanks.

Stardragon

01-04-2009 00:49:53

I have a question (groan)... I want to fade only the background of a Sheet, which begins as fully opaque black, to transparent. Each Sheet has numerous Widgets on it. I've set widget_inheritOpacity to false for all the widgets (Labels, Buttons, etc) but when I start ramping down the opacity of the Sheet, they fade out too. I'm using Sheet->setRelativeOpacity to do this... and what's interesting is the note which comes up if you wait for the hovertext in Visual Studio, which says that widgets always inherit their parent's opacity...

I'm puzzled. I'd like to try to avoid using another image file and material if I can (I don't altogether like them), but if that's the best way then that's how I'll have to go...

kungfoomasta

01-04-2009 01:12:16

Just to make sure your intellisense is up to date, here is something that usually works for me:

1. Clean all projects in solution
2. Close Visual Studio
3. delete the .ncb file
4. Open Solution
5. Rebuild All

I'm not saying intellisense if off in your case, but this is just a useful tip to making sure its accurate. I added in a comment that should say that setting a Window's opacity will effect all child widget's opactiy, regardless of inheritance property. If you think about it, each widget belongs to a window, which has a final texture. If I adjust the opacity of the texture, everything attached to it will receive that effect. To achieve the effect you want, the first thing that comes to mind is to create a window the size of the sheet, with no titlebar, and transparent skin, and have the widgets belong to the window.

Stardragon

01-04-2009 01:33:14

That makes sense. Thank you. :)

EDIT (later...)

Please can you tell me what I'm doing wrong here:


SkinClass Window
{
SkinType default
{
ComponentType hscrollbar
{
ClassName HScrollBar
SkinType default
}

ComponentType vscrollbar
{
ClassName VScrollBar
SkinType default
}

ComponentType titlebar
{
ClassName TitleBar
SkinType default
}

SkinElement background
{
Border_Bottom 10
Border_Left 10
Border_Right 10
Border_Top 10
Texture qgui.window.png
TileBackground true
TileBorders true
}
}

SkinType empty_win
{
ComponentType hscrollbar
{
ClassName HScrollBar
SkinType default
}

ComponentType vscrollbar
{
ClassName VScrollBar
SkinType default
}

ComponentType titlebar
{
ClassName TitleBar
SkinType default
}

SkinElement background
{
Border_Bottom 0
Border_Left 0
Border_Right 0
Border_Top 0
Texture lobby.panel.background.png
TileBackground false
TileBorders false
}
}
}


Trust me, I'll get the hang of this eventually... one day soon it will all fall into place... if I just bash my head on the desk enough times... :D

ANOTHER EDIT (later still...)

Actually, on reflection, I need a fader effect in-game, so... I think I'll just use an Overlay - since, IIRC, QuickGUI renders right at the end of the render queue... am I right?

kungfoomasta

01-04-2009 04:51:53

Remove everything inside the SkinElement:


SkinElement background
{
Border_Bottom 0
Border_Left 0
Border_Right 0
Border_Top 0
Texture lobby.panel.background.png
TileBackground false
TileBorders false
}


To


SkinElement background
{
}


QuickGUI renders at the end of the Overlay render queue by default, but you can change it using GUIManager::setRenderQueueID.