DialogBuild.cpp
#include "stdafx.h" #include "DialogBuild.h" #include "InputHandler.h" #include "PlayState.h" #include "Common/StaticEntity.h" #include "Common/EntityMgr.h" // these must match the IDs assigned in the layout const unsigned int DialogBuild::buttonCancelID = 1; const unsigned int DialogBuild::buttonStructuresID = 21; const unsigned int DialogBuild::buttonBioUnitsID = 22; const unsigned int DialogBuild::buttonMechsID = 23; const unsigned int DialogBuild::buttonVehiclesID = 24; const unsigned int DialogBuild::scrollBarID = 2; const unsigned int DialogBuild::buttonID[DIALOG_BUTTON_COUNT] = { 3, 5, 7, 9, 11, 13 }; const unsigned int DialogBuild::buttonLabelID[DIALOG_BUTTON_COUNT] = { 4, 6, 8, 10, 12, 14 }; const unsigned int DialogBuild::buttonTextID[DIALOG_BUTTON_COUNT] = { 15, 16, 17, 18, 19, 20 }; // Size of each Render-To-Texture texture, in pixels #define RTT_WINDOW_SIZE 128 // World height at which to place each Entity #define OBJECT_WORLD_POS_Y (-500.0) // Type of Entity to be displayed when first opening the dialog box #define INITIAL_ITEM_TYPE ItemType_Building DialogBuild::DialogBuild() : rootWindow(CEGUI::WindowManager::getSingleton().loadWindowLayout("DialogBuild.layout", "Build")) { using namespace CEGUI; Window* parent; itemTypeToDisplay = INITIAL_ITEM_TYPE; scrollOffset = 0; scrollbar = (Scrollbar *)rootWindow->getChild(scrollBarID); // we will destroy the DialogBuild box windows ourselves rootWindow->setDestroyedByParent(false); // Do events wire-up scrollbar->subscribeEvent(Scrollbar::EventScrollPositionChanged, Event::Subscriber(&DialogBuild::handleScrollChanged, this)); rootWindow->subscribeEvent(Window::EventKeyDown, Event::Subscriber(&DialogBuild::HandleKeyDownEvents, this)); rootWindow->getChild(buttonCancelID)->subscribeEvent(PushButton::EventClicked, Event::Subscriber(&DialogBuild::handleButtonCancel, this)); 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)); 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)); int buttonIndex; Ogre::String cameraName; Ogre::String texName; Ogre::String matName; Ogre::String lightName; CEGUI::String imageSetName; for (buttonIndex = 0; buttonIndex < DIALOG_BUTTON_COUNT; buttonIndex++) { displayedEntity[buttonIndex] = NULL; // Create Render-To-Texture texture texName = "RttTex_" + StringConverter::toString(buttonIndex); rttTex[buttonIndex] = global->root->getRenderSystem()->createRenderTexture(texName, RTT_WINDOW_SIZE, RTT_WINDOW_SIZE, TEX_TYPE_2D, PF_R8G8B8); rttTex[buttonIndex]->setActive(false); cameraName = "ButtonCam_" + StringConverter::toString(buttonIndex); rttCam[buttonIndex] = global->sceneMgr->createCamera(cameraName); rttCam[buttonIndex]->setAspectRatio((Real)global->renderWindow->getViewport(0)->getActualWidth() / (Real)global->renderWindow->getViewport(0)->getActualHeight()); rttNode[buttonIndex] = global->sceneMgr->getRootSceneNode()->createChildSceneNode(cameraName); rttNode[buttonIndex]->setFixedYawAxis(TRUE); matName = "RttMat_" + StringConverter::toString(buttonIndex); MaterialPtr material = MaterialManager::getSingleton().create(matName, ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME); material->getTechnique(0)->getPass(0)->setDepthCheckEnabled(false); material->getTechnique(0)->getPass(0)->setDepthWriteEnabled(false); rttTex[buttonIndex]->addListener(this); Viewport *v = rttTex[buttonIndex]->addViewport(rttCam[buttonIndex]); v->setClearEveryFrame(true); v->setBackgroundColour(ColourValue(0.1, 0.2, 0.7)); v->setOverlaysEnabled(false); // Set the CEGUI Button's image to our new RTT Ogre::TexturePtr ogreTex = Ogre::TextureManager::getSingletonPtr()->getByName(texName); OgreCEGUITexture* ceguiTex = (OgreCEGUITexture*)global->guiRenderer->createTexture(); ceguiTex->setOgreTexture(ogreTex); imageSetName = "ButtonTextureImageset_" + StringConverter::toString(buttonIndex); Imageset* textureImageSet = ImagesetManager::getSingleton().createImageset(imageSetName, ceguiTex); textureImageSet->defineImage("RttTex", Point(0.0f, 0.0f), Size(ceguiTex->getWidth(), ceguiTex->getHeight()), Point(0.0f,0.0f)); imageSetName = "set:ButtonTextureImageset_" + StringConverter::toString(buttonIndex) + " image:RttTex"; rootWindow->getChild(buttonID[buttonIndex])->setProperty("NormalImage", imageSetName); rootWindow->getChild(buttonID[buttonIndex])->setProperty("HoverImage", imageSetName); rootWindow->getChild(buttonID[buttonIndex])->setProperty("PushedImage", imageSetName); // Create a spotlight for each Entity lightName = "RttLight_" + StringConverter::toString(buttonIndex); spotLight[buttonIndex] = global->sceneMgr->createLight(lightName); spotLight[buttonIndex]->setType(Light::LT_SPOTLIGHT); spotLight[buttonIndex]->setDiffuseColour(0.93, 0.93, 0.93); spotLight[buttonIndex]->setSpecularColour(0.3, 0.3, 0.3); spotLight[buttonIndex]->setAttenuation(5000.0, 1.0, 0.01, 0.0); spotLight[buttonIndex]->setSpotlightRange(Degree(30), Degree(50), 1.0); spotLight[buttonIndex]->setVisible(false); } hideObjectsNode = global->sceneMgr->getRootSceneNode()->createChildSceneNode("HiddenButtonEntityNode"); hideObjectsNode->setVisible(false); // attach this window if parent is valid parent = System::getSingleton().getGUISheet(); if (parent) parent->addChildWindow(rootWindow); rootWindow->hide(); isShown = FALSE; } DialogBuild::~DialogBuild() { // destroy the windows that we loaded earlier CEGUI::WindowManager::getSingleton().destroyWindow(rootWindow); } bool DialogBuild::HandleKeyDownEvents(const CEGUI::EventArgs& args) { if (isShown) { SDLKey lastKeyHit = InputHandler::getInstance()->GetLastKeyHit(); if (lastKeyHit == SDLK_ESCAPE) hide(); return TRUE; } else { return FALSE; } } void DialogBuild::FrameStarted(Real timeElapsed) { if (!isShown) return; int buttonIndex; // Spin each of the objects around their axis for (buttonIndex = 0; buttonIndex < DIALOG_BUTTON_COUNT; buttonIndex++) rttNode[buttonIndex]->yaw((Radian)(timeElapsed * 0.8)); } void DialogBuild::preRenderTargetUpdate(const RenderTargetEvent& evt) { if (isShown) { #if USE_SEPERATE_ROOT_NODE global->rootNode->setVisible(false); #endif global->sceneMgr->addSpecialCaseRenderQueue(RENDER_QUEUE_MAIN); global->sceneMgr->setSpecialCaseRenderQueueMode(SceneManager::SCRQM_INCLUDE); } } void DialogBuild::postRenderTargetUpdate(const RenderTargetEvent& evt) { if (isShown) { #if USE_SEPERATE_ROOT_NODE global->rootNode->setVisible(true); #endif global->sceneMgr->clearSpecialCaseRenderQueues(); global->sceneMgr->setSpecialCaseRenderQueueMode(SceneManager::SCRQM_EXCLUDE); } } bool DialogBuild::handleScrollChanged(const CEGUI::EventArgs& args) { int newScrollOffset; // This event gets thrown when the scroll bar position moves even a little bit, // and may not cause a change in the scrollOffset. // Only do an update if scrollOffset actually changes. newScrollOffset = (int)scrollbar->getScrollPosition() * DIALOG_BUTTON_COLUMNS; if (newScrollOffset != scrollOffset) { scrollOffset = newScrollOffset; PopulateButtons(); } return true; } bool DialogBuild::handleButtonCancel(const CEGUI::EventArgs& args) { hide(); return true; } bool DialogBuild::handleButtonStructures(const CEGUI::EventArgs& args) { if (itemTypeToDisplay == ItemType_Building) return true; itemTypeToDisplay = ItemType_Building; InitializeForItemType(); PopulateButtons(); return true; } bool DialogBuild::handleButtonBioUnits(const CEGUI::EventArgs& args) { if (itemTypeToDisplay == ItemType_Character) return true; itemTypeToDisplay = ItemType_Character; InitializeForItemType(); PopulateButtons(); return true; } bool DialogBuild::handleButtonMechs(const CEGUI::EventArgs& args) { if (itemTypeToDisplay == ItemType_Mech) return true; itemTypeToDisplay = ItemType_Mech; InitializeForItemType(); PopulateButtons(); return true; } bool DialogBuild::handleButtonVehicles(const CEGUI::EventArgs& args) { if (itemTypeToDisplay == ItemType_Vehicle) return true; itemTypeToDisplay = ItemType_Vehicle; InitializeForItemType(); PopulateButtons(); return true; } // User hit the Entity button at Row 0, Column 0 bool DialogBuild::handleButton00(const CEGUI::EventArgs& args) { hide(); global->playState->SetPlaceEntityType(displayedEntityType[0]); return true; } bool DialogBuild::handleButton01(const CEGUI::EventArgs& args) { hide(); global->playState->SetPlaceEntityType(displayedEntityType[1]); return true; } bool DialogBuild::handleButton02(const CEGUI::EventArgs& args) { hide(); global->playState->SetPlaceEntityType(displayedEntityType[2]); return true; } bool DialogBuild::handleButton03(const CEGUI::EventArgs& args) { hide(); global->playState->SetPlaceEntityType(displayedEntityType[3]); return true; } bool DialogBuild::handleButton04(const CEGUI::EventArgs& args) { hide(); global->playState->SetPlaceEntityType(displayedEntityType[4]); return true; } bool DialogBuild::handleButton05(const CEGUI::EventArgs& args) { hide(); global->playState->SetPlaceEntityType(displayedEntityType[5]); return true; } // The itemType to be displayed changed, either by the dialog being initialized for the first time, // or the user pressed a button to change to a different itemType. void DialogBuild::InitializeForItemType(void) { int entityIndex; int entityCount; EntityTemplate * entityTemplate; scrollOffset = 0; // 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; } if (entityCount <= DIALOG_BUTTON_COUNT) { // There are fewer or equal number of Entities to be displayed than there are buttons, so we don't need a scrollbar rootWindow->getChild(scrollBarID)->hide(); return; } scrollbar->show(); scrollbar->setScrollPosition(0.0); scrollbar->setProperty("DocumentSize", StringConverter::toString((int)(entityCount / DIALOG_BUTTON_COLUMNS) + 1)); scrollbar->setProperty("PageSize", StringConverter::toString(DIALOG_BUTTON_ROWS)); scrollbar->setProperty("StepSize", CEGUI::String("1")); scrollbar->setProperty("OverlapSize", CEGUI::String("1")); } void DialogBuild::PopulateButtons(void) { int buttonIndex; int entityIndex; int scrollCount; Real cameraDist; char meshName[50]; Ogre::String modelName; Ogre::Vector3 cameraPosition; Ogre::Vector3 cameraTarget; Ogre::Vector3 lightDirection; EntityTemplate * entityTemplate; // Move entityIndex up to the value of scrollOffset, and continue from there entityIndex = 0; scrollCount = 0; while ((scrollCount < (scrollOffset)) && (entityIndex < global->entityMgr->GetEntityTemplateCount())) { entityTemplate = global->entityMgr->GetEntityTemplateFromIndex(entityIndex); if (entityTemplate && (entityTemplate->itemType == itemTypeToDisplay)) scrollCount += 1; entityIndex += 1; } // De-initialize all our buttons to make them ready to display a new Entity or be hidden if not needed. // They are all hidden here, and unhidden later if needed. for (buttonIndex = 0; buttonIndex < DIALOG_BUTTON_COUNT; buttonIndex++) { if (displayedEntity[buttonIndex] != NULL) { // Move any existing Entities that we already created for our buttons to the hidden sceneNode. rttNode[buttonIndex]->detachObject(displayedEntity[buttonIndex]); hideObjectsNode->attachObject(displayedEntity[buttonIndex]); displayedEntity[buttonIndex] = NULL; } rttTex[buttonIndex]->setActive(false); spotLight[buttonIndex]->setVisible(false); rootWindow->getChild(buttonID[buttonIndex])->hide(); rootWindow->getChild(buttonLabelID[buttonIndex])->hide(); rootWindow->getChild(buttonTextID[buttonIndex])->hide(); displayedEntityType[buttonIndex] = 0; } for (buttonIndex = 0; buttonIndex < DIALOG_BUTTON_COUNT; buttonIndex++) { if (entityIndex < global->entityMgr->GetEntityTemplateCount()) { // Find the next EntityTemplate that should be displayed on a button. while (entityIndex < global->entityMgr->GetEntityTemplateCount()) { entityTemplate = global->entityMgr->GetEntityTemplateFromIndex(entityIndex); if (entityTemplate && (entityTemplate->itemType == itemTypeToDisplay)) break; entityIndex += 1; } if (entityTemplate && (entityIndex < global->entityMgr->GetEntityTemplateCount())) { strcpy(meshName, entityTemplate->fileName1); strcat(meshName, ".mesh"); rttTex[buttonIndex]->setActive(true); rootWindow->getChild(buttonID[buttonIndex])->show(); rootWindow->getChild(buttonLabelID[buttonIndex])->show(); rootWindow->getChild(buttonTextID[buttonIndex])->show(); displayedEntityType[buttonIndex] = entityIndex; modelName = entityTemplate->name; modelName += "_DialogBuild_" + StringConverter::toString(entityIndex); // Try to grab a saved copy of the Entity we want from the hidden sceneNode. try { displayedEntity[buttonIndex] = (Ogre::Entity *)hideObjectsNode->getAttachedObject(modelName); hideObjectsNode->detachObject(displayedEntity[buttonIndex]); } catch(...) { // Did not already create this type Entity. Create a new one. displayedEntity[buttonIndex] = global->sceneMgr->createEntity(modelName, meshName); assert(_T("DialogBuild::show myModel == NULL") && (displayedEntity != NULL)); } rttNode[buttonIndex]->attachObject(displayedEntity[buttonIndex]); rttNode[buttonIndex]->setPosition(Ogre::Vector3(100.0 * entityIndex, OBJECT_WORLD_POS_Y, 0)); if (entityTemplate->collisionHeight > entityTemplate->collisionRadius) cameraDist = entityTemplate->collisionHeight * 1.5; else cameraDist = entityTemplate->collisionRadius * 2.5; cameraPosition = Ogre::Vector3(100.0 * entityIndex, OBJECT_WORLD_POS_Y + entityTemplate->collisionHeight * 1.2, cameraDist); cameraTarget = Ogre::Vector3(100.0 * entityIndex, OBJECT_WORLD_POS_Y + entityTemplate->collisionHeight * 0.4, 0.0); lightDirection = cameraTarget - cameraPosition; lightDirection.normalise(); rttCam[buttonIndex]->setPosition(cameraPosition); rttCam[buttonIndex]->lookAt(cameraTarget); spotLight[buttonIndex]->setPosition(cameraPosition); spotLight[buttonIndex]->setVisible(true); spotLight[buttonIndex]->setDirection(lightDirection); rootWindow->getChild(buttonLabelID[buttonIndex])->setText(entityTemplate->name); // TODO: populate this text box with real statistics regarding this Entity. rootWindow->getChild(buttonTextID[buttonIndex])->setText("Cost: " + StringConverter::toString(randInt(500,1000))); } else { // Finished going through all our EntityTemplates and could find no more to display. return; } } entityIndex += 1; } } void DialogBuild::show(void) { if (isShown) return; isShown = TRUE; // Force the Dialog to display the first "page" every time it opens. itemTypeToDisplay = INITIAL_ITEM_TYPE; InitializeForItemType(); PopulateButtons(); rootWindow->show(); rootWindow->moveToFront(); InputHandler::getInstance()->SetGUIHasFocus(TRUE); } void DialogBuild::hide(void) { rootWindow->hide(); InputHandler::getInstance()->SetGUIHasFocus(FALSE); if (!isShown) return; isShown = FALSE; int buttonIndex; for (buttonIndex = 0; buttonIndex < DIALOG_BUTTON_COUNT; buttonIndex++) { rttTex[buttonIndex]->setActive(false); if (displayedEntity[buttonIndex] != NULL) { // Move any existing Entities that we already created for our buttons to the hidden sceneNode. rttNode[buttonIndex]->detachObject(displayedEntity[buttonIndex]); hideObjectsNode->attachObject(displayedEntity[buttonIndex]); displayedEntity[buttonIndex] = NULL; } } } void DialogBuild::toggleVisibility() { if (isShown) hide(); else show(); } bool DialogBuild::isVisible() const { return isShown; }