CEGUIBuildDialog         CEGUI dialog which displays rotating 3D meshes on multiple buttons

Introduction

The code presented here will create a CEGUI dialog box with multiple pushbuttons, each displaying a single rotating 3D mesh, as shown in the following image


DialogBuild.jpg

When the user clicks on one of these buttons, the dialog box gets hidden and a game action may be executed.


IMPORTANT

The code in this dialog box is highly game-specific, and WILL need to be changed to run in your environment.
This code will not even compile without the game framework I am using, due to missing class definitions and structures.
However, it should not be a major ordeal to make these changes. I hope the code is generic enough to make it useful.

Dialog source code and Layout

Here are the complete source code and layout files for this dialog box.
Please refer to them as they are discussed.

DialogBuild.layout

Section "Build/Cancel"

Defines the Cancel button at the bottom

Sections "Build/Structures", "Build/BioUnits", "Build/Mechs", and "Build/Vehicles"

Defines the four buttons at the bottom for switching itemTypes.

Section "Build/Scrollbar"

Defines the scrollbar at the right

Sections "Build/Button00" - "Build/Button21"

These are the actual Entity buttons, displaying the 3D meshes. They are numbered by Row/Column.

Sections "Build/ButtonLabel00" - "Build/ButtonLabel21"

These are read-only edit boxes at the bottom of each Entity button, used to provide a label for each button.

Sections "Build/ButtonText00" - "Build/ButtonText21"

These are read-only multi-line edit boxes to the right of each Entity button, used to provide a more detailed description for each button.

DialogBuild.h

The first thing in this file that may need to be changed are two #defines
DIALOG_BUTTON_COLUMNS and DIALOG_BUTTON_ROWS.
These should be set to the number of EntityButtons defined in DialogBuild.layout.
Next are the IDs for the itemType buttons
buttonStructuresID, buttonBioUnitsID, buttonMechsID, and buttonVehiclesID.
These are game-specific and hard-coded, so you will probably want to change the names and labels of these buttons.
If you do change these, the event handlers will also need to be changed/added
handleButtonStructures, handleButtonBioUnits...
And finally, the last thing that may require changing are the EntityButton handlers, handleButton00 - handleButton05.
If you keep the number of EntityButtons at six, then these won't have to change.
However, if you add or subtract buttons, you will have to add or subtract the appropriate number of handlers.

DialogBuild.cpp

The follow include files are game specific and are not included in this sample.
They will have to be changed to match your environment.
#include "InputHandler.h"
#include "PlayState.h"
#include "Common/StaticEntity.h"
#include "Common/EntityMgr.h"
Next are all the ID definitions for the layout.
If you change the layout file, make sure these IDs still match the layout.
The definition for RTT_WINDOW_SIZE essentially determines the resolution displayed in each EntityButton.
The line
#define INITIAL_ITEM_TYPE     ItemType_Building
is also game specific and will have to be changed to match some definition in your environment.
It is used to determine what Entities are displayed on the buttons,
so you will have to have some sort of identifier to distinguish between different types of Entities (Structures, Vehicles, Characters...).

DialogBuild::DialogBuild

Probably the only thing needing changing here are the itemType button event handlers
rootWindow->getChild(buttonStructuresID)->subscribeEvent(PushButton::EventClicked, Event::Subscriber(&DialogBuild::handleButtonStructures, this));
rootWindow->getChild(buttonBioUnitsID)->subscribeEvent(PushButton::EventClicked, Event::Subscriber(&DialogBuild::handleButtonBioUnits, this));
rootWindow->getChild(buttonMechsID)->subscribeEvent(PushButton::EventClicked, Event::Subscriber(&DialogBuild::handleButtonMechs, this));
rootWindow->getChild(buttonVehiclesID)->subscribeEvent(PushButton::EventClicked, Event::Subscriber(&DialogBuild::handleButtonVehicles, this));
If you change the number of buttons on the dialog, then the handlers for those will also need changing accordingly
rootWindow->getChild(buttonID[0])->subscribeEvent(PushButton::EventClicked, Event::Subscriber(&DialogBuild::handleButton00, this));
rootWindow->getChild(buttonID[1])->subscribeEvent(PushButton::EventClicked, Event::Subscriber(&DialogBuild::handleButton01, this));
rootWindow->getChild(buttonID[2])->subscribeEvent(PushButton::EventClicked, Event::Subscriber(&DialogBuild::handleButton02, this));
rootWindow->getChild(buttonID[3])->subscribeEvent(PushButton::EventClicked, Event::Subscriber(&DialogBuild::handleButton03, this));
rootWindow->getChild(buttonID[4])->subscribeEvent(PushButton::EventClicked, Event::Subscriber(&DialogBuild::handleButton04, this));
rootWindow->getChild(buttonID[5])->subscribeEvent(PushButton::EventClicked, Event::Subscriber(&DialogBuild::handleButton05, this));

