www.pudn.com > RCApp-src.zip > GUI.cpp
/* RedEye Project (http://members.ozemail.com.au/~ndmcevoy/) Copyright (C) 2003 Nick McEvoy This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. ----------------------------------------------------------------- Commented for use with Doxygen (http://www.doxygen.org) ----------------------------------------------------------------- */ /*! \file GUI.cpp * \brief Game gui. * * This file contains the game gui. */ // GLUT includes #include// RedEye includes #include "GUI.h" #include "Engine.h" #include "SoundManager.h" const char* re_version = "1.0"; const char* credits_text = "CREDITS\n\n" " Nick McEvoy : coding & design\n" "\nSpecial thanks to:\n" " Steve Baker : for PLIB & example code\n" " Russell Smith : for ODE physics engine\n" " Larry Ewing : for painting the original Tux image\n" " DigiBen : for 3D Triangle-Sphere overlap testing\n" " Tomas Akenine-Moller : for fast 3D Triangle-Box overlap testing\n" "\nAlso thanks to:\n" " Jarred McEvoy (my son 6 yrs) : game tester\n" " Owen McEvoy (my son 4 yrs) : game tester\n" "\nAnd finaly thanks to:\n" " Donna McEvoy (my wife) : computer widow :)"; const char* about_text = "ABOUT\n\n" "todo:\n"; const char* help_text = "HELP\n" "\nControls:\n" " up arrow : forward\n" " down arrow : reverse\n" " left arrow : steer left\n" " right arrow : steer right\n" " <> : roll left & right (jetski only)\n" "\nView:\n" " f1 : player view\n" " f2 : external view attached\n" " f3 : external view detached\n" " f4 : tracking view\n" " shift+arrows : rotate external camera\n" " page-up/down : zoom in/out external camera\n" " home : reset external camera\n" " t : toggle tracking (closest) target\n" " n : select next target\n" "\nGame:\n" " r : restart\n" " h : help\n" " p : pause\n" " escape : quit\n"; //! The one and only instance reGameGUI* reGameGUI::mpInstance = NULL; static puMenuBar *main_menu_bar; static puDialogBox *dialog_box; static reText *dialog_box_message; static puOneShot *dialog_box_ok_button; static puDialogBox *load_dialog_box; static puListBox *load_dialog_box_list_box; static puOneShot *load_dialog_box_ok_button; static puOneShot *load_dialog_box_cancel_button; #define RE_MAX_LEVELS 20 static char* level_desc[RE_MAX_LEVELS] = {0}; static char* level_dir[RE_MAX_LEVELS] = {0}; static int miNumLevels = 0; static void start_cb(puObject*) { int iIndex = load_dialog_box_list_box->getValue(); char sLevelDir[RE_STRING_MAX]; sprintf(sLevelDir, "%s", level_dir[iIndex]); // Hide the dialog (see warning below) load_dialog_box->hide(); // Start the game reGetGameEngine()->LoadLevel(sLevelDir); // Delete dialog box // warning: if deleted b4 loading level ... we get an // exception due to puMouse(button, state, x, y) arriving // after dialog is deleted !??? puDeleteObject(load_dialog_box); load_dialog_box = NULL; } static void go_away_cb(puObject*) { // Unpause game (if paused) reGetGameEngine()->SetGamePaused(false); // Delete dialog box puDeleteObject(dialog_box); dialog_box = NULL; } static void mk_dialog(int w, int h, const char *fmt, ...) { // Pause game (if running) reGetGameEngine()->SetGamePaused(true); static char sMsg[RE_GUI_STRING_MAX]; int win_w = glutGet(GLUT_WINDOW_WIDTH); int win_h = glutGet(GLUT_WINDOW_HEIGHT); int cx = win_w/2; int cy = win_h/2; int dx = cx - w/2; int dy = cy - h/2; va_list argptr; va_start(argptr, fmt); vsprintf(sMsg, fmt, argptr); va_end(argptr); dialog_box = new puDialogBox(dx, dy); { new puFrame(0, 0, w, h); dialog_box_message = new reText(10, h-30); dialog_box_message->SetLabel(sMsg); dialog_box_ok_button = new puOneShot(w/2-30, 10, w/2+30, 50); dialog_box_ok_button->setLegend("OK"); dialog_box_ok_button->makeReturnDefault(TRUE); dialog_box_ok_button->setCallback(go_away_cb); } dialog_box->close(); dialog_box->reveal(); } static void mk_load_level_dialog(char** list, const char* ok_legend, const char* cancel_legend, puCallback ok_cb, puCallback cancel_cb) { // Pause game (if running) reGetGameEngine()->SetGamePaused(true); int w = 400; int h = 400; int win_w = glutGet(GLUT_WINDOW_WIDTH); int win_h = glutGet(GLUT_WINDOW_HEIGHT); int cx = win_w/2; int cy = win_h/2; int dx = cx - w/2; int dy = cy - h/2; load_dialog_box = new puDialogBox(dx, dy); { new puFrame(0, 0, w, h); load_dialog_box_list_box = new puListBox(w/2-150, 60, w/2+150, h-30, list); load_dialog_box_list_box->setValue(0); if (ok_legend) { load_dialog_box_ok_button = new puOneShot(w/2-30, 10, w/2+30, 50); load_dialog_box_ok_button->setLegend(ok_legend); load_dialog_box_ok_button->makeReturnDefault(TRUE); load_dialog_box_ok_button->setCallback(ok_cb); } if (cancel_legend) { load_dialog_box_cancel_button = new puOneShot(w/2+60, 10, w/2+120, 50); load_dialog_box_cancel_button->setLegend(cancel_legend); load_dialog_box_cancel_button->makeReturnDefault(FALSE); load_dialog_box_cancel_button->setCallback(cancel_cb); } } load_dialog_box->close(); load_dialog_box->reveal(); } static void exit_cb(puObject*) { delete reGetGameEngine(); exit(0); } static void window_on_cb(puObject*) { reGetGameEngine()->SetFullscreen(false); } static void window_off_cb(puObject*) { reGetGameEngine()->SetFullscreen(true); } static void music_off_cb(puObject*) { reGetSoundManager()->SetMusicOn(false); } static void sfx_off_cb(puObject*) { reGetSoundManager()->SetSoundFxOn(false); } static void music_on_cb(puObject*) { reGetSoundManager()->SetMusicOn(true); } static void sfx_on_cb(puObject*) { reGetSoundManager()->SetSoundFxOn(true); } static void versions_cb(puObject*) { char sVersions[RE_GUI_STRING_MAX]; sprintf(sVersions, "VERSIONS\n\n" "Reality Check Version : %s\n" "PLIB Version : %s\n" "ODE Version : %s\n" "OpenGL Version : %s\n" "OpenGL Vendor : %s\n" "OpenGL Renderer : %s\n", re_version, ssgGetVersion(), "0.03", glGetString(GL_VERSION), glGetString(GL_VENDOR), glGetString(GL_RENDERER)); mk_dialog(500, 180, sVersions); } static void credits_cb(puObject*) { mk_dialog(650, 290, credits_text); // todo: would be good to read from xml ... but need \n tags converted, etc... //mk_dialog(650, 290, reGetXMLChildValue(reGetGameEngine()->GetXMLConfigNode(), "Credits", "")); } static void about_cb(puObject*) { mk_dialog(600, 300, about_text); // todo: would be good to read from xml ... but need \n tags converted, etc... //mk_dialog(650, 290, reGetXMLChildValue(reGetGameEngine()->GetXMLConfigNode(), "About", "")); } static void help_cb(puObject*) { mk_dialog(600, 350, help_text); // todo: would be good to read from xml ... but need \n tags converted, etc... //mk_dialog(650, 290, reGetXMLChildValue(reGetGameEngine()->GetXMLConfigNode(), "Help", "")); } // Menu bar entries static char *file_submenu [] = { "Exit", NULL } ; static puCallback file_submenu_cb [] = { exit_cb, NULL } ; static char *view_submenu [] = { "Windowed" , "Fullscreen" , NULL } ; static puCallback view_submenu_cb [] = { window_on_cb, window_off_cb, NULL } ; static char *sound_submenu [] = { "Turn off Music", "Turn off Sounds", "Turn on Music", "Turn on Sounds", NULL } ; static puCallback sound_submenu_cb [] = { music_off_cb, sfx_off_cb, music_on_cb, sfx_on_cb, NULL } ; static char *help_submenu [] = { "Versions...", "Credits...", "About...", "Help...", NULL } ; static puCallback help_submenu_cb [] = { versions_cb, credits_cb, about_cb, help_cb, NULL } ; reGameGUI::reGameGUI() : mNotifyText(0,0), mStatusText(0,0), mPlayerText(0,0), mDebugText(0,0) { puSetDefaultStyle(PUSTYLE_SMALL_SHADED); puSetDefaultColourScheme(0.3f, 0.4f, 0.6f, 1.0f); mNotifyText.setColour(PUCOL_LABEL, 1.0, 1.0, 1.0); mNotifyText.hide(); mStatusText.setColour(PUCOL_LABEL, 1.0, 1.0, 1.0); mStatusText.hide(); mPlayerText.setColour(PUCOL_LABEL, 1.0, 1.0, 1.0); mPlayerText.setColour(PUCOL_BACKGROUND, 0.0, 0.0, 0.8, 0.5); mPlayerText.hide(); mDebugText.setColour(PUCOL_LABEL, 1.0, 1.0, 1.0); mDebugText.hide(); main_menu_bar = new puMenuBar(); main_menu_bar->add_submenu("Game", file_submenu, file_submenu_cb); main_menu_bar->add_submenu("View", view_submenu, view_submenu_cb); main_menu_bar->add_submenu("Sound", sound_submenu, sound_submenu_cb); main_menu_bar->add_submenu("Help", help_submenu, help_submenu_cb); main_menu_bar->close(); main_menu_bar->reveal(); } reGameGUI::~reGameGUI() { mpInstance = NULL; } reGameGUI* reGameGUI::GetInstance() { if (mpInstance == NULL) { mpInstance = new reGameGUI; } return mpInstance; } void reGameGUI::Display() { puDisplay(); } void reGameGUI::Reshape(int w, int h) { int cx = w/2; int cy = h/2; mNotifyText.setPosition(cx-150, cy); mStatusText.setPosition(10, 10); mPlayerText.setPosition(10, h-80); mDebugText.setPosition(w-120, h-20); if (dialog_box) { int dw, dh; dialog_box->getSize(&dw, &dh); dialog_box->setPosition(cx - dw/2, cy - dh/2); } if (load_dialog_box) { int dw, dh; load_dialog_box->getSize(&dw, &dh); load_dialog_box->setPosition(cx - dw/2, cy - dh/2); } } void reGameGUI::Keyboard(unsigned char key, int x, int y, bool bKeyDown) { if (bKeyDown) puKeyboard(key, PU_DOWN); } void reGameGUI::KeyboardSpecial(int key, int x, int y, bool bKeyDown) { } void reGameGUI::MouseFunc(int button, int state, int x, int y) { puMouse(button, state, x, y); } void reGameGUI::MotionFunc(int x, int y) { puMouse(x, y); } void reGameGUI::PassiveMotionFunc(int x, int y) { puMouse(x, y); } void reGameGUI::ShowLoadLevel() { int i; // Tidy-up for (i = 0; i < miNumLevels; i++) { delete [] level_desc[i]; delete [] level_dir[i]; } miNumLevels = 0; // Get levels i = 0; TiXmlNode* pNode = reGetGameEngine()->GetXMLConfigNode(); pNode = pNode->FirstChild("Levels"); pNode = pNode->FirstChild("Level"); TiXmlNode* pElement = pNode->ToElement(); while (pElement && i < RE_MAX_LEVELS) { const char* psName = reGetXMLAttribute(pElement, "name", ""); const char* psDesc = reGetXMLAttribute(pElement, "desc", ""); const char* psFile = reGetXMLAttribute(pElement, "file", ""); printf("Level %s,%s,%s\n", psName, psDesc, psFile); level_desc[i] = new char[strlen(psDesc)+1]; strcpy(level_desc[i], psDesc); level_dir[i] = new char[strlen(psFile)+1]; strcpy(level_dir[i], psFile); pElement = pElement->NextSiblingElement(); i++; } miNumLevels = i; level_desc[miNumLevels+1] = NULL; level_dir[miNumLevels+1] = NULL; mk_load_level_dialog( level_desc, "Start", "Quit", start_cb, exit_cb); } void reGameGUI::ShowHelp() { help_cb(NULL); } void reGameGUI::SetTextOff() { SetTextOn(eNotifyText, false); SetTextOn(eStatusText, false); SetTextOn(ePlayerText, false); SetTextOn(eDebugText, false); } void reGameGUI::SetText(eGUIText eText, const char* sText, bool bOn) { reText* pText = NULL; switch (eText) { case eNotifyText: pText = &mNotifyText; break; case eStatusText: pText = &mStatusText; break; case ePlayerText: pText = &mPlayerText; break; case eDebugText: pText = &mDebugText; break; default: pText = NULL; break; } if (pText) { pText->SetLabel(sText); if (bOn) pText->reveal(); else pText->hide(); } } void reGameGUI::SetTextOn(eGUIText eText, bool bOn) { reText* pText = NULL; switch (eText) { case eNotifyText: pText = &mNotifyText; break; case eStatusText: pText = &mStatusText; break; case ePlayerText: pText = &mPlayerText; break; case eDebugText: pText = &mDebugText; break; default: pText = NULL; break; } if (pText) { if (bOn) pText->reveal(); else pText->hide(); } }