@@ -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; | ||||