| @@ -101,7 +101,7 @@ liblol_core_sources = \ | |||||
| \ | \ | ||||
| audio/audio.cpp audio/sample.cpp \ | audio/audio.cpp audio/sample.cpp \ | ||||
| \ | \ | ||||
| ui/input.cpp ui/input.h ui/input_internal.h ui/keys.inc \ | |||||
| ui/input.cpp ui/input.h ui/keys.inc \ | |||||
| ui/controller.cpp ui/controller.h \ | ui/controller.cpp ui/controller.h \ | ||||
| ui/gui.cpp ui/gui.h \ | ui/gui.cpp ui/gui.h \ | ||||
| \ | \ | ||||
| @@ -28,7 +28,7 @@ extern "C" { | |||||
| } | } | ||||
| #include "application/android-app.h" | #include "application/android-app.h" | ||||
| #include "ui/input_internal.h" | |||||
| #include "ui/input.h" | |||||
| using namespace lol; | using namespace lol; | ||||
| @@ -84,7 +84,7 @@ public: | |||||
| /* FIXME: we need proper unproject or at least screen space events!! */ | /* FIXME: we need proper unproject or at least screen space events!! */ | ||||
| ivec2 m_wanted_resolution; | ivec2 m_wanted_resolution; | ||||
| InputDeviceInternal* m_mouse; | |||||
| InputDevice* m_mouse; | |||||
| SavedState m_state; | SavedState m_state; | ||||
| @@ -344,7 +344,7 @@ lol::AndroidApp::AndroidApp(char const *title, ivec2 res, float fps) | |||||
| Ticker::Setup(fps); | Ticker::Setup(fps); | ||||
| m_data->m_wanted_resolution = res; | m_data->m_wanted_resolution = res; | ||||
| m_data->m_mouse = InputDeviceInternal::CreateStandardMouse(); | |||||
| m_data->m_mouse = InputDevice::CreateStandardMouse(); | |||||
| } | } | ||||
| void lol::AndroidApp::ShowPointer(bool show) | void lol::AndroidApp::ShowPointer(bool show) | ||||
| @@ -291,7 +291,6 @@ | |||||
| <ClInclude Include="ui\d3d9-input.h" /> | <ClInclude Include="ui\d3d9-input.h" /> | ||||
| <ClInclude Include="ui\gui.h" /> | <ClInclude Include="ui\gui.h" /> | ||||
| <ClInclude Include="ui\input.h" /> | <ClInclude Include="ui\input.h" /> | ||||
| <ClInclude Include="ui\input_internal.h" /> | |||||
| <ClInclude Include="ui\keys.inc" /> | <ClInclude Include="ui\keys.inc" /> | ||||
| <ClInclude Include="ui\sdl-input.h"> | <ClInclude Include="ui\sdl-input.h"> | ||||
| <ExcludedFromBuild Condition="'$(enable_sdl)'=='no'">true</ExcludedFromBuild> | <ExcludedFromBuild Condition="'$(enable_sdl)'=='no'">true</ExcludedFromBuild> | ||||
| @@ -683,9 +683,6 @@ | |||||
| <ClInclude Include="ui\controller.h"> | <ClInclude Include="ui\controller.h"> | ||||
| <Filter>ui</Filter> | <Filter>ui</Filter> | ||||
| </ClInclude> | </ClInclude> | ||||
| <ClInclude Include="ui\input_internal.h"> | |||||
| <Filter>ui</Filter> | |||||
| </ClInclude> | |||||
| <ClInclude Include="utils.h"> | <ClInclude Include="utils.h"> | ||||
| <Filter>...</Filter> | <Filter>...</Filter> | ||||
| </ClInclude> | </ClInclude> | ||||
| @@ -21,7 +21,7 @@ | |||||
| #include <lol/engine-internal.h> | #include <lol/engine-internal.h> | ||||
| #include "ui/d3d9-input.h" | #include "ui/d3d9-input.h" | ||||
| #include "ui/input_internal.h" | |||||
| #include "ui/input.h" | |||||
| namespace lol | namespace lol | ||||
| { | { | ||||
| @@ -57,7 +57,7 @@ class D3d9InputData | |||||
| private: | private: | ||||
| #if defined LOL_USE_XINPUT | #if defined LOL_USE_XINPUT | ||||
| array<int, InputDeviceInternal*> m_joysticks; | |||||
| array<int, InputDevice*> m_joysticks; | |||||
| #endif // LOL_USE_XINPUT | #endif // LOL_USE_XINPUT | ||||
| }; | }; | ||||
| @@ -75,7 +75,7 @@ D3d9Input::D3d9Input() | |||||
| if (XInputGetState(i, &state) != ERROR_SUCCESS) | if (XInputGetState(i, &state) != ERROR_SUCCESS) | ||||
| continue; | continue; | ||||
| // TODO: we can put more friendly name here, such as LeftAxisX, ButtonX... | // TODO: we can put more friendly name here, such as LeftAxisX, ButtonX... | ||||
| InputDeviceInternal* stick = new InputDeviceInternal(g_name_joystick(i + 1)); | |||||
| InputDevice* stick = new InputDevice(g_name_joystick(i + 1)); | |||||
| stick->AddAxis(g_name_xbox_axis_left_x.c_str()); | stick->AddAxis(g_name_xbox_axis_left_x.c_str()); | ||||
| stick->AddAxis(g_name_xbox_axis_left_y.c_str()); | stick->AddAxis(g_name_xbox_axis_left_y.c_str()); | ||||
| @@ -15,12 +15,20 @@ | |||||
| #include <string> | #include <string> | ||||
| #include <map> | #include <map> | ||||
| #include <memory> | |||||
| #include "ui/input_internal.h" | |||||
| #include "ui/input.h" | |||||
| namespace lol | namespace lol | ||||
| { | { | ||||
| std::shared_ptr<input> input::get() | |||||
| { | |||||
| static auto instance = new input(); | |||||
| static auto shared_instance = std::shared_ptr<input>(instance); | |||||
| return shared_instance; | |||||
| } | |||||
| // Lookup tables for scancode and key name lookups | // Lookup tables for scancode and key name lookups | ||||
| static std::vector<input::key> g_all_keys | static std::vector<input::key> g_all_keys | ||||
| { | { | ||||
| @@ -47,8 +55,9 @@ std::vector<input::key> const &input::all_keys() | |||||
| std::string const &input::key_to_name(input::key k) | std::string const &input::key_to_name(input::key k) | ||||
| { | { | ||||
| static std::string unknown("Unknown"); | |||||
| auto it = g_key_to_name.find(k); | auto it = g_key_to_name.find(k); | ||||
| return it == g_key_to_name.end() ? "Unknown" : it->second; | |||||
| return it == g_key_to_name.end() ? unknown : it->second; | |||||
| } | } | ||||
| input::key input::name_to_key(std::string const &name) | input::key input::name_to_key(std::string const &name) | ||||
| @@ -58,8 +67,6 @@ input::key input::name_to_key(std::string const &name) | |||||
| } | } | ||||
| array<InputDevice*> InputDevice::devices; | array<InputDevice*> InputDevice::devices; | ||||
| int InputDevice::joystick_count = 0; | |||||
| bool InputDevice::m_capturemouse; | |||||
| array<std::string> InputDevice::GetAvailableDevices() | array<std::string> InputDevice::GetAvailableDevices() | ||||
| { | { | ||||
| @@ -86,7 +93,7 @@ void InputDevice::SetTextInputActive(bool status) | |||||
| m_input_active = status; | m_input_active = status; | ||||
| } | } | ||||
| void InputDeviceInternal::AddKey(int index, const char* name) | |||||
| void InputDevice::AddKey(int index, const char* name) | |||||
| { | { | ||||
| if (index == -1) | if (index == -1) | ||||
| index = (int)m_key_names.size(); | index = (int)m_key_names.size(); | ||||
| @@ -100,7 +107,7 @@ void InputDeviceInternal::AddKey(int index, const char* name) | |||||
| m_key_names[index] = name; | m_key_names[index] = name; | ||||
| } | } | ||||
| void InputDeviceInternal::AddAxis(int index, const char* name, float sensitivity) | |||||
| void InputDevice::AddAxis(int index, const char* name, float sensitivity) | |||||
| { | { | ||||
| if (index == -1) | if (index == -1) | ||||
| index = (int)m_axis_names.size(); | index = (int)m_axis_names.size(); | ||||
| @@ -116,7 +123,7 @@ void InputDeviceInternal::AddAxis(int index, const char* name, float sensitivity | |||||
| m_axis[index].m2 = sensitivity; | m_axis[index].m2 = sensitivity; | ||||
| } | } | ||||
| void InputDeviceInternal::AddCursor(int index, const char* name) | |||||
| void InputDevice::AddCursor(int index, const char* name) | |||||
| { | { | ||||
| if (index == -1) | if (index == -1) | ||||
| index = (int)m_cursor_names.size(); | index = (int)m_cursor_names.size(); | ||||
| @@ -130,9 +137,9 @@ void InputDeviceInternal::AddCursor(int index, const char* name) | |||||
| m_cursor_names[index] = name; | m_cursor_names[index] = name; | ||||
| } | } | ||||
| InputDeviceInternal* InputDeviceInternal::CreateStandardKeyboard() | |||||
| InputDevice* InputDevice::CreateStandardKeyboard() | |||||
| { | { | ||||
| InputDeviceInternal* keyboard = new InputDeviceInternal(g_name_keyboard.c_str()); | |||||
| InputDevice* keyboard = new InputDevice(g_name_keyboard.c_str()); | |||||
| /* Register all scancodes known to SDL (from the USB standard) */ | /* Register all scancodes known to SDL (from the USB standard) */ | ||||
| # define _SC(id, str, name) keyboard->AddKey(id, #name); | # define _SC(id, str, name) keyboard->AddKey(id, #name); | ||||
| @@ -141,9 +148,9 @@ InputDeviceInternal* InputDeviceInternal::CreateStandardKeyboard() | |||||
| return keyboard; | return keyboard; | ||||
| } | } | ||||
| InputDeviceInternal* InputDeviceInternal::CreateStandardMouse() | |||||
| InputDevice* InputDevice::CreateStandardMouse() | |||||
| { | { | ||||
| InputDeviceInternal* mouse = new InputDeviceInternal(g_name_mouse.c_str()); | |||||
| InputDevice* mouse = new InputDevice(g_name_mouse.c_str()); | |||||
| mouse->AddKey(g_name_mouse_key_left.c_str()); | mouse->AddKey(g_name_mouse_key_left.c_str()); | ||||
| mouse->AddKey(g_name_mouse_key_middle.c_str()); | mouse->AddKey(g_name_mouse_key_middle.c_str()); | ||||
| mouse->AddKey(g_name_mouse_key_right.c_str()); | mouse->AddKey(g_name_mouse_key_right.c_str()); | ||||
| @@ -15,6 +15,7 @@ | |||||
| #include <string> | #include <string> | ||||
| #include <vector> | #include <vector> | ||||
| #include <memory> | |||||
| namespace lol | namespace lol | ||||
| { | { | ||||
| @@ -22,6 +23,10 @@ namespace lol | |||||
| class input | class input | ||||
| { | { | ||||
| public: | public: | ||||
| static std::shared_ptr<input> get(); | |||||
| // Keyboard API | |||||
| enum class key : uint16_t | enum class key : uint16_t | ||||
| { | { | ||||
| #define _SC(id, str, name) SC_##name = id, | #define _SC(id, str, name) SC_##name = id, | ||||
| @@ -31,6 +36,24 @@ public: | |||||
| static std::vector<key> const &all_keys(); | static std::vector<key> const &all_keys(); | ||||
| static std::string const &key_to_name(key k); | static std::string const &key_to_name(key k); | ||||
| static key name_to_key(std::string const &name); | static key name_to_key(std::string const &name); | ||||
| // Internal keyboard API (TODO: move to input device class?) | |||||
| void internal_set_key(key k, bool state); | |||||
| void internal_add_text(std::string const &text); | |||||
| // Mouse API | |||||
| /** Gets and sets whether the mouse cursor should be captured. */ | |||||
| void mouse_capture(bool value) { m_mouse_capture = value; } | |||||
| bool mouse_capture() const { return m_mouse_capture; } | |||||
| // Joystick API | |||||
| private: | |||||
| input() = default; | |||||
| bool m_mouse_capture = false; | |||||
| }; | }; | ||||
| const std::string g_name_mouse("Mouse"); | const std::string g_name_mouse("Mouse"); | ||||
| @@ -57,6 +80,25 @@ const std::string g_name_mouse_cursor("Cursor"); | |||||
| class InputDevice | class InputDevice | ||||
| { | { | ||||
| public: | public: | ||||
| InputDevice(std::string const &name) | |||||
| : m_name(name), | |||||
| m_input_active(false) | |||||
| { | |||||
| devices.push_unique(this); | |||||
| } | |||||
| ~InputDevice() | |||||
| { | |||||
| for (int i = 0; i < devices.count(); ++i) | |||||
| { | |||||
| if (devices[i] == this) | |||||
| { | |||||
| devices.remove(i); | |||||
| return; | |||||
| } | |||||
| } | |||||
| } | |||||
| /** Gets the name of this input device */ | /** Gets the name of this input device */ | ||||
| const std::string& GetName() const | const std::string& GetName() const | ||||
| { | { | ||||
| @@ -162,21 +204,66 @@ public: | |||||
| { | { | ||||
| return GetDevice(g_name_mouse); | return GetDevice(g_name_mouse); | ||||
| } | } | ||||
| static int GetJoystickCount() | |||||
| { | |||||
| return joystick_count; | |||||
| } | |||||
| static InputDevice* GetJoystick(const uint64_t num) | static InputDevice* GetJoystick(const uint64_t num) | ||||
| { | { | ||||
| return GetDevice(g_name_joystick(num)); | return GetDevice(g_name_joystick(num)); | ||||
| } | } | ||||
| /** Sets whether the mouse cursor should be captured. */ | |||||
| static void CaptureMouse(bool activated) | |||||
| public: | |||||
| /** Internal functions that allow to construct an InputDevice | |||||
| * dynamically, when the keys, axis and cursors are not known at | |||||
| * compile time. */ | |||||
| void AddKey(int id, char const * name); | |||||
| inline void AddKey(char const * name) | |||||
| { | |||||
| AddKey(-1, name); | |||||
| } | |||||
| void AddAxis(int id, char const * name, float sensitivity = 1.0f); | |||||
| inline void AddAxis(char const * name, float sensitivity = 1.0f) | |||||
| { | |||||
| AddAxis(-1, name, sensitivity); | |||||
| } | |||||
| void AddCursor(int id, char const * name); | |||||
| inline void AddCursor(char const * name) | |||||
| { | |||||
| AddCursor(-1, name); | |||||
| } | |||||
| void SetCursor(int id, vec2 const & position, ivec2 const & pixel) | |||||
| { | |||||
| m_cursors[id].m1 = position; | |||||
| m_cursors[id].m2 = pixel; | |||||
| } | |||||
| ivec2 GetCursorPixelPos(int id) | |||||
| { | |||||
| return m_cursors[id].m2; | |||||
| } | |||||
| /* Internal functions for the platform-specific drivers. */ | |||||
| void internal_set_key(int id, bool state) | |||||
| { | |||||
| m_keys[id] = state; | |||||
| } | |||||
| void internal_add_text(std::string const &text) | |||||
| { | |||||
| m_text += text; | |||||
| } | |||||
| void internal_set_axis(int id, float value) | |||||
| { | { | ||||
| m_capturemouse = activated; | |||||
| m_axis[id].m1 = value; | |||||
| } | } | ||||
| static InputDevice* CreateStandardKeyboard(); | |||||
| static InputDevice* CreateStandardMouse(); | |||||
| protected: | protected: | ||||
| // TODO: hide all of this in a InputDeviceData? | // TODO: hide all of this in a InputDeviceData? | ||||
| @@ -199,30 +286,8 @@ protected: | |||||
| /** Cursor position */ | /** Cursor position */ | ||||
| array<vec2, ivec2> m_cursors; | array<vec2, ivec2> m_cursors; | ||||
| static bool m_capturemouse; | |||||
| InputDevice(std::string const &name) | |||||
| : m_name(name), | |||||
| m_input_active(false) | |||||
| { | |||||
| devices.push_unique(this); | |||||
| } | |||||
| ~InputDevice() | |||||
| { | |||||
| for (int i = 0; i < devices.count(); ++i) | |||||
| { | |||||
| if (devices[i] == this) | |||||
| { | |||||
| devices.remove(i); | |||||
| return; | |||||
| } | |||||
| } | |||||
| } | |||||
| private: | private: | ||||
| static array<InputDevice*> devices; | static array<InputDevice*> devices; | ||||
| static int joystick_count; | |||||
| template <typename... T> | template <typename... T> | ||||
| size_t GetItemIndex(std::string const &name, std::vector<std::string, T...> const& a) const | size_t GetItemIndex(std::string const &name, std::vector<std::string, T...> const& a) const | ||||
| @@ -235,10 +300,6 @@ private: | |||||
| static InputDevice* GetDevice(std::string const &name) | static InputDevice* GetDevice(std::string const &name) | ||||
| { | { | ||||
| //Count the device types. TODO: Multi mouse/keyboard | |||||
| if (name.find(g_name_joystick()) != std::string::npos) | |||||
| ++joystick_count; | |||||
| for (int i = 0; i < devices.count(); ++i) | for (int i = 0; i < devices.count(); ++i) | ||||
| { | { | ||||
| if (devices[i]->m_name == name) | if (devices[i]->m_name == name) | ||||
| @@ -1,87 +0,0 @@ | |||||
| // | |||||
| // Lol Engine | |||||
| // | |||||
| // Copyright © 2017—2019 Sam Hocevar <sam@hocevar.net> | |||||
| // © 2010—2015 Benjamin Litzelmann | |||||
| // | |||||
| // Lol Engine is free software. It comes without any warranty, to | |||||
| // the extent permitted by applicable law. You can redistribute it | |||||
| // and/or modify it under the terms of the Do What the Fuck You Want | |||||
| // to Public License, Version 2, as published by the WTFPL Task Force. | |||||
| // See http://www.wtfpl.net/ for more details. | |||||
| // | |||||
| #pragma once | |||||
| #include <string> | |||||
| namespace lol | |||||
| { | |||||
| /** Internal class (not public) that allows to construct an InputDevice | |||||
| * dynamically, when the keys, axis and cursors are not known at | |||||
| * compile time. */ | |||||
| class InputDeviceInternal : public InputDevice | |||||
| { | |||||
| public: | |||||
| inline InputDeviceInternal(std::string const& name) : InputDevice(name) { } | |||||
| void AddKey(int id, char const * name); | |||||
| inline void AddKey(char const * name) | |||||
| { | |||||
| AddKey(-1, name); | |||||
| } | |||||
| void AddAxis(int id, char const * name, float sensitivity = 1.0f); | |||||
| inline void AddAxis(char const * name, float sensitivity = 1.0f) | |||||
| { | |||||
| AddAxis(-1, name, sensitivity); | |||||
| } | |||||
| void AddCursor(int id, char const * name); | |||||
| inline void AddCursor(char const * name) | |||||
| { | |||||
| AddCursor(-1, name); | |||||
| } | |||||
| void SetCursor(int id, vec2 const & position, ivec2 const & pixel) | |||||
| { | |||||
| m_cursors[id].m1 = position; | |||||
| m_cursors[id].m2 = pixel; | |||||
| } | |||||
| ivec2 GetCursorPixelPos(int id) | |||||
| { | |||||
| return m_cursors[id].m2; | |||||
| } | |||||
| /* Internal functions for the platform-specific drivers. */ | |||||
| void internal_set_key(int id, bool state) | |||||
| { | |||||
| m_keys[id] = state; | |||||
| } | |||||
| void internal_add_text(std::string const &text) | |||||
| { | |||||
| m_text += text; | |||||
| } | |||||
| void internal_set_axis(int id, float value) | |||||
| { | |||||
| m_axis[id].m1 = value; | |||||
| } | |||||
| static bool GetMouseCapture() | |||||
| { | |||||
| return m_capturemouse; | |||||
| } | |||||
| static InputDeviceInternal* CreateStandardKeyboard(); | |||||
| static InputDeviceInternal* CreateStandardMouse(); | |||||
| }; | |||||
| } /* namespace lol */ | |||||
| @@ -23,8 +23,8 @@ | |||||
| # include <emscripten/html5.h> | # include <emscripten/html5.h> | ||||
| #endif | #endif | ||||
| #include "ui/input_internal.h" | |||||
| #include "ui/sdl-input.h" | #include "ui/sdl-input.h" | ||||
| #include "ui/input.h" | |||||
| /* We force joystick polling because no events are received when | /* We force joystick polling because no events are received when | ||||
| * there is no SDL display (eg. on the Raspberry Pi). */ | * there is no SDL display (eg. on the Raspberry Pi). */ | ||||
| @@ -89,8 +89,8 @@ SdlInput::SdlInput(int app_w, int app_h, int screen_w, int screen_h) | |||||
| SDL_Init(SDL_INIT_TIMER | SDL_INIT_JOYSTICK); | SDL_Init(SDL_INIT_TIMER | SDL_INIT_JOYSTICK); | ||||
| #endif | #endif | ||||
| m_keyboard = InputDeviceInternal::CreateStandardKeyboard(); | |||||
| m_mouse = InputDeviceInternal::CreateStandardMouse(); | |||||
| m_keyboard = InputDevice::CreateStandardKeyboard(); | |||||
| m_mouse = InputDevice::CreateStandardMouse(); | |||||
| // XXX: another option for emscripten is to properly support gamepads | // XXX: another option for emscripten is to properly support gamepads | ||||
| #if LOL_USE_SDL && !__EMSCRIPTEN__ | #if LOL_USE_SDL && !__EMSCRIPTEN__ | ||||
| @@ -118,7 +118,7 @@ SdlInput::SdlInput(int app_w, int app_h, int screen_w, int screen_h) | |||||
| } | } | ||||
| //format("Joystick%d", i + 1).c_str() | //format("Joystick%d", i + 1).c_str() | ||||
| InputDeviceInternal* stick = new InputDeviceInternal(g_name_joystick(i + 1)); | |||||
| InputDevice* stick = new InputDevice(g_name_joystick(i + 1)); | |||||
| for (int j = 0; j < SDL_JoystickNumAxes(sdlstick); ++j) | for (int j = 0; j < SDL_JoystickNumAxes(sdlstick); ++j) | ||||
| stick->AddAxis(format("Axis%d", j + 1).c_str()); | stick->AddAxis(format("Axis%d", j + 1).c_str()); | ||||
| for (int j = 0; j < SDL_JoystickNumButtons(sdlstick); ++j) | for (int j = 0; j < SDL_JoystickNumButtons(sdlstick); ++j) | ||||
| @@ -283,9 +283,9 @@ void SdlInput::tick(float seconds) | |||||
| SDL_GetMouseState(&mouse.x, &mouse.y); | SDL_GetMouseState(&mouse.x, &mouse.y); | ||||
| mouse.y = Video::GetSize().y - 1 - mouse.y; | mouse.y = Video::GetSize().y - 1 - mouse.y; | ||||
| if (InputDeviceInternal::GetMouseCapture() != m_mousecapture) | |||||
| if (input::get()->mouse_capture() != m_mousecapture) | |||||
| { | { | ||||
| m_mousecapture = InputDeviceInternal::GetMouseCapture(); | |||||
| m_mousecapture = input::get()->mouse_capture(); | |||||
| SDL_SetRelativeMouseMode(m_mousecapture ? SDL_TRUE : SDL_FALSE); | SDL_SetRelativeMouseMode(m_mousecapture ? SDL_TRUE : SDL_FALSE); | ||||
| mouse = ivec2(m_app * .5f); | mouse = ivec2(m_app * .5f); | ||||
| @@ -46,9 +46,9 @@ protected: | |||||
| private: | private: | ||||
| void tick(float seconds); | void tick(float seconds); | ||||
| array<SDL_Joystick *, class InputDeviceInternal *> m_joysticks; | |||||
| InputDeviceInternal *m_mouse = nullptr; | |||||
| InputDeviceInternal *m_keyboard = nullptr; | |||||
| array<SDL_Joystick *, class InputDevice *> m_joysticks; | |||||
| InputDevice *m_mouse = nullptr; | |||||
| InputDevice *m_keyboard = nullptr; | |||||
| ivec2 m_prevmouse = ivec2::zero; | ivec2 m_prevmouse = ivec2::zero; | ||||
| vec2 m_app; | vec2 m_app; | ||||