DialogBuild::~DialogBuild

Very generic. Nothing to see here.

DialogBuild::HandleKeyDownEvents

This is used to capture the ESC key being hit, to close the dialog box.
It uses SDL and my own InputHandler class, so you will have to change this to work with your input system.

DialogBuild::FrameStarted(Real timeElapsed)

This should be called every frame to rotate each of the Entities.
Pass in the time since the previous frame.

DialogBuild::preRenderTargetUpdate

This is an event handler, called by Ogre just before the RTTs are rendered.
Here we disable drawing everything but our Entities via the SpecialCaseRenderQueue functions, including the skybox and terrain.
Also in this function is more game-specific code
global->rootNode->setVisible(false);
The idea behind this is that every "normal" sceneNode is derived from global->rootNode.
Therefore, when this node is hidden, everything in the world attached to that node is hidden, and therefore NOT drawn on the EntityButtons.

DialogBuild::postRenderTargetUpdate

Similar to DialogBuild
:preRenderTargetUpdate, but here we turn on normal rendering to display everything once again.

DialogBuild::handleScrollChanged

The event handler for the scrollbar.

DialogBuild::handleButtonCancel

Closes the dialog box without taking any other actions.

DialogBuild::handleButtonStructures

Event handler for the Structures button.
Changes the item type displayed on the dialog box to ItemType_Building (a game-specific enum).
The buttons will be re-initialized to display these.

DialogBuild::handleButtonBioUnits

Event handler for the BioUnits button.
Changes the item type displayed on the dialog box to ItemType_Character(a game-specific enum).
The buttons will be re-initialized to display these.

DialogBuild::handleButtonMechs

Event handler for the Mechs button.
Changes the item type displayed on the dialog box to ItemType_Mech(a game-specific enum).
The buttons will be re-initialized to display these.

DialogBuild::handleButtonVehicles

Event handler for the Vehicles button.
Changes the item type displayed on the dialog box to ItemType_Vehicle(a game-specific enum).
The buttons will be re-initialized to display these.

DialogBuild::handleButton00 - DialogBuild::handleButton05

Event handlers for each of the EntityButtons.
Each handler hides the dialog box, then calls the game-specific code
global->playState->SetPlaceEntityType(displayedEntityType0);
Change this function call to do something useful in your code.
The variable displayedEntityType indicates what type of Entity was selected by the user,
and is initialized in the function DialogBuild
:PopulateButtons().

DialogBuild::InitializeForItemType

Changes the itemType to be displayed on the dialog box.
Also updates the scrollbar according to how many different Entities will be available.
EntityTemplate is a game-specific class which contains information about each Entity type.
global->entityMgr->GetEntityTemplateCount() returns the number of EntityTemplates available (the count).
The following section of code in this function will have to be changed to work with your game framework
EntityTemplate *  entityTemplate;

   // Count the total number of Entities eligible to be displayed in the Build dialog.
   entityCount = 0;
   for (entityIndex = 0; entityIndex < global->entityMgr->GetEntityTemplateCount(); entityIndex++)
      {
      entityTemplate = global->entityMgr->GetEntityTemplateFromIndex(entityIndex);
      if (entityTemplate && (entityTemplate->itemType == itemTypeToDisplay))
         entityCount += 1;
      }

DialogBuild::PopulateButtons

Initializes the Ogre Entities, Cameras, and RTTs for each of the EntityButtons.
Called from the show() function, as well as when the user scrolls the scrollbar, or changes the type of item via one of the buttons.
This function also uses the EntityTemplate class, which will have to be changed.
Entities are not destroyed when removing them from a button.
Rather, they are moved to a hidden sceneNode, hideObjectsNode, where they may be reused when needed.

DialogBuild::show

Shows the dialog box.

DialogBuild::hide

Hides the dialog box.