Migration from CEGUI to QuickGUI

SpaceDude

12-12-2007 17:13:11

This is my first time on this forum so please excuse me if this question has already been asked before. I've been working on a game for about a year now, and at the start of the project I just decided to go with CEGUI without a second thought as it seemed to be the de facto GUI system to use with Ogre. But things have changed since then. One of the main things that I think CEGUI is not good at is using custom skins. So I thought I'd give QuickGUI a try. But I don't want to dive in head first and completely remove CEGUI from my game and replace it with QuickGUI. Because that would take too long and I'm not yet sure that QuickGUI fulfils all my requirements yet.

So my question is: Is it possible to use CEGUI and QuickGUI simultaneously in the same application?

To start with I have just added a main menu intro screen to the game, and I'd like to place some buttons on top of it (the buttons should be textures). All I need it to do is to switch between two textures depending on whether the mouse is hovering of the button or not. And obviously have some way of firing off an event when the mouse button is clicked.

Is there any chance of using QuickGUI to do this without stripping out all the CEGUI code? I can only think of one potential issue relating to the cursor position. If QuickGUI and CEGUI each keep track of the cursor position independently then I guess I'm in trouble. Has anybody tried this before?

kungfoomasta

12-12-2007 18:03:26

I haven't tried this, but I think there shouldn't be any problems. QuickGUI shouldn't interfere with CEGUI, so you can create all the required components, and then just inject input into both systems. So if you were using OIS, you'd be injecting mouse positions into both CEGUI and QuickGUI. Also note that if you have overlapping buttons and inject a click into both systems, you will fire events for both buttons. I remember that I don't inject inputs if the mouse cursor isn't visible, so I may need to change some things, if you wanted to support the CEGUI cursor (or even an OS cursor) and still inject input to the GUI.

As far as drawing goes, you can move QuickGUI to a higher render Queue, if there are zOrder issues between them. Currently it defaults to the Overlay Render Queue Group, but there is one above that.

A brief outline of the skinning, as it is implemented right now (it will be upgraded):

You create 3 sets of textures for every button type you want. Each widget has a *skin component* that it uses to determine the texture to apply. A button's default skin component is ".button". So the default qgui skin is made of the following textures:

qgui.button.png
qgui.button.down.png
qgui.button.over.png

Skins are loaded via the skinset manager, and are represented by 2 files: <skinname>.skinset and Skinset.<skinname>.png. If the files are not present, they are built for you.

If you want to support multiple buttons, you could have a set of textures like:

spacedude.button.png
spacedude.button.down.png
spacedude.button.over.png

spacedude.button2.png
spacedude.button2.down.png
spacedude.button2.over.png

etc.

To load the skin and create the 2 files, you would call

QuickGUI::SkinSetManager::getSingleton().loadSkin("spacedude",IMAGE_TYPE_PNG);

Since buttons have a skin component of ".button" by default, you will need to modify the skin component where you want the buttons to use the other defined skin parts:

mySecondButton->setSkinComponent(".button2");
mySecondButton->applyDefaultTexture();

I need to fix this so you don't have to make the call to apply the texture after setting the skin component. :P

SpaceDude

12-12-2007 22:10:39

Ok thanks a lot for the detailed reply, I will try this tomorrow. I'd like to continue using the CEGUI cursor for now. I'm thinking I can synchronise the position by making a call to set the QuickGUI's cursor position equal to that of the CEGUI's cursor each frame. As for the cursor not processing input if the cursor is invisible, could I just modify the cursor's skin to be completely transparent in effect hiding it without actually doing so in the code?

kungfoomasta

12-12-2007 22:20:48

I was thinking along the same lines, regarding a transparent cursor texture. If you delete the .skinset and Skinset.*.png and call "loadSkin" it will rebuild the files for you. You need to do this if you change the textures that are used to make the SkinSet.

Also, whenever the viewport dimensions change (ie resolution changes, or resize render window) you need to notify the GUIManager of the change.

If there are problems let me know.

SpaceDude

13-12-2007 16:44:05

Ok I've got things working now! I like the way it automatically takes textures and puts them into a texture atlas for you and handles the uv coordinates associated with that. I have something similar set up with overlays. I'm wondering if it might be good to convert all my overlays over to QuickGUI widgets. Do you have any idea on the performance of overlays vs widgets? I'm think that neither should be a drain on FPS but I've heard of problems about other libraries.

