MegaGlest/source/glest_game/main/program.cpp

999 lines
39 KiB
C++

// ==============================================================
// 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.registerGraphicComponent("ShowMessageProgramState", "msgBox");
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() : msgBox("Program", "msgBox") {
//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.registerGraphicComponent("Program", "msgBox");
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<MainWindow *>(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<string> 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<MainWindow *>(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<Game *>(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<Intro *>(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<Game *>(programStateNew) != NULL) {
try {
Game *game = dynamic_cast<Game *>(programStateNew);
Renderer &renderer= Renderer::getInstance();
game->setQuitPendingIndicator();// by this the world is no more updated
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<Game *>(programStateNew) != NULL) {
Game *game = dynamic_cast<Game *>(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