// ============================================================== // This file is part of Glest (www.glest.org) // // Copyright (C) 2001-2008 MartiƱo Figueroa // // You can redistribute this code and/or modify it under // the terms of the GNU General Public License as published // by the Free Software Foundation; either version 2 of the // License, or (at your option) any later version // ============================================================== #include "program.h" #include "sound.h" #include "renderer.h" #include "config.h" #include "game.h" #include "main_menu.h" #include "intro.h" #include "world.h" #include "main.h" #include "sound_renderer.h" #include "logger.h" #include "profiler.h" #include "core_data.h" #include "metrics.h" #include "network_manager.h" #include "menu_state_custom_game.h" #include "menu_state_join_game.h" #include "menu_state_scenario.h" #include "leak_dumper.h" using namespace Shared::Util; using namespace Shared::Graphics; using namespace Shared::Graphics::Gl; // ===================================================== // class Program // ===================================================== namespace Glest{ namespace Game{ const int Program::maxTimes= 10; Program *Program::singleton = NULL; const int SOUND_THREAD_UPDATE_MILLISECONDS = 25; bool Program::wantShutdownApplicationAfterGame = false; const char *ProgramState::MAIN_PROGRAM_RENDER_KEY = "MEGAGLEST.RENDER"; // ===================================================== // class Program::CrashProgramState // ===================================================== ProgramState::ProgramState(Program *program) { this->program= program; this->forceMouseRender = false; this->mouseX = 0; this->mouseY = 0; this->mouse2dAnim = 0; this->fps= 0; this->lastFps= 0; this->startX=0; this->startY=0; } void ProgramState::restoreToStartXY() { SDL_WarpMouseInWindow(this->program->getWindow()->getSDLWindow(), startX, startY); } void ProgramState::incrementFps() { fps++; } void ProgramState::tick() { lastFps= fps; fps= 0; } bool ProgramState::canRender(bool sleepIfCannotRender) { int maxFPSCap = Config::getInstance().getInt("RenderFPSCap","500"); int sleepMillis = Config::getInstance().getInt("RenderFPSCapSleepMillis","1"); //Renderer &renderer= Renderer::getInstance(); if(GlobalStaticFlags::getIsNonGraphicalModeEnabled() == true) { maxFPSCap = Config::getInstance().getInt("RenderFPSCapHeadless","250"); sleepMillis = Config::getInstance().getInt("RenderFPSCapHeadlessSleepMillis","1"); } if(lastFps > maxFPSCap) { if(sleepIfCannotRender == true) { sleep(sleepMillis); //if(SystemFlags::VERBOSE_MODE_ENABLED) printf("In [%s::%s Line: %d] sleeping because lastFps = %d, maxFPSCap = %d sleepMillis = %d\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__,lastFps,maxFPSCap,sleepMillis); } return false; } return true; } void ProgramState::render() { Renderer &renderer= Renderer::getInstance(); canRender(); incrementFps(); if(GlobalStaticFlags::getIsNonGraphicalModeEnabled() == false) { renderer.clearBuffers(); renderer.reset2d(); renderer.renderMessageBox(program->getMsgBox()); renderer.renderMouse2d(mouseX, mouseY, mouse2dAnim); renderer.swapBuffers(); } } void ProgramState::update() { mouse2dAnim = (mouse2dAnim +1) % Renderer::maxMouse2dAnim; } void ProgramState::mouseMove(int x, int y, const MouseState *mouseState) { mouseX = x; mouseY = y; program->getMsgBox()->mouseMove(x, y); } Program::ShowMessageProgramState::ShowMessageProgramState(Program *program, const char *msg) : ProgramState(program) { userWantsExit = false; msgBox.init("Ok"); if(msg) { fprintf(stderr, "%s\n", msg); msgBox.setText(msg); } else { msgBox.setText("Mega-Glest has crashed."); } mouse2dAnim = mouseY = mouseX = 0; this->msg = (msg ? msg : ""); } void Program::ShowMessageProgramState::render() { Renderer &renderer= Renderer::getInstance(); renderer.clearBuffers(); renderer.reset2d(); renderer.renderMessageBox(&msgBox); renderer.renderMouse2d(mouseX, mouseY, mouse2dAnim); renderer.swapBuffers(); } void Program::ShowMessageProgramState::mouseDownLeft(int x, int y) { int button= 0; if(msgBox.mouseClick(x,y,button)) { program->exit(); userWantsExit = true; } } void Program::ShowMessageProgramState::keyPress(SDL_KeyboardEvent c) { if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s %d] c = [%d]\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__,c.keysym.sym); // if user pressed return we exit //if(c == 13) { if(isKeyPressed(SDLK_RETURN,c) == true) { program->exit(); userWantsExit = true; } } void Program::ShowMessageProgramState::mouseMove(int x, int y, const MouseState &mouseState) { mouseX = x; mouseY = y; msgBox.mouseMove(x, y); } void Program::ShowMessageProgramState::update() { mouse2dAnim = (mouse2dAnim +1) % Renderer::maxMouse2dAnim; } // ===================== PUBLIC ======================== bool Program::rendererInitOk = false; bool Program::tryingRendererInit = false; Program::Program() { //this->masterserverMode = false; this->window = NULL; this->shutdownApplicationEnabled = false; this->skipRenderFrameCount = 0; this->messageBoxIsSystemError = false; this->programStateOldSystemError = NULL; this->programState= NULL; this->singleton = this; this->soundThreadManager = NULL; //mesage box Lang &lang= Lang::getInstance(); msgBox.init(lang.getString("Ok")); msgBox.setEnabled(false); } //bool Program::isMasterserverMode() const { // return this->masterserverMode; //} void Program::initNormal(WindowGl *window){ if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__); Config &config = Config::getInstance(); init(window); if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__); setState(new Intro(this)); showCursor(config.getBool("No2DMouseRendering","false")); if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__); } void Program::initSavedGame(WindowGl *window,bool masterserverMode, string saveGameFile) { init(window); MainMenu *mainMenu= new MainMenu(this); setState(mainMenu); if(saveGameFile == "") { Config &config = Config::getInstance(); saveGameFile = config.getString("LastSavedGame",""); if(saveGameFile == "") { saveGameFile = GameConstants::saveGameFileDefault; if(getGameReadWritePath(GameConstants::path_logs_CacheLookupKey) != "") { saveGameFile = getGameReadWritePath(GameConstants::path_logs_CacheLookupKey) + saveGameFile; } else { string userData = Config::getInstance().getString("UserData_Root",""); if(userData != "") { endPathWithSlash(userData); } saveGameFile = userData + saveGameFile; } } } //if(SystemFlags::VERBOSE_MODE_ENABLED) printf("Loading game from [%s]\n",saveGameFile.c_str()); printf("Loading saved game from [%s]\n",saveGameFile.c_str()); Game::loadGame(saveGameFile,this,masterserverMode); } void Program::initServer(WindowGl *window, bool autostart,bool openNetworkSlots, bool masterserverMode) { //this->masterserverMode = masterserverMode; init(window); MainMenu *mainMenu= new MainMenu(this); setState(mainMenu); mainMenu->setState(new MenuStateCustomGame(this, mainMenu, openNetworkSlots, pNewGame, autostart, NULL, masterserverMode)); } void Program::initServer(WindowGl *window, GameSettings *settings) { init(window); MainMenu *mainMenu= new MainMenu(this); setState(mainMenu); mainMenu->setState(new MenuStateCustomGame(this, mainMenu, false, pNewGame, true, settings)); } void Program::initClient(WindowGl *window, const Ip &serverIp, int portNumber) { init(window); MainMenu *mainMenu= new MainMenu(this); setState(mainMenu); mainMenu->setState(new MenuStateJoinGame(this, mainMenu, true, serverIp,portNumber)); } void Program::initClientAutoFindHost(WindowGl *window) { init(window); MainMenu *mainMenu= new MainMenu(this); setState(mainMenu); bool autoFindHost = true; mainMenu->setState(new MenuStateJoinGame(this, mainMenu, &autoFindHost)); } void Program::initScenario(WindowGl *window, string autoloadScenarioName) { init(window); MainMenu *mainMenu= new MainMenu(this); setState(mainMenu); mainMenu->setState(new MenuStateScenario(this, mainMenu, false, Config::getInstance().getPathListForType(ptScenarios),autoloadScenarioName)); } Program::~Program(){ if(SystemFlags::VERBOSE_MODE_ENABLED) printf("In [%s::%s Line: %d]\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__); delete programState; programState = NULL; if(SystemFlags::VERBOSE_MODE_ENABLED) printf("In [%s::%s Line: %d]\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__); Renderer::getInstance().end(); CoreData &coreData= CoreData::getInstance(); coreData.cleanup(); if(SystemFlags::VERBOSE_MODE_ENABLED) printf("In [%s::%s Line: %d]\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__); //restore video mode restoreDisplaySettings(); singleton = NULL; if(SystemFlags::VERBOSE_MODE_ENABLED) printf("In [%s::%s Line: %d]\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__); if(soundThreadManager != NULL) { BaseThread::shutdownAndWait(soundThreadManager); delete soundThreadManager; soundThreadManager = NULL; } if(SystemFlags::VERBOSE_MODE_ENABLED) printf("In [%s::%s Line: %d]\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__); } void Program::restoreStateFromSystemError() { messageBoxIsSystemError = false; if(this->programStateOldSystemError == NULL) { setState(new Intro(this)); } else { setState(this->programStateOldSystemError); } } bool Program::textInput(std::string text) { if(msgBox.getEnabled()) { return false; } //delegate event return programState->textInput(text); } bool Program::sdlKeyDown(SDL_KeyboardEvent key) { //delegate event return programState->sdlKeyDown(key); } void Program::keyDown(SDL_KeyboardEvent key) { if(msgBox.getEnabled()) { //SDL_keysym keystate = Window::getKeystate(); if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__); //if(key == vkEscape || key == SDLK_ESCAPE || // ((key == vkReturn || key == SDLK_RETURN || key == SDLK_KP_ENTER) && !(keystate.mod & (KMOD_LALT | KMOD_RALT)))) { if(isKeyPressed(SDLK_ESCAPE,key) == true || ((isKeyPressed(SDLK_RETURN,key) == true) && !(key.keysym.mod & (KMOD_LALT | KMOD_RALT)))) { if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__); //printf("---> keystate [%d]\n",keystate); msgBox.setEnabled(false); if(messageBoxIsSystemError == true) { restoreStateFromSystemError(); } } } //delegate event programState->keyDown(key); } void Program::keyUp(SDL_KeyboardEvent key) { programState->keyUp(key); } void Program::keyPress(SDL_KeyboardEvent c) { programState->keyPress(c); } void Program::mouseDownLeft(int x, int y) { if(msgBox.getEnabled()) { int button= 0; if(msgBox.mouseClick(x, y, button)) { //if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__); //close message box msgBox.setEnabled(false); if(messageBoxIsSystemError == true) { restoreStateFromSystemError(); } } } } void Program::eventMouseMove(int x, int y, const MouseState *ms) { if (msgBox.getEnabled()) { msgBox.mouseMove(x, y); } } void Program::simpleTask(BaseThread *callingThread,void *userdata) { loopWorker(); } void Program::loop() { loopWorker(); } void Program::loopWorker() { if(SystemFlags::getSystemSettingType(SystemFlags::debugPerformance).enabled) SystemFlags::OutputDebug(SystemFlags::debugPerformance,"In [%s::%s Line: %d] ================================= MAIN LOOP START ================================= \n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__); //Renderer &renderer= Renderer::getInstance(); if(GlobalStaticFlags::getIsNonGraphicalModeEnabled() == false && window) { MainWindow *mainWindow = dynamic_cast(window); if(mainWindow) { //mainWindow->render(); if(mainWindow->getTriggerLanguageToggle()) { mainWindow->toggleLanguage(mainWindow->getTriggerLanguage()); } } } Chrono chronoPerformanceCounts; bool showPerfStats = Config::getInstance().getBool("ShowPerfStats","false"); Chrono chronoPerf; char perfBuf[8096]=""; std::vector perfList; if(showPerfStats) chronoPerf.start(); Chrono chronoLoop; if(SystemFlags::getSystemSettingType(SystemFlags::debugPerformance).enabled) chronoLoop.start(); Chrono chrono; if(SystemFlags::getSystemSettingType(SystemFlags::debugPerformance).enabled) chrono.start(); //render assert(programState != NULL); if(this->programState->quitTriggered() == true) { if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__); Stats endStats = this->programState->quitAndToggleState(); if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__); Game::exitGameState(this, endStats); if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__); return; } ProgramState *prevState = this->programState; if(showPerfStats) { sprintf(perfBuf,"In [%s::%s] Line: %d took msecs: " MG_I64_SPECIFIER "\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__,chronoPerf.getMillis()); perfList.push_back(perfBuf); } assert(programState != NULL); chronoPerformanceCounts.start(); programState->render(); programState->addPerformanceCount(ProgramState::MAIN_PROGRAM_RENDER_KEY,chronoPerformanceCounts.getMillis()); if(showPerfStats) { sprintf(perfBuf,"In [%s::%s] Line: %d took msecs: " MG_I64_SPECIFIER "\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__,chronoPerf.getMillis()); perfList.push_back(perfBuf); } if(SystemFlags::getSystemSettingType(SystemFlags::debugPerformance).enabled && chrono.getMillis() > 0) SystemFlags::OutputDebug(SystemFlags::debugPerformance,"In [%s::%s] Line: %d programState->render took msecs: %lld ==============> MAIN LOOP RENDERING\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__,chrono.getMillis()); if(SystemFlags::getSystemSettingType(SystemFlags::debugPerformance).enabled && chrono.getMillis() > 0) chrono.start(); //update camera if(SystemFlags::getSystemSettingType(SystemFlags::debugPerformance).enabled) chrono.start(); chronoPerformanceCounts.start(); while(updateCameraTimer.isTime()) { programState->updateCamera(); } programState->addPerformanceCount("programState->updateCamera()",chronoPerformanceCounts.getMillis()); if(showPerfStats) { sprintf(perfBuf,"In [%s::%s] Line: %d took msecs: " MG_I64_SPECIFIER "\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__,chronoPerf.getMillis()); perfList.push_back(perfBuf); } if(SystemFlags::getSystemSettingType(SystemFlags::debugPerformance).enabled && chrono.getMillis() > 0) SystemFlags::OutputDebug(SystemFlags::debugPerformance,"In [%s::%s] Line: %d programState->render took msecs: %lld ==============> MAIN LOOP CAMERA UPDATING\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__,chrono.getMillis()); if(SystemFlags::getSystemSettingType(SystemFlags::debugPerformance).enabled && chrono.getMillis() > 0) chrono.start(); //update world if(SystemFlags::getSystemSettingType(SystemFlags::debugPerformance).enabled) chrono.start(); int updateCount = 0; while(prevState == this->programState && updateTimer.isTime()) { Chrono chronoUpdateLoop; if(SystemFlags::getSystemSettingType(SystemFlags::debugPerformance).enabled) chronoUpdateLoop.start(); if(showPerfStats) { sprintf(perfBuf,"In [%s::%s] Line: %d took msecs: " MG_I64_SPECIFIER " updateCount: %d\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__,chronoPerf.getMillis(),updateCount); perfList.push_back(perfBuf); } GraphicComponent::update(); programState->update(); if(SystemFlags::getSystemSettingType(SystemFlags::debugPerformance).enabled && chronoUpdateLoop.getMillis() > 0) SystemFlags::OutputDebug(SystemFlags::debugPerformance,"In [%s::%s Line: %d] programState->update took msecs: %lld, updateCount = %d\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__,chronoUpdateLoop.getMillis(),updateCount); if(SystemFlags::getSystemSettingType(SystemFlags::debugPerformance).enabled && chronoUpdateLoop.getMillis() > 0) chronoUpdateLoop.start(); if(showPerfStats) { sprintf(perfBuf,"In [%s::%s] Line: %d took msecs: " MG_I64_SPECIFIER " updateCount: %d\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__,chronoPerf.getMillis(),updateCount); perfList.push_back(perfBuf); } if(prevState == this->programState) { chronoPerformanceCounts.start(); if(soundThreadManager == NULL || soundThreadManager->isThreadExecutionLagging()) { if(soundThreadManager != NULL) { if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s %d] ERROR / WARNING soundThreadManager->isThreadExecutionLagging is TRUE\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__); SystemFlags::OutputDebug(SystemFlags::debugError,"In [%s::%s %d] ERROR / WARNING soundThreadManager->isThreadExecutionLagging is TRUE\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__); } SoundRenderer::getInstance().update(); if(SystemFlags::getSystemSettingType(SystemFlags::debugPerformance).enabled && chronoUpdateLoop.getMillis() > 0) SystemFlags::OutputDebug(SystemFlags::debugPerformance,"In [%s::%s Line: %d] SoundRenderer::getInstance().update() took msecs: %lld, updateCount = %d\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__,chronoUpdateLoop.getMillis(),updateCount); if(SystemFlags::getSystemSettingType(SystemFlags::debugPerformance).enabled && chronoUpdateLoop.getMillis() > 0) chronoUpdateLoop.start(); } programState->addPerformanceCount("SoundRenderer::getInstance().update()",chronoPerformanceCounts.getMillis()); if(showPerfStats) { sprintf(perfBuf,"In [%s::%s] Line: %d took msecs: " MG_I64_SPECIFIER " updateCount: %d\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__,chronoPerf.getMillis(),updateCount); perfList.push_back(perfBuf); } chronoPerformanceCounts.start(); NetworkManager::getInstance().update(); programState->addPerformanceCount("NetworkManager::getInstance().update()",chronoPerformanceCounts.getMillis()); if(SystemFlags::getSystemSettingType(SystemFlags::debugPerformance).enabled && chronoUpdateLoop.getMillis() > 0) SystemFlags::OutputDebug(SystemFlags::debugPerformance,"In [%s::%s Line: %d] NetworkManager::getInstance().update() took msecs: %lld, updateCount = %d\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__,chronoUpdateLoop.getMillis(),updateCount); if(SystemFlags::getSystemSettingType(SystemFlags::debugPerformance).enabled && chronoUpdateLoop.getMillis() > 0) chronoUpdateLoop.start(); if(showPerfStats) { sprintf(perfBuf,"In [%s::%s] Line: %d took msecs: " MG_I64_SPECIFIER " updateCount: %d\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__,chronoPerf.getMillis(),updateCount); perfList.push_back(perfBuf); } } updateCount++; } if(SystemFlags::getSystemSettingType(SystemFlags::debugPerformance).enabled && chrono.getMillis() > 0) SystemFlags::OutputDebug(SystemFlags::debugPerformance,"In [%s::%s] Line: %d AFTER programState->update took msecs: %lld ==============> MAIN LOOP BODY LOGIC, updateCount = %d\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__,chrono.getMillis(),updateCount); if(SystemFlags::getSystemSettingType(SystemFlags::debugPerformance).enabled && chrono.getMillis() > 0) chrono.start(); if(SystemFlags::getSystemSettingType(SystemFlags::debugPerformance).enabled && chrono.getMillis() > 0) chrono.start(); if(showPerfStats) { sprintf(perfBuf,"In [%s::%s] Line: %d took msecs: " MG_I64_SPECIFIER "\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__,chronoPerf.getMillis()); perfList.push_back(perfBuf); } if(prevState == this->programState) { //fps timer chronoPerformanceCounts.start(); chrono.start(); while(fpsTimer.isTime()) { programState->tick(); } programState->addPerformanceCount("programState->tick()",chronoPerformanceCounts.getMillis()); if(showPerfStats) { sprintf(perfBuf,"In [%s::%s] Line: %d took msecs: " MG_I64_SPECIFIER "\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__,chronoPerf.getMillis()); perfList.push_back(perfBuf); } if(SystemFlags::getSystemSettingType(SystemFlags::debugPerformance).enabled && chrono.getMillis() > 0) SystemFlags::OutputDebug(SystemFlags::debugPerformance,"In [%s::%s] Line: %d programState->render took msecs: %lld ==============> MAIN LOOP TICKING\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__,chrono.getMillis()); if(SystemFlags::getSystemSettingType(SystemFlags::debugPerformance).enabled && chrono.getMillis() > 0) chrono.start(); //if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled && chrono.getMillis() > 0) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s] Line: %d programState->render took msecs: %lld ==============> MAIN LOOP TICKING\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__,chrono.getMillis()); if(SystemFlags::getSystemSettingType(SystemFlags::debugPerformance).enabled && chrono.getMillis() > 0) chrono.start(); } if(showPerfStats && chronoPerf.getMillis() >= 100) { for(unsigned int x = 0; x < perfList.size(); ++x) { printf("%s",perfList[x].c_str()); } } if(SystemFlags::getSystemSettingType(SystemFlags::debugPerformance).enabled) SystemFlags::OutputDebug(SystemFlags::debugPerformance,"In [%s::%s Line: %d] ------------------------------- MAIN LOOP END, stats: loop took msecs: %lld -------------------------------\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__,chronoLoop.getMillis()); } void Program::resize(SizeState sizeState){ switch(sizeState){ case ssMinimized: //restoreVideoMode(); break; case ssMaximized: case ssRestored: //setDisplaySettings(); //renderer.reloadResources(); break; } } // ==================== misc ==================== void Program::renderProgramMsgBox() { Renderer &renderer= Renderer::getInstance(); if(msgBox.getEnabled()) { renderer.renderMessageBox(&msgBox); } if(GlobalStaticFlags::getIsNonGraphicalModeEnabled() == false && window) { MainWindow *mainWindow = dynamic_cast(window); if(mainWindow) { mainWindow->render(); } } } void Program::setState(ProgramState *programStateNew, bool cleanupOldState) { try { if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__); this->programStateOldSystemError = this->programState; bool msgBoxEnabled = msgBox.getEnabled(); if(dynamic_cast(programStateNew) != NULL) { if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__); int X = 0; int Y = 0; SDL_GetMouseState(&X,&Y); programStateNew->setStartXY(X,Y); Logger::getInstance().setProgress(0); Logger::getInstance().setState(""); SDL_PumpEvents(); showCursor(true); SDL_PumpEvents(); sleep(0); if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__); } if(cleanupOldState == true) { if(this->programState != programStateNew) { if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__); this->programStateOldSystemError = NULL; delete this->programState; if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__); this->programState = NULL; if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__); } } if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__); //mesage box Lang &lang= Lang::getInstance(); msgBox.init(lang.getString("Ok")); msgBox.setEnabled(msgBoxEnabled); fpsTimer.init(1, maxTimes); updateTimer.init(GameConstants::updateFps, maxTimes); updateCameraTimer.init(GameConstants::cameraFps, maxTimes); this->programState= programStateNew; assert(programStateNew != NULL); if(programStateNew == NULL) { throw megaglest_runtime_error("programStateNew == NULL"); } programStateNew->load(); if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__); programStateNew->init(); if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__); updateTimer.reset(); updateCameraTimer.reset(); fpsTimer.reset(); Config &config = Config::getInstance(); if(dynamic_cast(programStateNew) != NULL && msgBoxEnabled == true) { showCursor(true); } else { showCursor(config.getBool("No2DMouseRendering","false")); } this->programStateOldSystemError = NULL; if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__); } catch(megaglest_runtime_error& e) { //printf("3333333 ex.wantStackTrace() = %d\n",e.wantStackTrace()); char szBuf[8096]=""; snprintf(szBuf,8096,"In [%s::%s Line: %d]\nError [%s]\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__,e.what()); SystemFlags::OutputDebug(SystemFlags::debugError,szBuf); if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,szBuf); //abort(); //printf("44444444a ex.wantStackTrace() = %d\n",e.wantStackTrace()); messageBoxIsSystemError = true; string errorMsg = e.what(); if(GlobalStaticFlags::getIsNonGraphicalModeEnabled() == false) { if(dynamic_cast(programStateNew) != NULL) { try { Game *game = dynamic_cast(programStateNew); Renderer &renderer= Renderer::getInstance(); renderer.initGame(game,game->getGameCameraPtr()); } catch(megaglest_runtime_error& ex2) { errorMsg += "\n" + string(ex2.what()); } } } //printf("44444444b ex.wantStackTrace() = %d\n",e.wantStackTrace()); this->showMessage(errorMsg.c_str()); //setState(new Intro(this)); } catch(const exception &e){ char szBuf[8096]=""; snprintf(szBuf,8096,"In [%s::%s Line: %d]\nError [%s]\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__,e.what()); SystemFlags::OutputDebug(SystemFlags::debugError,szBuf); if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,szBuf); //abort(); messageBoxIsSystemError = true; if(GlobalStaticFlags::getIsNonGraphicalModeEnabled() == false) { if(dynamic_cast(programStateNew) != NULL) { Game *game = dynamic_cast(programStateNew); Renderer &renderer= Renderer::getInstance(); renderer.initGame(game,game->getGameCameraPtr()); } } this->showMessage(e.what()); //setState(new Intro(this)); } } void Program::exit() { window->destroy(); } // ==================== PRIVATE ==================== void Program::initResolution() { const Metrics &metrics = Metrics::getInstance(); if(window->getScreenWidth() != metrics.getScreenW() || window->getScreenHeight() != metrics.getScreenH()) { int oldW = metrics.getScreenW(); int oldH = metrics.getScreenH(); Config &config= Config::getInstance(); config.setInt("ScreenWidth",window->getScreenWidth(),true); config.setInt("ScreenHeight",window->getScreenHeight(),true); metrics.reload(window->getScreenWidth(), window->getScreenHeight()); printf("MainWindow forced change of resolution to desktop values (%d x %d) instead of (%d x %d)\n",metrics.getScreenW(), metrics.getScreenH(),oldW,oldH); } } void Program::init(WindowGl *window, bool initSound, bool toggleFullScreen){ if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__); this->window= window; Config &config= Config::getInstance(); if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__); //set video mode if(toggleFullScreen == false) { setDisplaySettings(); } if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__); //window //window->setText("MegaGlest"); window->setStyle(config.getBool("Windowed")? wsWindowedFixed: wsFullscreen); window->setPos(0, 0); window->setSize(config.getInt("ScreenWidth"), config.getInt("ScreenHeight")); window->create(); if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__); //timers fpsTimer.init(1, maxTimes); updateTimer.init(GameConstants::updateFps, maxTimes); updateCameraTimer.init(GameConstants::cameraFps, maxTimes); if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__); //log start Logger &logger= Logger::getInstance(); string logFile = "glest.log"; if(getGameReadWritePath(GameConstants::path_logs_CacheLookupKey) != "") { logFile = getGameReadWritePath(GameConstants::path_logs_CacheLookupKey) + logFile; } else { string userData = config.getString("UserData_Root",""); if(userData != "") { endPathWithSlash(userData); } logFile = userData + logFile; } logger.setFile(logFile); logger.clear(); if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__); //lang //Lang &lang= Lang::getInstance(); Lang::getInstance(); if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__); //render Renderer &renderer= Renderer::getInstance(); if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__); window->initGl(config.getInt("ColorBits"), config.getInt("DepthBits"), config.getInt("StencilBits"), config.getBool("HardwareAcceleration","false"), config.getBool("FullScreenAntiAliasing","false"), config.getFloat("GammaValue","0.0")); window->setText(config.getString("WindowTitle","MegaGlest")); if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__); window->makeCurrentGl(); initResolution(); if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__); //coreData, needs renderer, but must load before renderer init CoreData &coreData= CoreData::getInstance(); coreData.load(); if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__); //init renderer (load global textures) tryingRendererInit = true; renderer.init(); tryingRendererInit = false; rendererInitOk = true; if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__); //sound if(initSound == true && toggleFullScreen == false) { SoundRenderer &soundRenderer= SoundRenderer::getInstance(); bool initOk = soundRenderer.init(window); if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d] initOk = %d\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__,initOk); // Test sound system failed //initOk = false; // END if(initOk == false) { string sError = "Sound System could not be initialized!"; this->showMessage(sError.c_str()); } // Run sound streaming in a background thread if enabled if(SoundRenderer::getInstance().runningThreaded() == true) { if(BaseThread::shutdownAndWait(soundThreadManager) == true) { delete soundThreadManager; } static string mutexOwnerId = string(extractFileFromDirectoryPath(__FILE__).c_str()) + string("_") + intToStr(__LINE__); soundThreadManager = new SimpleTaskThread(&SoundRenderer::getInstance(),0,SOUND_THREAD_UPDATE_MILLISECONDS); soundThreadManager->setUniqueID(mutexOwnerId); soundThreadManager->start(); } } NetworkInterface::setAllowGameDataSynchCheck(Config::getInstance().getBool("AllowGameDataSynchCheck","false")); NetworkInterface::setAllowDownloadDataSynch(Config::getInstance().getBool("AllowDownloadDataSynch","false")); if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__); } void Program::reloadUI() { if(programState) { programState->reloadUI(); } } void Program::setDisplaySettings(){ Config &config= Config::getInstance(); if(!config.getBool("Windowed")) { //int freq= config.getInt("RefreshFrequency"); int colorBits= config.getInt("ColorBits"); int screenWidth= config.getInt("ScreenWidth"); int screenHeight= config.getInt("ScreenHeight"); if(config.getBool("AutoMaxFullScreen","false") == true) { getFullscreenVideoInfo(colorBits,screenWidth,screenHeight,!config.getBool("Windowed")); config.setInt("ColorBits",colorBits); config.setInt("ScreenWidth",screenWidth); config.setInt("ScreenHeight",screenHeight); } } changeVideoModeFullScreen(!config.getBool("Windowed")); } void Program::restoreDisplaySettings(){ Config &config= Config::getInstance(); if(!config.getBool("Windowed")){ restoreVideoMode(this->getWindow()->getSDLWindow()); } } bool Program::isMessageShowing() { return msgBox.getEnabled(); } void Program::showMessage(const char *msg) { if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s %d] msg [%s]\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__,msg); msgBox.setText(msg); msgBox.setEnabled(true); if(GlobalStaticFlags::getIsNonGraphicalModeEnabled() == true) { printf("Message:\n%s\n",msg); if(messageBoxIsSystemError == true) { messageBoxIsSystemError = false; //setState(new Intro(this)); initServer(window,false,true,true); } } } void Program::stopSoundSystem() { if(soundThreadManager != NULL) { BaseThread::shutdownAndWait(soundThreadManager); delete soundThreadManager; soundThreadManager = NULL; } } void Program::startSoundSystem() { stopSoundSystem(); if(SoundRenderer::getInstance().runningThreaded() == true) { static string mutexOwnerId = string(extractFileFromDirectoryPath(__FILE__).c_str()) + string("_") + intToStr(__LINE__); soundThreadManager = new SimpleTaskThread(&SoundRenderer::getInstance(),0,SOUND_THREAD_UPDATE_MILLISECONDS); soundThreadManager->setUniqueID(mutexOwnerId); soundThreadManager->start(); } } void Program::resetSoundSystem() { startSoundSystem(); } void Program::reInitGl() { if(window != NULL) { Config &config= Config::getInstance(); window->initGl(config.getInt("ColorBits"), config.getInt("DepthBits"), config.getInt("StencilBits"), config.getBool("HardwareAcceleration","false"), config.getBool("FullScreenAntiAliasing","false"), config.getFloat("GammaValue","0.0")); window->setText(config.getString("WindowTitle","MegaGlest")); initResolution(); } } void Program::consoleAddLine(string line) { if(programState != NULL) { programState->consoleAddLine(line); } } SimpleTaskThread * Program::getSoundThreadManager(bool takeOwnership) { SimpleTaskThread *result = soundThreadManager; if(takeOwnership) { soundThreadManager = NULL; } return result; } }}//end namespace