One other thing, what's the best way to set a full screen background? I tried the following but didn't seem to work:

QuickGUI::Sheet *pSheet = m_QuickGUIManager->getDefaultSheet();
pSheet->getQuad()->setTexture("background.jpg");


Should I create some kind of other widget instead that takes up the full screen and then put widgets on top of that?

kungfoomasta

13-12-2007 17:37:40

I was thinking in the future of forcing people to create the texture atlas in a SkinSet Editor tool. The tool would simply allow the user to set the texture size (its hardcoded to 1024 x 1024 at the moment) and place in textures, mapping them to skin components. The automatic creation of the atlas is nice, but it won't be as optimal, for example, you could create a skin that contains skins for only 3 widgets, you wouldn't need the entire 1024 x 1024. The algorithm to place textures is pretty good, but can't match a human. If I make the SkinSet Editor dead easy and convenient to use, this would be a good alternative, no? (do you think I should try to allow automatic and manual creation as options?)

Regarding overlays: not efficient. Each overlay element, panel, textarea, or otherwise, adds another batch to your rendering. If you replaced your overlays with QuickGUI widgets you should see a boost in performance. I don't know how many overlays you use, so it could be a minimal amount. Using the texture atlas allows me to minimize batching.

For the background, I'm not sure why setting the quad's texture doesn't work. I would recomment using

Sheet::setTexture("background.jpg");

I believe thats in the zip release. :lol:

I have recently converted QuickGUI to make use of materials. Which means you will be using the following code within the near future.

Sheet::setMaterial("myMaterial");

SpaceDude

13-12-2007 19:25:05

>>For the background, I'm not sure why setting the quad's texture doesn't work.

Well the code runs but it then crashes when trying to render. In the file QuickGUIVertexBuffer.cpp, function "void VertexBuffer::_renderVertexBuffer()"


if (mat.isNull())
{
mat = Ogre::MaterialManager::getSingleton().getByName("QuickQuiSkinTemplate");
}

mat->load();
Ogre::Technique *t = mat->getBestTechnique(0);


The line mat->load(); causes a crash because the pointer is NULL.

I tried setting the texture directly on the sheet but that function doesn't seem to exist in the version I downloaded yesterday (QuickGUIv0.9.7PreRelease).

>>I was thinking in the future of forcing people to create the texture atlas in a SkinSet Editor tool.

That's good too. Its true that it may not be ideal to have to distribute an application with duplicate copies of a texture (i.e. 1 on its own and second inside the texture atlas).

I was able to modify the texture atlas size by editing the .skinset file after it was created. I assume this is a feature you implemented. Although it would be kinda nice to be able to specify that in the code somehow. Like:


QuickGUI::SkinSetManager::getSingleton().setSize(512, 512)


before creating the skin.

At the moment all of my overlay elements use the same material, just different UV coordinates. Will it still be rendered as a separate batch even know then use the same material?

I don't have a massive amount of overlays but any performance increase is always welcome.

kungfoomasta

13-12-2007 19:47:19

Well we know the fix for the material issue, I'm assuming the cause of the problem is that you don't have QuickQuiSkinTemplate listed in an Ogre resource path?

I'm in the process of changing this. SkinSets should create their own material, which should be used, so we don't need a default material like "QuickQuiSkinTemplate".

Tuan Kuranes added the code for creating the skinset, as well as showed me how to render materials. (extremely thankful) So I'm not 100% familiar with the code, but its getting there. I will be enhancing/updating the skinning process over time.

This is my thought process, when it comes to users using their own skins with QuickGUI:
1. Load Up SkinSetManager, and create a skin. This will produce 2 files: .skinset file and Skinset.xyz.png
2. Move the 2 files into your own project, make sure they're loaded as Ogre resources.
3. Load the skin in code.
4. Apply skin to widgets, as done currently.

Then the SkinSet class only has 2 main operations:
1. Getting UV texture coordinates. (parse the .skinset file and store data for quick access)
2. Creating the SkinSet material.

Even further in the future I want to make the material persist on disk, but its too early to determine what the process would be, or how I should design it. User feedback for teh win!

But as you see, my process would require use of the SkinSetEditor, since you can't create everything during execution. Ideally we want to do all this extra processing outside execution, so on start up we're just loading, and not creating textures and generating skinset files.