summaryrefslogtreecommitdiffstats
path: root/src/app/app.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/app/app.cpp')
-rw-r--r--src/app/app.cpp541
1 files changed, 463 insertions, 78 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(&currentEvent, 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;
+}