diff options
author | Piotr Dziwinski <piotrdz@gmail.com> | 2012-09-19 22:53:06 +0200 |
---|---|---|
committer | Piotr Dziwinski <piotrdz@gmail.com> | 2012-09-19 22:53:06 +0200 |
commit | 7479f486b671acb2a6aea2c84a56b383aaba00ca (patch) | |
tree | 4043545a14234dfaa2d7d08d59c7ee9ee97f0de9 /src/app | |
parent | 901f10b2bac18a2063cd21798f22b3917e8519b5 (diff) | |
parent | 57d33d79ea570773d84ad81d4a61f50e079979ef (diff) | |
download | colobot-7479f486b671acb2a6aea2c84a56b383aaba00ca.tar.gz colobot-7479f486b671acb2a6aea2c84a56b383aaba00ca.tar.bz2 colobot-7479f486b671acb2a6aea2c84a56b383aaba00ca.zip |
Forgotten fix in dev-graphics
Diffstat (limited to 'src/app')
-rw-r--r-- | src/app/app.cpp | 541 | ||||
-rw-r--r-- | src/app/app.h | 171 | ||||
-rw-r--r-- | src/app/main.cpp | 7 | ||||
-rw-r--r-- | src/app/system_windows.h | 8 |
4 files changed, 612 insertions, 115 deletions
diff --git a/src/app/app.cpp b/src/app/app.cpp index 00cd13d..23e6d9f 100644 --- a/src/app/app.cpp +++ b/src/app/app.cpp @@ -23,16 +23,24 @@ #include "common/logger.h" #include "common/iman.h" #include "common/image.h" +#include "common/key.h" #include "graphics/opengl/gldevice.h" +#include "object/robotmain.h" #include <SDL/SDL.h> #include <SDL/SDL_image.h> -#include <stdio.h> +#include <fstream> +#include <stdlib.h> +#include <libintl.h> -template<> CApplication* CSingleton<CApplication>::mInstance = NULL; + +template<> CApplication* CSingleton<CApplication>::mInstance = nullptr; + +//! Static buffer for putenv locale +static char S_LANGUAGE[50] = { 0 }; //! Interval of timer called to update joystick state @@ -62,8 +70,8 @@ struct ApplicationPrivate ApplicationPrivate() { memset(¤tEvent, 0, sizeof(SDL_Event)); - surface = NULL; - joystick = NULL; + surface = nullptr; + joystick = nullptr; joystickTimer = 0; } }; @@ -76,14 +84,10 @@ CApplication::CApplication() m_iMan = new CInstanceManager(); m_eventQueue = new CEventQueue(m_iMan); - m_engine = NULL; - m_device = NULL; - m_robotMain = NULL; - m_sound = NULL; - - m_keyState = 0; - m_axeKey = Math::Vector(0.0f, 0.0f, 0.0f); - m_axeJoy = Math::Vector(0.0f, 0.0f, 0.0f); + m_engine = nullptr; + m_device = nullptr; + m_robotMain = nullptr; + m_sound = nullptr; m_exitCode = 0; m_active = false; @@ -91,29 +95,57 @@ CApplication::CApplication() m_windowTitle = "COLOBOT"; + m_simulationSuspended = false; + + m_simulationSpeed = 1.0f; + + m_realAbsTimeBase = 0LL; + m_realAbsTime = 0LL; + m_realRelTime = 0LL; + + m_absTimeBase = 0LL; + m_exactAbsTime = 0LL; + m_exactRelTime = 0LL; + + m_absTime = 0.0f; + m_relTime = 0.0f; + + m_baseTimeStamp = CreateTimeStamp(); + m_curTimeStamp = CreateTimeStamp(); + m_lastTimeStamp = CreateTimeStamp(); + m_joystickEnabled = false; + m_kmodState = 0; + m_mouseButtonsState = 0; + m_trackedKeys = 0; + m_dataPath = "./data"; - ResetKey(); + m_language = LANG_ENGLISH; } CApplication::~CApplication() { delete m_private; - m_private = NULL; + m_private = nullptr; delete m_eventQueue; - m_eventQueue = NULL; + m_eventQueue = nullptr; delete m_iMan; - m_iMan = NULL; + m_iMan = nullptr; + + DestroyTimeStamp(m_baseTimeStamp); + DestroyTimeStamp(m_curTimeStamp); + DestroyTimeStamp(m_lastTimeStamp); } -bool CApplication::ParseArguments(int argc, char *argv[]) +ParseArgsStatus CApplication::ParseArguments(int argc, char *argv[]) { bool waitDataDir = false; bool waitLogLevel = false; + bool waitLanguage = false; for (int i = 1; i < argc; ++i) { @@ -123,6 +155,7 @@ bool CApplication::ParseArguments(int argc, char *argv[]) { waitDataDir = false; m_dataPath = arg; + GetLogger()->Info("Using custom data dir: '%s'\n", m_dataPath.c_str()); continue; } @@ -142,7 +175,23 @@ bool CApplication::ParseArguments(int argc, char *argv[]) else if (arg == "none") GetLogger()->SetLogLevel(LOG_NONE); else - return false; + return PARSE_ARGS_FAIL; + continue; + } + + if (waitLanguage) + { + waitLanguage = false; + if (arg == "en") + m_language = LANG_ENGLISH; + else if (arg == "de") + m_language = LANG_GERMAN; + else if (arg == "fr") + m_language = LANG_FRENCH; + else if (arg == "pl") + m_language = LANG_POLISH; + else + return PARSE_ARGS_FAIL; continue; } @@ -158,34 +207,95 @@ bool CApplication::ParseArguments(int argc, char *argv[]) { waitDataDir = true; } + else if (arg == "-language") + { + waitLanguage = true; + } + else if (arg == "-help") + { + GetLogger()->Message("\n"); + GetLogger()->Message("COLOBOT GOLD pre-alpha\n"); + GetLogger()->Message("\n"); + GetLogger()->Message("List of available options:\n"); + GetLogger()->Message(" -help this help\n"); + GetLogger()->Message(" -datadir path set custom data directory path\n"); + GetLogger()->Message(" -debug enable debug mode (more info printed in logs)\n"); + GetLogger()->Message(" -loglevel level set log level to level (one of: trace, debug, info, warn, error, none)\n"); + GetLogger()->Message(" -language lang set language (one of: en, de, fr, pl)\n"); + return PARSE_ARGS_HELP; + } else { m_exitCode = 1; - return false; + return PARSE_ARGS_FAIL; } } // Args not given? - if (waitDataDir || waitLogLevel) - return false; + if (waitDataDir || waitLogLevel || waitLanguage) + return PARSE_ARGS_FAIL; - return true; + return PARSE_ARGS_OK; } bool CApplication::Create() { GetLogger()->Info("Creating CApplication\n"); - // TODO: verify that data directory exists + // I know, a primitive way to check for dir, but works + std::string readmePath = m_dataPath + "/README.txt"; + std::ifstream testReadme; + testReadme.open(readmePath.c_str(), std::ios_base::in); + if (!testReadme.good()) + { + GetLogger()->Error("Could not open test file in data dir: '%s'\n", readmePath.c_str()); + m_errorMessage = std::string("Could not read from data directory:\n") + + std::string("'") + m_dataPath + std::string("'\n") + + std::string("Please check your installation, or supply a valid data directory by -datadir option."); + m_exitCode = 1; + return false; + } + + /* Gettext initialization */ + + std::string locale = "C"; + switch (m_language) + { + case LANG_ENGLISH: + locale = "en_US.utf8"; + break; + + case LANG_GERMAN: + locale = "de_DE.utf8"; + break; + + case LANG_FRENCH: + locale = "fr_FR.utf8"; + break; + + case LANG_POLISH: + locale = "pl_PL.utf8"; + break; + } + + std::string langStr = "LANGUAGE="; + langStr += locale; + strcpy(S_LANGUAGE, langStr.c_str()); + putenv(S_LANGUAGE); + setlocale(LC_ALL, locale.c_str()); + + std::string trPath = m_dataPath + std::string("/i18n"); + bindtextdomain("colobot", trPath.c_str()); + bind_textdomain_codeset("colobot", "UTF-8"); + textdomain("colobot"); + + GetLogger()->Debug("Testing gettext translation: '%s'\n", gettext("Colobot rules!")); // Temporarily -- only in windowed mode m_deviceConfig.fullScreen = false; -/* // Create the sound instance. - m_sound = new CSound(m_iMan); - - // Create the robot application. - m_robotMain = new CRobotMain(m_iMan); */ + // Create the sound instance. + m_sound = new CSoundInterface(); std::string standardInfoMessage = @@ -218,7 +328,7 @@ bool CApplication::Create() if (! CreateVideoSurface()) return false; // dialog is in function - if (m_private->surface == NULL) + if (m_private->surface == nullptr) { m_errorMessage = std::string("SDL error while setting video mode:\n") + std::string(SDL_GetError()); @@ -261,6 +371,11 @@ bool CApplication::Create() return false; } + // Create the robot application. + m_robotMain = new CRobotMain(m_iMan, this); + + m_robotMain->ChangePhase(PHASE_WELCOME1); + GetLogger()->Info("CApplication created successfully\n"); return true; @@ -269,7 +384,7 @@ bool CApplication::Create() bool CApplication::CreateVideoSurface() { const SDL_VideoInfo *videoInfo = SDL_GetVideoInfo(); - if (videoInfo == NULL) + if (videoInfo == nullptr) { m_errorMessage = std::string("SDL error while getting video info:\n ") + std::string(SDL_GetError()); @@ -321,44 +436,46 @@ bool CApplication::CreateVideoSurface() void CApplication::Destroy() { - /*if (m_robotMain != NULL) + m_joystickEnabled = false; + + if (m_robotMain != nullptr) { delete m_robotMain; - m_robotMain = NULL; + m_robotMain = nullptr; } - if (m_sound != NULL) + if (m_sound != nullptr) { delete m_sound; - m_sound = NULL; - }*/ + m_sound = nullptr; + } - if (m_engine != NULL) + if (m_engine != nullptr) { m_engine->Destroy(); delete m_engine; - m_engine = NULL; + m_engine = nullptr; } - if (m_device != NULL) + if (m_device != nullptr) { m_device->Destroy(); delete m_device; - m_device = NULL; + m_device = nullptr; } - if (m_private->joystick != NULL) + if (m_private->joystick != nullptr) { SDL_JoystickClose(m_private->joystick); - m_private->joystick = NULL; + m_private->joystick = nullptr; } - if (m_private->surface != NULL) + if (m_private->surface != nullptr) { SDL_FreeSurface(m_private->surface); - m_private->surface = NULL; + m_private->surface = nullptr; } IMG_Quit(); @@ -383,7 +500,7 @@ bool CApplication::ChangeVideoConfig(const Gfx::GLDeviceConfig &newConfig) return false; } - if (m_private->surface == NULL) + if (m_private->surface == nullptr) { if (! restore) { @@ -426,7 +543,7 @@ bool CApplication::OpenJoystick() return false; m_private->joystick = SDL_JoystickOpen(m_joystick.index); - if (m_private->joystick == NULL) + if (m_private->joystick == nullptr) return false; m_joystick.axisCount = SDL_JoystickNumAxes(m_private->joystick); @@ -437,7 +554,7 @@ bool CApplication::OpenJoystick() m_joyButtonState = std::vector<bool>(m_joystick.buttonCount, false); // Create a timer for polling joystick state - m_private->joystickTimer = SDL_AddTimer(JOYSTICK_TIMER_INTERVAL, JoystickTimerCallback, NULL); + m_private->joystickTimer = SDL_AddTimer(JOYSTICK_TIMER_INTERVAL, JoystickTimerCallback, nullptr); return true; } @@ -447,7 +564,7 @@ void CApplication::CloseJoystick() // Timer will remove itself automatically SDL_JoystickClose(m_private->joystick); - m_private->joystick = NULL; + m_private->joystick = nullptr; } bool CApplication::ChangeJoystick(const JoystickDevice &newJoystick) @@ -455,7 +572,7 @@ bool CApplication::ChangeJoystick(const JoystickDevice &newJoystick) if ( (newJoystick.index < 0) || (newJoystick.index >= SDL_NumJoysticks()) ) return false; - if (m_private->joystick != NULL) + if (m_private->joystick != nullptr) CloseJoystick(); return OpenJoystick(); @@ -464,7 +581,7 @@ bool CApplication::ChangeJoystick(const JoystickDevice &newJoystick) Uint32 JoystickTimerCallback(Uint32 interval, void *) { CApplication *app = CApplication::GetInstancePointer(); - if ((app == NULL) || (! app->GetJoystickEnabled())) + if ((app == nullptr) || (! app->GetJoystickEnabled())) return 0; // don't run the timer again app->UpdateJoystick(); @@ -540,6 +657,10 @@ int CApplication::Run() { m_active = true; + GetCurrentTimeStamp(m_baseTimeStamp); + GetCurrentTimeStamp(m_lastTimeStamp); + GetCurrentTimeStamp(m_curTimeStamp); + while (true) { // To be sure no old event remains @@ -577,12 +698,24 @@ int CApplication::Run() { bool passOn = ProcessEvent(event); - if (m_engine != NULL && passOn) + if (m_engine != nullptr && passOn) passOn = m_engine->ProcessEvent(event); if (passOn) m_eventQueue->AddEvent(event); } + + Event virtualEvent = CreateVirtualEvent(event); + if (virtualEvent.type != EVENT_NULL) + { + bool passOn = ProcessEvent(virtualEvent); + + if (m_engine != nullptr && passOn) + passOn = m_engine->ProcessEvent(virtualEvent); + + if (passOn) + m_eventQueue->AddEvent(virtualEvent); + } } } @@ -602,12 +735,12 @@ int CApplication::Run() { passOn = ProcessEvent(event); - if (passOn && m_engine != NULL) + if (passOn && m_engine != nullptr) passOn = m_engine->ProcessEvent(event); } - /*if (passOn && m_robotMain != NULL) - m_robotMain->ProcessEvent(event); */ + if (passOn && m_robotMain != nullptr) + m_robotMain->EventProcess(event); } /* Update mouse position explicitly right before rendering @@ -616,6 +749,9 @@ int CApplication::Run() // Update game and render a frame during idle time (no messages are waiting) Render(); + + // Update simulation state + StepSimulation(); } } @@ -664,6 +800,7 @@ Event CApplication::ParseEvent() else event.type = EVENT_KEY_UP; + event.key.virt = false; event.key.key = m_private->currentEvent.key.keysym.sym; event.key.mod = m_private->currentEvent.key.keysym.mod; event.key.state = TranslatePressState(m_private->currentEvent.key.state); @@ -672,15 +809,32 @@ Event CApplication::ParseEvent() else if ( (m_private->currentEvent.type == SDL_MOUSEBUTTONDOWN) || (m_private->currentEvent.type == SDL_MOUSEBUTTONUP) ) { - if (m_private->currentEvent.type == SDL_MOUSEBUTTONDOWN) - event.type = EVENT_MOUSE_BUTTON_DOWN; + if ((m_private->currentEvent.button.button == SDL_BUTTON_WHEELUP) || + (m_private->currentEvent.button.button == SDL_BUTTON_WHEELDOWN)) + { + if (m_private->currentEvent.type == SDL_MOUSEBUTTONDOWN) // ignore the following up event + { + event.type = EVENT_MOUSE_WHEEL; + if (m_private->currentEvent.button.button == SDL_BUTTON_WHEELDOWN) + event.mouseWheel.dir = WHEEL_DOWN; + else + event.mouseWheel.dir = WHEEL_UP; + event.mouseWheel.pos = m_engine->WindowToInterfaceCoords( + Math::IntPoint(m_private->currentEvent.button.x, m_private->currentEvent.button.y)); + } + } else - event.type = EVENT_MOUSE_BUTTON_UP; + { + if (m_private->currentEvent.type == SDL_MOUSEBUTTONDOWN) + event.type = EVENT_MOUSE_BUTTON_DOWN; + else + event.type = EVENT_MOUSE_BUTTON_UP; - event.mouseButton.button = m_private->currentEvent.button.button; - event.mouseButton.state = TranslatePressState(m_private->currentEvent.button.state); - event.mouseButton.pos = m_engine->WindowToInterfaceCoords( - Math::IntPoint(m_private->currentEvent.button.x, m_private->currentEvent.button.y)); + event.mouseButton.button = m_private->currentEvent.button.button; + event.mouseButton.state = TranslatePressState(m_private->currentEvent.button.state); + event.mouseButton.pos = m_engine->WindowToInterfaceCoords( + Math::IntPoint(m_private->currentEvent.button.x, m_private->currentEvent.button.y)); + } } else if (m_private->currentEvent.type == SDL_MOUSEMOTION) { @@ -725,18 +879,93 @@ Event CApplication::ParseEvent() return event; } -/** Processes incoming events. It is the first function called after an event is captures. - Function returns \c true if the event is to be passed on to other processing functions - or \c false if not. */ -bool CApplication::ProcessEvent(const Event &event) +/** + * Processes incoming events. It is the first function called after an event is captured. + * Event is modified, updating its tracked keys state and mouse position to current values. + * Function returns \c true if the event is to be passed on to other processing functions + * or \c false if not. */ +bool CApplication::ProcessEvent(Event &event) { CLogger *l = GetLogger(); + event.trackedKeys = m_trackedKeys; + if (GetSystemMouseVisibile()) + event.mousePos = m_systemMousePos; + else + event.mousePos = m_engine->GetMousePos(); + if (event.type == EVENT_ACTIVE) { - m_active = event.active.gain; if (m_debugMode) - l->Info("Focus change: active = %s\n", m_active ? "true" : "false"); + l->Info("Focus change: active = %s\n", event.active.gain ? "true" : "false"); + + /*if (m_active != event.active.gain) + { + m_active = event.active.gain; + + if (m_active) + ResumeSimulation(); + else + SuspendSimulation(); + }*/ + } + else if (event.type == EVENT_KEY_DOWN) + { + m_kmodState = event.key.mod; + + if ((m_kmodState & KEY_MOD(SHIFT)) != 0) + m_trackedKeys |= TRKEY_SHIFT; + else if ((m_kmodState & KEY_MOD(CTRL)) != 0) + m_trackedKeys |= TRKEY_CONTROL; + else if (event.key.key == KEY(KP8)) + m_trackedKeys |= TRKEY_NUM_UP; + else if (event.key.key == KEY(KP2)) + m_trackedKeys |= TRKEY_NUM_DOWN; + else if (event.key.key == KEY(KP4)) + m_trackedKeys |= TRKEY_NUM_LEFT; + else if (event.key.key == KEY(KP6)) + m_trackedKeys |= TRKEY_NUM_RIGHT; + else if (event.key.key == KEY(KP_PLUS)) + m_trackedKeys |= TRKEY_NUM_PLUS; + else if (event.key.key == KEY(KP_MINUS)) + m_trackedKeys |= TRKEY_NUM_MINUS; + else if (event.key.key == KEY(PAGEUP)) + m_trackedKeys |= TRKEY_PAGE_UP; + else if (event.key.key == KEY(PAGEDOWN)) + m_trackedKeys |= TRKEY_PAGE_DOWN; + } + else if (event.type == EVENT_KEY_UP) + { + m_kmodState = event.key.mod; + + if ((m_kmodState & KEY_MOD(SHIFT)) != 0) + m_trackedKeys &= ~TRKEY_SHIFT; + else if ((m_kmodState & KEY_MOD(CTRL)) != 0) + m_trackedKeys &= ~TRKEY_CONTROL; + else if (event.key.key == KEY(KP8)) + m_trackedKeys &= ~TRKEY_NUM_UP; + else if (event.key.key == KEY(KP2)) + m_trackedKeys &= ~TRKEY_NUM_DOWN; + else if (event.key.key == KEY(KP4)) + m_trackedKeys &= ~TRKEY_NUM_LEFT; + else if (event.key.key == KEY(KP6)) + m_trackedKeys &= ~TRKEY_NUM_RIGHT; + else if (event.key.key == KEY(KP_PLUS)) + m_trackedKeys &= ~TRKEY_NUM_PLUS; + else if (event.key.key == KEY(KP_MINUS)) + m_trackedKeys &= ~TRKEY_NUM_MINUS; + else if (event.key.key == KEY(PAGEUP)) + m_trackedKeys &= ~TRKEY_PAGE_UP; + else if (event.key.key == KEY(PAGEDOWN)) + m_trackedKeys &= ~TRKEY_PAGE_DOWN; + } + else if (event.type == EVENT_MOUSE_BUTTON_DOWN) + { + m_mouseButtonsState |= 1 << event.mouseButton.button; + } + else if (event.type == EVENT_MOUSE_BUTTON_UP) + { + m_mouseButtonsState &= ~(1 << event.mouseButton.button); } // Print the events in debug mode to test the code @@ -747,6 +976,7 @@ bool CApplication::ProcessEvent(const Event &event) case EVENT_KEY_DOWN: case EVENT_KEY_UP: l->Info("EVENT_KEY_%s:\n", (event.type == EVENT_KEY_DOWN) ? "DOWN" : "UP"); + l->Info(" virt = %s\n", (event.key.virt) ? "true" : "false"); l->Info(" key = %4x\n", event.key.key); l->Info(" state = %s\n", (event.key.state == STATE_PRESSED) ? "STATE_PRESSED" : "STATE_RELEASED"); l->Info(" mod = %4x\n", event.key.mod); @@ -764,6 +994,11 @@ bool CApplication::ProcessEvent(const Event &event) l->Info(" state = %s\n", (event.mouseButton.state == STATE_PRESSED) ? "STATE_PRESSED" : "STATE_RELEASED"); l->Info(" pos = (%f, %f)\n", event.mouseButton.pos.x, event.mouseButton.pos.y); break; + case EVENT_MOUSE_WHEEL: + l->Info("EVENT_MOUSE_WHEEL:\n"); + l->Info(" dir = %s\n", (event.mouseWheel.dir == WHEEL_DOWN) ? "WHEEL_DOWN" : "WHEEL_UP"); + l->Info(" pos = (%f, %f)\n", event.mouseWheel.pos.x, event.mouseWheel.pos.y); + break; case EVENT_JOY_AXIS: l->Info("EVENT_JOY_AXIS:\n"); l->Info(" axis = %d\n", event.joyAxis.axis); @@ -789,6 +1024,48 @@ bool CApplication::ProcessEvent(const Event &event) return true; } + +Event CApplication::CreateVirtualEvent(const Event& sourceEvent) +{ + Event virtualEvent; + virtualEvent.systemEvent = true; + + if ((sourceEvent.type == EVENT_KEY_DOWN) || (sourceEvent.type == EVENT_KEY_UP)) + { + virtualEvent.type = sourceEvent.type; + virtualEvent.key = sourceEvent.key; + virtualEvent.key.virt = true; + + if (sourceEvent.key.key == KEY(LCTRL) || sourceEvent.key.key == KEY(RCTRL)) + virtualEvent.key.key = VIRTUAL_KMOD(CTRL); + else if (sourceEvent.key.key == KEY(LSHIFT) || sourceEvent.key.key == KEY(RSHIFT)) + virtualEvent.key.key = VIRTUAL_KMOD(SHIFT); + else if (sourceEvent.key.key == KEY(LALT) || sourceEvent.key.key == KEY(RALT)) + virtualEvent.key.key = VIRTUAL_KMOD(ALT); + else if (sourceEvent.key.key == KEY(LMETA) || sourceEvent.key.key == KEY(RMETA)) + virtualEvent.key.key = VIRTUAL_KMOD(META); + else + virtualEvent.type = EVENT_NULL; + } + else if ((sourceEvent.type == EVENT_JOY_BUTTON_DOWN) || (sourceEvent.type == EVENT_JOY_BUTTON_UP)) + { + if (sourceEvent.type == EVENT_JOY_BUTTON_DOWN) + virtualEvent.type = EVENT_KEY_DOWN; + else + virtualEvent.type = EVENT_KEY_UP; + virtualEvent.key.virt = true; + virtualEvent.key.key = VIRTUAL_JOY(sourceEvent.joyButton.button); + virtualEvent.key.mod = 0; + virtualEvent.key.unicode = 0; + } + else + { + virtualEvent.type = EVENT_NULL; + } + + return virtualEvent; +} + /** Renders the frame and swaps buffers as necessary */ void CApplication::Render() { @@ -798,9 +1075,101 @@ void CApplication::Render() SDL_GL_SwapBuffers(); } -void CApplication::StepSimulation(float rTime) +void CApplication::SuspendSimulation() { - // TODO + m_simulationSuspended = true; + GetLogger()->Info("Suspend simulation\n"); +} + +void CApplication::ResumeSimulation() +{ + m_simulationSuspended = false; + + GetCurrentTimeStamp(m_baseTimeStamp); + CopyTimeStamp(m_curTimeStamp, m_baseTimeStamp); + m_realAbsTimeBase = m_realAbsTime; + m_absTimeBase = m_exactAbsTime; + + GetLogger()->Info("Resume simulation\n"); +} + +bool CApplication::GetSimulationSuspended() +{ + return m_simulationSuspended; +} + +void CApplication::SetSimulationSpeed(float speed) +{ + m_simulationSpeed = speed; + + GetCurrentTimeStamp(m_baseTimeStamp); + m_realAbsTimeBase = m_realAbsTime; + m_absTimeBase = m_exactAbsTime; + + GetLogger()->Info("Simulation speed = %.2f\n", speed); +} + +void CApplication::StepSimulation() +{ + if (m_simulationSuspended) + return; + + CopyTimeStamp(m_lastTimeStamp, m_curTimeStamp); + GetCurrentTimeStamp(m_curTimeStamp); + + long long absDiff = TimeStampExactDiff(m_baseTimeStamp, m_curTimeStamp); + m_realAbsTime = m_realAbsTimeBase + absDiff; + // m_baseTimeStamp is updated on simulation speed change, so this is OK + m_exactAbsTime = m_absTimeBase + m_simulationSpeed * absDiff; + m_absTime = (m_absTimeBase + m_simulationSpeed * absDiff) / 1e9f; + + m_realRelTime = TimeStampExactDiff(m_lastTimeStamp, m_curTimeStamp); + m_exactRelTime = m_simulationSpeed * m_realRelTime; + m_relTime = (m_simulationSpeed * m_realRelTime) / 1e9f; + + + m_engine->FrameUpdate(); + m_sound->FrameMove(m_relTime); + + + Event frameEvent(EVENT_FRAME); + frameEvent.rTime = m_relTime; + m_eventQueue->AddEvent(frameEvent); +} + +float CApplication::GetSimulationSpeed() +{ + return m_simulationSpeed; +} + +float CApplication::GetAbsTime() +{ + return m_absTime; +} + +long long CApplication::GetExactAbsTime() +{ + return m_exactAbsTime; +} + +long long CApplication::GetRealAbsTime() +{ + return m_realAbsTime; +} + +float CApplication::GetRelTime() +{ + return m_relTime; +} + +long long CApplication::GetExactRelTime() +{ + return m_exactRelTime; +} + +long long CApplication::GetRealRelTime() +{ + return m_realRelTime; } Gfx::GLDeviceConfig CApplication::GetVideoConfig() @@ -814,7 +1183,7 @@ VideoQueryResult CApplication::GetVideoResolutionList(std::vector<Math::IntPoint resolutions.clear(); const SDL_VideoInfo *videoInfo = SDL_GetVideoInfo(); - if (videoInfo == NULL) + if (videoInfo == nullptr) return VIDEO_QUERY_ERROR; Uint32 videoFlags = SDL_OPENGL | SDL_GL_DOUBLEBUFFER | SDL_HWPALETTE; @@ -861,25 +1230,31 @@ bool CApplication::GetDebugMode() return m_debugMode; } -void CApplication::FlushPressKey() +int CApplication::GetKmods() { - // TODO + return m_kmodState; } -void CApplication::ResetKey() +bool CApplication::GetKmodState(int kmod) { - // TODO + return (m_kmodState & kmod) != 0; } -void CApplication::SetKey(int keyRank, int option, int key) +bool CApplication::GetTrackedKeyState(TrackedKey key) { - // TODO + return (m_trackedKeys & key) != 0; } -int CApplication::GetKey(int keyRank, int option) +bool CApplication::GetMouseButtonState(int index) { - // TODO - return 0; + return (m_mouseButtonsState & (1<<index)) != 0; +} + +void CApplication::ResetKeyStates() +{ + m_trackedKeys = 0; + m_kmodState = 0; + m_robotMain->ResetKeyStates(); } void CApplication::SetGrabInput(bool grab) @@ -964,3 +1339,13 @@ std::string CApplication::GetDataFilePath(const std::string& dirName, const std: { return m_dataPath + "/" + dirName + "/" + fileName; } + +Language CApplication::GetLanguage() +{ + return m_language; +} + +void CApplication::SetLanguage(Language language) +{ + m_language = language; +} diff --git a/src/app/app.h b/src/app/app.h index 7991177..33be5a5 100644 --- a/src/app/app.h +++ b/src/app/app.h @@ -22,8 +22,7 @@ #pragma once - -#include "common/misc.h" +#include "common/global.h" #include "common/singleton.h" #include "graphics/core/device.h" #include "graphics/engine/engine.h" @@ -36,11 +35,12 @@ class CInstanceManager; class CEvent; class CRobotMain; -class CSound; +class CSoundInterface; /** - \struct JoystickDevice - \brief Information about a joystick device */ + * \struct JoystickDevice + * \brief Information about a joystick device + */ struct JoystickDevice { //! Device index (-1 = invalid device) @@ -57,8 +57,9 @@ struct JoystickDevice }; /** - \enum VideoQueryResult - \brief Result of querying for available video resolutions */ + * \enum VideoQueryResult + * \brief Result of querying for available video resolutions + */ enum VideoQueryResult { VIDEO_QUERY_ERROR, @@ -68,6 +69,35 @@ enum VideoQueryResult }; +/** + * \enum TrackedKeys + * \brief Keys (or kmods) whose state (pressed/released) is tracked by CApplication + */ +enum TrackedKey +{ + TRKEY_SHIFT = (1<<0), + TRKEY_CONTROL = (1<<1), + TRKEY_NUM_UP = (1<<2), + TRKEY_NUM_DOWN = (1<<3), + TRKEY_NUM_LEFT = (1<<4), + TRKEY_NUM_RIGHT = (1<<5), + TRKEY_NUM_PLUS = (1<<6), + TRKEY_NUM_MINUS = (1<<7), + TRKEY_PAGE_UP = (1<<8), + TRKEY_PAGE_DOWN = (1<<9) +}; + +/** + * \enum ParseArgsStatus + * \brief State of parsing commandline arguments + */ +enum ParseArgsStatus +{ + PARSE_ARGS_OK = 1, //! < all ok + PARSE_ARGS_FAIL = 2, //! < invalid syntax + PARSE_ARGS_HELP = 3 //! < -help requested +}; + struct ApplicationPrivate; /** @@ -82,7 +112,7 @@ struct ApplicationPrivate; * \section Creation Creation of other main objects * * The class creates the only instance of CInstanceManager, CEventQueue, CEngine, - * CRobotMain and CSound classes. + * CRobotMain and CSoundInterface classes. * * \section Window Window management * @@ -123,7 +153,7 @@ public: public: //! Parses commandline arguments - bool ParseArguments(int argc, char *argv[]); + ParseArgsStatus ParseArguments(int argc, char *argv[]); //! Initializes the application bool Create(); //! Main event loop @@ -147,8 +177,37 @@ public: //! Change the video mode to given mode bool ChangeVideoConfig(const Gfx::GLDeviceConfig &newConfig); + //! Suspends animation (time will not be updated) + void SuspendSimulation(); + //! Resumes animation + void ResumeSimulation(); + //! Returns whether simulation is suspended + bool GetSimulationSuspended(); + //! Updates the simulation state - void StepSimulation(float rTime); + void StepSimulation(); + + //@{ + //! Management of simulation speed + void SetSimulationSpeed(float speed); + float GetSimulationSpeed(); + //@} + + //! Returns the absolute time counter [seconds] + float GetAbsTime(); + //! Returns the exact absolute time counter [nanoseconds] + long long GetExactAbsTime(); + + //! Returns the exact absolute time counter disregarding speed setting [nanoseconds] + long long GetRealAbsTime(); + + //! Returns the relative time since last update [seconds] + float GetRelTime(); + //! Returns the exact realative time since last update [nanoseconds] + long long GetExactRelTime(); + + //! Returns the exact relative time since last update disregarding speed setting [nanoseconds] + long long GetRealRelTime(); //! Returns a list of available joystick devices std::vector<JoystickDevice> GetJoystickList(); @@ -159,10 +218,11 @@ public: //! Change the current joystick device bool ChangeJoystick(const JoystickDevice &newJoystick); - //! Enables/disables joystick + //! Management of joystick enable state + //@{ void SetJoystickEnabled(bool enable); - //! Returns whether joystick is enabled bool GetJoystickEnabled(); + //@} //! Polls the state of joystick axes and buttons void UpdateJoystick(); @@ -170,42 +230,63 @@ public: //! Updates the mouse position explicitly void UpdateMouse(); - void FlushPressKey(); - void ResetKey(); - void SetKey(int keyRank, int option, int key); - int GetKey(int keyRank, int option); + //! Returns the current key modifiers + int GetKmods(); + //! Returns whether the given kmod is active + bool GetKmodState(int kmod); + + //! Returns whether the tracked key is pressed + bool GetTrackedKeyState(TrackedKey key); - //! Sets the grab mode for input (keyboard & mouse) + //! Returns whether the mouse button is pressed + bool GetMouseButtonState(int index); + + //! Resets tracked key states and modifiers + void ResetKeyStates(); + + //! Management of the grab mode for input (keyboard & mouse) + //@{ void SetGrabInput(bool grab); - //! Returns the grab mode bool GetGrabInput(); + //@} - //! Sets the visiblity of system mouse cursor + //! Management of the visiblity of system mouse cursor + //@{ void SetSystemMouseVisible(bool visible); - //! Returns the visiblity of system mouse cursor bool GetSystemMouseVisibile(); + //@} - //! Sets the position of system mouse cursor (in interface coords) + //! Management of the position of system mouse cursor (in interface coords) + //@{ void SetSystemMousePos(Math::Point pos); - //! Returns the position of system mouse cursor (in interface coords) Math::Point GetSystemMousePos(); + //@} - //! Enables/disables debug mode (prints more info in logger) + //! Management of debug mode (prints more info in logger) + //@{ void SetDebugMode(bool mode); - //! Returns whether debug mode is enabled bool GetDebugMode(); + //@} //! Returns the full path to a file in data directory std::string GetDataFilePath(const std::string &dirName, const std::string &fileName); + //! Management of language + //@{ + Language GetLanguage(); + void SetLanguage(Language language); + //@} + protected: //! Creates the window's SDL_Surface bool CreateVideoSurface(); //! Processes the captured SDL event to Event struct Event ParseEvent(); + //! If applicable, creates a virtual event to match the changed state as of new event + Event CreateVirtualEvent(const Event& sourceEvent); //! Handles some incoming events - bool ProcessEvent(const Event &event); + bool ProcessEvent(Event &event); //! Renders the image in window void Render(); @@ -226,7 +307,7 @@ protected: //! Graphics device Gfx::CDevice* m_device; //! Sound subsystem - CSound* m_sound; + CSoundInterface* m_sound; //! Main class of the proper game engine CRobotMain* m_robotMain; @@ -248,13 +329,36 @@ protected: //! Text set as window title std::string m_windowTitle; - int m_keyState; - Math::Vector m_axeKey; - Math::Vector m_axeJoy; - Math::Point m_systemMousePos; - long m_mouseWheel; + //! Animation time stamps, etc. + //@{ + SystemTimeStamp* m_baseTimeStamp; + SystemTimeStamp* m_lastTimeStamp; + SystemTimeStamp* m_curTimeStamp; - long m_key[50][2]; + long long m_realAbsTimeBase; + long long m_realAbsTime; + long long m_realRelTime; + + long long m_absTimeBase; + long long m_exactAbsTime; + long long m_exactRelTime; + + float m_absTime; + float m_relTime; + + float m_simulationSpeed; + bool m_simulationSuspended; + //@} + + //! Current state of key modifiers (mask of SDLMod) + unsigned int m_kmodState; + //! Current state of some tracked keys (mask of TrackedKey) + unsigned int m_trackedKeys; + //! Current state of mouse buttons (mask of button indexes) + unsigned int m_mouseButtonsState; + + //! Current system mouse position + Math::Point m_systemMousePos; //! Info about current joystick device JoystickDevice m_joystick; @@ -267,5 +371,8 @@ protected: //! Path to directory with data files std::string m_dataPath; + + //! Application language + Language m_language; }; diff --git a/src/app/main.cpp b/src/app/main.cpp index 0d885f7..084ca30 100644 --- a/src/app/main.cpp +++ b/src/app/main.cpp @@ -78,11 +78,16 @@ int main(int argc, char *argv[]) CApplication app; // single instance of the application - if (! app.ParseArguments(argc, argv)) + ParseArgsStatus status = app.ParseArguments(argc, argv); + if (status == PARSE_ARGS_FAIL) { SystemDialog(SDT_ERROR, "COLOBOT - Fatal Error", "Invalid commandline arguments!\n"); return app.GetExitCode(); } + else if (status == PARSE_ARGS_HELP) + { + return app.GetExitCode(); + } int code = 0; diff --git a/src/app/system_windows.h b/src/app/system_windows.h index 72d9f88..c9743e6 100644 --- a/src/app/system_windows.h +++ b/src/app/system_windows.h @@ -48,18 +48,18 @@ struct SystemTimeStamp // Convert a wide Unicode string to an UTF8 string std::string UTF8_Encode_Windows(const std::wstring &wstr) { - int size_needed = WideCharToMultiByte(CP_UTF8, 0, &wstr[0], (int)wstr.size(), NULL, 0, NULL, NULL); + int size_needed = WideCharToMultiByte(CP_UTF8, 0, &wstr[0], static_cast<int>(wstr.size()), NULL, 0, NULL, NULL); std::string strTo(size_needed, 0); - WideCharToMultiByte(CP_UTF8, 0, &wstr[0], (int)wstr.size(), &strTo[0], size_needed, NULL, NULL); + WideCharToMultiByte(CP_UTF8, 0, &wstr[0], static_cast<int>(wstr.size()), &strTo[0], size_needed, NULL, NULL); return strTo; } // Convert an UTF8 string to a wide Unicode String std::wstring UTF8_Decode_Windows(const std::string &str) { - int size_needed = MultiByteToWideChar(CP_UTF8, 0, &str[0], (int)str.size(), NULL, 0); + int size_needed = MultiByteToWideChar(CP_UTF8, 0, &str[0], static_cast<int>(str.size()), NULL, 0); std::wstring wstrTo(size_needed, 0); - MultiByteToWideChar(CP_UTF8, 0, &str[0], (int)str.size(), &wstrTo[0], size_needed); + MultiByteToWideChar(CP_UTF8, 0, &str[0], static_cast<int>(str.size()), &wstrTo[0], size_needed); return wstrTo; } |