/* * This file is part of the Colobot: Gold Edition source code * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * See the GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see http://gnu.org/licenses */ /** * \file app/app.h * \brief CApplication class */ #pragma once #include "common/event.h" #include "common/language.h" #include "common/singleton.h" #include "graphics/core/device.h" #include "level/level_category.h" #include #include #include class CEventQueue; class CController; class CSoundInterface; class CInput; class CPathManager; class CConfigFile; class CSystemUtils; struct SystemTimeStamp; namespace Gfx { class CEngine; struct DeviceConfig; } /** * \struct JoystickDevice * \brief Information about a joystick device */ struct JoystickDevice { //! Device index (-1 = invalid device) int index; //! Device name std::string name; //! Number of axes (only available after joystick opened) int axisCount; //! Number of buttons (only available after joystick opened) int buttonCount; JoystickDevice() : index(-1), axisCount(0), buttonCount(0) {} }; /** * \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 }; /** * \enum MouseMode * \brief Mode of mouse cursor */ enum MouseMode { MOUSE_SYSTEM, //! < system cursor visible; in-game cursor hidden MOUSE_ENGINE, //! < in-game cursor visible; system cursor hidden MOUSE_BOTH, //! < both cursors visible (only for debug) MOUSE_NONE, //! < no cursor visible }; enum DebugMode { DEBUG_SYS_EVENTS = 1 << 0, DEBUG_UPDATE_EVENTS = 1 << 1, DEBUG_APP_EVENTS = 1 << 2, DEBUG_EVENTS = DEBUG_SYS_EVENTS | DEBUG_UPDATE_EVENTS | DEBUG_APP_EVENTS, DEBUG_MODELS = 1 << 3, DEBUG_ALL = DEBUG_SYS_EVENTS | DEBUG_APP_EVENTS | DEBUG_MODELS }; struct ApplicationPrivate; /** * \class CApplication * \brief Main application * * This class is responsible for main application execution, including creating * and handling main application window, receiving events, etc. * * It is a singleton class with only one instance that can be created. * * \section Creation Creation of other main objects * * The class creates the only instance of CEventQueue, CEngine, * CRobotMain and CSoundInterface classes. * * \section Window Window management * * The class is responsible for creating app window, setting and changing the video mode, * joystick management, grabbing input and changing the system mouse cursor * position and visibility. * ("System mouse cursor" means the cursor displayed by the OS in constrast to the cursor * displayed by CEngine). * * \section Events Events * * Events are taken from SDL event queue, translated to common events from src/common.h * and pushed to global event queue CEventQueue. * * Joystick events are generated somewhat differently, by running a separate timer, * polling the device for changes and synthesising events on change. It avoids flooding * the event queue with too many joystick events and the granularity of the timer can be * adjusted. * * The events are passed to ProcessEvent() of classes in this order: CApplication, CEngine * and CRobotMain. CApplication and CEngine's ProcessEvent() functions return bool, which * means whether to pass the event on, or stop the chain. This is to enable handling some * events which are internal to CApplication or CEngine. * * \section Portability Portability * * Currently, the class only handles OpenGL devices. SDL can be used with DirectX, but * for that to work, video initialization and video setting must be done differently. * */ class CApplication : public CSingleton { public: //! Constructor (can only be called once!) CApplication(CSystemUtils* systemUtils); //! Destructor ~CApplication(); //! Returns the application's event queue CEventQueue* GetEventQueue(); //! Returns the sound subsystem CSoundInterface* GetSound(); public: //! Loads some data from environment variables void LoadEnvironmentVariables(); //! Parses commandline arguments (they take priority) ParseArgsStatus ParseArguments(int argc, char *argv[]); //! Initializes the application bool Create(); //! Main event loop int Run(); //! Returns the code to be returned at main() exit int GetExitCode() const; //! Returns the message of error (set to something if exit code is not 0) const std::string& GetErrorMessage() const; //! Returns a list of possible video modes void GetVideoResolutionList(std::vector &resolutions, int display = 0) const; //! Returns the current video mode Gfx::DeviceConfig GetVideoConfig() const; //! Change the video mode to given mode bool ChangeVideoConfig(const Gfx::DeviceConfig &newConfig); //! Suspends animation (time will not be updated) void SuspendSimulation(); //! Resumes animation void ResumeSimulation(); //! Returns whether simulation is suspended bool GetSimulationSuspended() const; //! Resets time counters to account for time spent loading game void ResetTimeAfterLoading(); //@{ //! Management of simulation speed void SetSimulationSpeed(float speed); float GetSimulationSpeed() const; //@} //! Returns the absolute time counter [seconds] float GetAbsTime() const; //! Returns the exact absolute time counter [nanoseconds] long long GetExactAbsTime() const; //! Returns the exact absolute time counter disregarding speed setting [nanoseconds] long long GetRealAbsTime() const; //! Returns the relative time since last update [seconds] float GetRelTime() const; //! Returns the exact realative time since last update [nanoseconds] long long GetExactRelTime() const; //! Returns the exact relative time since last update disregarding speed setting [nanoseconds] long long GetRealRelTime() const; //! Returns a list of available joystick devices std::vector GetJoystickList() const; //! Returns info about the current joystick JoystickDevice GetJoystick() const; //! Change the current joystick device bool ChangeJoystick(const JoystickDevice &newJoystick); //! Management of joystick enable state //@{ void SetJoystickEnabled(bool enable); bool GetJoystickEnabled() const; //@} //! Polls the state of joystick axes and buttons void UpdateJoystick(); //! Updates the mouse position explicitly void UpdateMouse(); //! Management of mouse mode //@{ void SetMouseMode(MouseMode mode); MouseMode GetMouseMode() const; //@} //! Enable/disable text input, this toggles the on-screen keyboard on some platforms /** This also allows for writing in CJK languages (not tested!), see https://wiki.libsdl.org/Tutorials/TextInput for detailed explanation */ void SetTextInput(bool textInputEnabled, int id); //! Moves (warps) the mouse cursor to the specified position (in interface coords) void MoveMouse(Math::Point pos); //! Management of debug modes (printing more info in logger) //@{ void SetDebugModeActive(DebugMode mode, bool active); bool IsDebugModeActive(DebugMode mode) const; static bool ParseDebugModes(const std::string& str, int& debugModes); //@} //! Management of language //@{ Language GetLanguage() const; char GetLanguageChar() const; void SetLanguage(Language language); //@} bool GetSceneTestMode(); //! Renders the image in window void Render(); //! Renders the image in window if needed void RenderIfNeeded(int updateRate); //! Starts a force feedback effect on the joystick void PlayForceFeedbackEffect(float strength = 1.0f, int length = 999999); //! Stops a force feedback effect on the joystick void StopForceFeedbackEffect(); protected: //! Creates the window's SDL_Surface bool CreateVideoSurface(); //! Processes the captured SDL event to Event struct Event ProcessSystemEvent(); //! If applicable, creates a virtual event to match the changed state as of new event Event CreateVirtualEvent(const Event& sourceEvent); //! Prepares a simulation update event TEST_VIRTUAL Event CreateUpdateEvent(); //! Logs debug data for event void LogEvent(const Event& event); //! Opens the joystick device bool OpenJoystick(); //! Closes the joystick device void CloseJoystick(); //! Internal procedure to reset time counters void InternalResumeSimulation(); protected: //! System utils instance CSystemUtils* m_systemUtils; //! Private (SDL-dependent data) std::unique_ptr m_private; //! Global event queue std::unique_ptr m_eventQueue; //! Graphics engine std::unique_ptr m_engine; //! Graphics device std::unique_ptr m_device; //! Sound subsystem std::unique_ptr m_sound; //! Game controller - game engine and UI std::unique_ptr m_controller; //! Profile (INI) reader/writer std::unique_ptr m_configFile; //! Input manager std::unique_ptr m_input; //! Path manager std::unique_ptr m_pathManager; //! Code to return at exit int m_exitCode; //! Whether application window is active bool m_active; //! Bit array of active debug modes long m_debugModes; //! Message to be displayed as error to the user std::string m_errorMessage; //! Current configuration of OpenGL display device Gfx::DeviceConfig m_deviceConfig; //! Text set as window title std::string m_windowTitle; //! Animation time stamps, etc. //@{ SystemTimeStamp* m_baseTimeStamp; SystemTimeStamp* m_lastTimeStamp; SystemTimeStamp* m_curTimeStamp; 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; //@} SystemTimeStamp* m_manualFrameLast; SystemTimeStamp* m_manualFrameTime; //! Graphics device to use bool m_graphicsOverride = false; std::string m_graphics = "default"; //! OpenGL version to use bool m_glVersionOverride = false; int m_glMajor = -1; int m_glMinor = -1; //! OpenGL profile bool m_glProfileOverride = false; int m_glProfile = 0; //! Current mode of mouse MouseMode m_mouseMode; //! Info about current joystick device JoystickDevice m_joystick; //! Whether joystick is enabled bool m_joystickEnabled; //! Current state of joystick axes; may be updated from another thread std::vector m_joyAxeState; //! Current state of joystick buttons; may be updated from another thread std::vector m_joyButtonState; //@{ //! Scene to run on startup LevelCategory m_runSceneCategory; int m_runSceneRank; //@} //! Scene test mode bool m_sceneTest; //! Application language Language m_language; //! Screen resoultion overriden by commandline bool m_resolutionOverride; //! Headles mode bool m_headless; //! Static buffer for putenv locale static char m_languageLocale[50]; std::map m_textInputEnabled; };