| @@ -31,10 +31,10 @@ public: | |||||
| # ifdef OLD_SCHOOL | # ifdef OLD_SCHOOL | ||||
| m_controller->SetInputCount(KEY_MAX, AXIS_MAX); | m_controller->SetInputCount(KEY_MAX, AXIS_MAX); | ||||
| auto keyboard = input::get()->keyboard(); | |||||
| auto keyboard = input::keyboard(); | |||||
| m_controller->GetKey(KEY_MANUAL_ROTATION).Bind(g_name_keyboard, "Space"); | m_controller->GetKey(KEY_MANUAL_ROTATION).Bind(g_name_keyboard, "Space"); | ||||
| auto mouse = input::get()->mouse(); | |||||
| auto mouse = input::mouse(); | |||||
| if (mouse) | if (mouse) | ||||
| { | { | ||||
| m_controller->GetKey(KEY_DRAG_MESH).Bind(g_name_mouse, "Left"); | m_controller->GetKey(KEY_DRAG_MESH).Bind(g_name_mouse, "Left"); | ||||
| @@ -119,20 +119,21 @@ public: | |||||
| /* Handle mouse */ | /* Handle mouse */ | ||||
| if (true) | if (true) | ||||
| { | { | ||||
| if (m_controller->IsKeyPressed(KEY_DRAG_MESH)) | |||||
| auto mouse = input::mouse(); | |||||
| if (mouse->button(input::button::BTN_Left)) | |||||
| { | { | ||||
| input::get()->mouse_capture(true); | |||||
| mouse->capture(true); | |||||
| m_pitch_angle -= m_controller->GetAxisValue(AXIS_DRAG_PITCH) * seconds * 0.1f; | m_pitch_angle -= m_controller->GetAxisValue(AXIS_DRAG_PITCH) * seconds * 0.1f; | ||||
| m_yaw_angle += m_controller->GetAxisValue(AXIS_DRAG_YAW) * seconds * 0.1f; | m_yaw_angle += m_controller->GetAxisValue(AXIS_DRAG_YAW) * seconds * 0.1f; | ||||
| } | } | ||||
| else | else | ||||
| { | { | ||||
| input::get()->mouse_capture(false); | |||||
| mouse->capture(false); | |||||
| if (m_autorot) | if (m_autorot) | ||||
| m_yaw_angle += seconds * 0.2f; | m_yaw_angle += seconds * 0.2f; | ||||
| } | } | ||||
| auto mouse = input::get()->mouse(); | |||||
| m_text->SetText(lol::format( | m_text->SetText(lol::format( | ||||
| "cursor: (%0.3f, %0.3f) - pixel (%d, %d)", | "cursor: (%0.3f, %0.3f) - pixel (%d, %d)", | ||||
| mouse->get_cursor_uv(0).x, mouse->get_cursor_uv(0).y, | mouse->get_cursor_uv(0).x, mouse->get_cursor_uv(0).y, | ||||
| @@ -157,7 +157,7 @@ public: | |||||
| { | { | ||||
| WorldEntity::tick_game(seconds); | WorldEntity::tick_game(seconds); | ||||
| ivec2 mousepos = input::get()->mouse()->get_cursor_pixel(0); | |||||
| ivec2 mousepos = input::mouse()->get_cursor_pixel(0); | |||||
| int prev_frame = (m_frame + 4) % 4; | int prev_frame = (m_frame + 4) % 4; | ||||
| m_frame = (m_frame + 1) % 4; | m_frame = (m_frame + 1) % 4; | ||||
| @@ -28,18 +28,6 @@ LOLFX_RESOURCE_DECLARE(12_voronoi_distance); | |||||
| LOLFX_RESOURCE_DECLARE(12_distance); | LOLFX_RESOURCE_DECLARE(12_distance); | ||||
| LOLFX_RESOURCE_DECLARE(12_texture_to_screen); | LOLFX_RESOURCE_DECLARE(12_texture_to_screen); | ||||
| enum | |||||
| { | |||||
| KEY_ESC, | |||||
| KEY_PUSH, | |||||
| KEY_POP, | |||||
| KEY_F1, | |||||
| KEY_F2, | |||||
| KEY_F3, | |||||
| KEY_MAX | |||||
| }; | |||||
| enum FboType | enum FboType | ||||
| { | { | ||||
| SrcVoronoiFbo, | SrcVoronoiFbo, | ||||
| @@ -66,24 +54,17 @@ public: | |||||
| m_time = .0f; | m_time = .0f; | ||||
| m_timer = -1.0f; | m_timer = -1.0f; | ||||
| mode = 0; | mode = 0; | ||||
| m_controller = new Controller("Default"); | |||||
| m_controller->GetKey(KEY_ESC).Bind(g_name_keyboard, "Escape"); | |||||
| m_controller->GetKey(KEY_PUSH).Bind(g_name_keyboard, "p"); | |||||
| m_controller->GetKey(KEY_POP).Bind(g_name_keyboard, "o"); | |||||
| m_controller->GetKey(KEY_F1).Bind(g_name_keyboard, "F1"); | |||||
| m_controller->GetKey(KEY_F2).Bind(g_name_keyboard, "F2"); | |||||
| m_controller->GetKey(KEY_F3).Bind(g_name_keyboard, "F3"); | |||||
| } | } | ||||
| virtual void tick_game(float seconds) | virtual void tick_game(float seconds) | ||||
| { | { | ||||
| WorldEntity::tick_game(seconds); | WorldEntity::tick_game(seconds); | ||||
| { | |||||
| //Shutdown logic | |||||
| if (m_controller->WasKeyReleasedThisFrame(KEY_ESC)) | |||||
| Ticker::Shutdown(); | |||||
| } | |||||
| auto keyboard = input::keyboard(); | |||||
| // Shutdown logic | |||||
| if (keyboard->key_released(input::key::SC_Escape)) | |||||
| Ticker::Shutdown(); | |||||
| m_time += seconds; | m_time += seconds; | ||||
| m_hotspot = 0.4f * vec3((float)lol::sin(m_time * 4.0) + (float)lol::cos(m_time * 5.3), | m_hotspot = 0.4f * vec3((float)lol::sin(m_time * 4.0) + (float)lol::cos(m_time * 5.3), | ||||
| @@ -170,34 +151,33 @@ public: | |||||
| m_cur_fbo = VoronoiFbo; | m_cur_fbo = VoronoiFbo; | ||||
| } | } | ||||
| auto keyboard = input::keyboard(); | |||||
| if (keyboard->key_released(input::key::SC_O)) | |||||
| voronoi_points.pop(); | |||||
| else if (keyboard->key_released(input::key::SC_P)) | |||||
| voronoi_points.push(vec3(rand<float>(512.f), rand<float>(512.f), .0f), | |||||
| vec2(64.f + rand<float>(64.f), 64.f + rand<float>(64.f))); | |||||
| else if (keyboard->key_released(input::key::SC_F1)) | |||||
| m_cur_fbo = SrcVoronoiFbo; | |||||
| else if (keyboard->key_released(input::key::SC_F2)) | |||||
| m_cur_fbo = VoronoiFbo; | |||||
| else if (keyboard->key_released(input::key::SC_F3)) | |||||
| { | { | ||||
| //Shutdown logic | |||||
| if (m_controller->WasKeyReleasedThisFrame(KEY_POP)) | |||||
| voronoi_points.pop(); | |||||
| else if (m_controller->WasKeyReleasedThisFrame(KEY_PUSH)) | |||||
| voronoi_points.push(vec3(rand<float>(512.f), rand<float>(512.f), .0f), | |||||
| vec2(64.f + rand<float>(64.f), 64.f + rand<float>(64.f))); | |||||
| else if (m_controller->WasKeyReleasedThisFrame(KEY_F1)) | |||||
| m_cur_fbo = SrcVoronoiFbo; | |||||
| else if (m_controller->WasKeyReleasedThisFrame(KEY_F2)) | |||||
| m_cur_fbo = VoronoiFbo; | |||||
| else if (m_controller->WasKeyReleasedThisFrame(KEY_F3)) | |||||
| voronoi_points.clear(); | |||||
| if (mode == 0) | |||||
| { | { | ||||
| voronoi_points.clear(); | |||||
| if (mode == 0) | |||||
| { | |||||
| int i = 4; | |||||
| while (i-- > 0) | |||||
| voronoi_points.push(vec3(rand<float>(512.f), rand<float>(512.f), .0f), | |||||
| vec2(64.f + rand<float>(64.f), 64.f + rand<float>(64.f)) | |||||
| //vec2::zero | |||||
| ); | |||||
| mode = 1; | |||||
| } | |||||
| else | |||||
| { | |||||
| mode = 0; | |||||
| } | |||||
| int i = 4; | |||||
| while (i-- > 0) | |||||
| voronoi_points.push(vec3(rand<float>(512.f), rand<float>(512.f), .0f), | |||||
| vec2(64.f + rand<float>(64.f), 64.f + rand<float>(64.f)) | |||||
| //vec2::zero | |||||
| ); | |||||
| mode = 1; | |||||
| } | |||||
| else | |||||
| { | |||||
| mode = 0; | |||||
| } | } | ||||
| } | } | ||||
| @@ -381,7 +361,6 @@ public: | |||||
| } | } | ||||
| private: | private: | ||||
| Controller* m_controller; | |||||
| array<vec3, vec2> voronoi_points; | array<vec3, vec2> voronoi_points; | ||||
| array<vec2> m_vertices; | array<vec2> m_vertices; | ||||
| std::shared_ptr<Shader> m_screen_shader; | std::shared_ptr<Shader> m_screen_shader; | ||||
| @@ -193,7 +193,7 @@ void lol::AndroidAppData::DestroyDisplay() | |||||
| */ | */ | ||||
| int32_t lol::AndroidAppData::HandleInput(AInputEvent* event) | int32_t lol::AndroidAppData::HandleInput(AInputEvent* event) | ||||
| { | { | ||||
| auto mouse = input::get()->mouse(); | |||||
| auto mouse = input::mouse(); | |||||
| switch (AInputEvent_getType(event)) | switch (AInputEvent_getType(event)) | ||||
| { | { | ||||
| @@ -200,10 +200,10 @@ float AxisBinding::RetrieveCurrentValue() | |||||
| for (int i = 0; i < m_keybindings.count(); ++i) | for (int i = 0; i < m_keybindings.count(); ++i) | ||||
| { | { | ||||
| float value = 0.0f; | float value = 0.0f; | ||||
| m_keybindings[i].m1->key(m_keybindings[i].m2); | |||||
| value += m_keybindings[i].m1->key(m_keybindings[i].m3) ? 1.0f : 0.0f; | |||||
| m_keybindings[i].m1->key((input::key)m_keybindings[i].m2); | |||||
| value += m_keybindings[i].m1->key((input::key)m_keybindings[i].m3) ? 1.0f : 0.0f; | |||||
| if (m_keybindings[i].m2 != -1) | if (m_keybindings[i].m2 != -1) | ||||
| value += m_keybindings[i].m1->key(m_keybindings[i].m2) ? -1.0f : 0.0f; | |||||
| value += m_keybindings[i].m1->key((input::key)m_keybindings[i].m2) ? -1.0f : 0.0f; | |||||
| if (value > max_positive) | if (value > max_positive) | ||||
| max_positive = value; | max_positive = value; | ||||
| @@ -371,7 +371,7 @@ void Controller::BindProfile(InputProfile const& setup) | |||||
| m_profile = setup; | m_profile = setup; | ||||
| // Keyboard | // Keyboard | ||||
| m_keyboard = input::get()->keyboard(); | |||||
| m_keyboard = input::keyboard(); | |||||
| if (m_keyboard) | if (m_keyboard) | ||||
| { | { | ||||
| for (InputProfile::KeyboardKey& key : m_profile.m_keys) | for (InputProfile::KeyboardKey& key : m_profile.m_keys) | ||||
| @@ -379,7 +379,7 @@ void Controller::BindProfile(InputProfile const& setup) | |||||
| } | } | ||||
| // Mouse | // Mouse | ||||
| m_mouse = input::get()->mouse(); | |||||
| m_mouse = input::mouse(); | |||||
| if (m_mouse) | if (m_mouse) | ||||
| { | { | ||||
| for (InputProfile::MouseKey& key : m_profile.m_mouse_keys) | for (InputProfile::MouseKey& key : m_profile.m_mouse_keys) | ||||
| @@ -56,7 +56,7 @@ protected: | |||||
| m_previous = m_current; | m_previous = m_current; | ||||
| m_current = false; | m_current = false; | ||||
| for (int i = 0; i < m_keybindings.count(); ++i) | for (int i = 0; i < m_keybindings.count(); ++i) | ||||
| m_current = m_current || m_keybindings[i].m1->key(m_keybindings[i].m2); | |||||
| m_current = m_current || m_keybindings[i].m1->key((input::key)m_keybindings[i].m2); | |||||
| } | } | ||||
| /** m1 is the InputDevice, m2 is the key index on the InputDevice */ | /** m1 is the InputDevice, m2 is the key index on the InputDevice */ | ||||
| @@ -145,7 +145,7 @@ void D3d9Input::tick_game(float seconds) | |||||
| int key_index = (1 << b) > XINPUT_GAMEPAD_RIGHT_SHOULDER ? b - 2 : b; | int key_index = (1 << b) > XINPUT_GAMEPAD_RIGHT_SHOULDER ? b - 2 : b; | ||||
| m_data->m_joysticks[i].m2->internal_set_key(key_index, ((uint16_t)(state.Gamepad.wButtons) >> b) & 1); | |||||
| m_data->m_joysticks[i].m2->internal_set_button((input::button)key_index, ((uint16_t)(state.Gamepad.wButtons) >> b) & 1); | |||||
| } | } | ||||
| } | } | ||||
| #endif | #endif | ||||
| @@ -207,8 +207,8 @@ void gui::tick_game(float seconds) | |||||
| { | { | ||||
| super::tick_game(seconds); | super::tick_game(seconds); | ||||
| auto keyboard = input::get()->keyboard(); | |||||
| auto mouse = input::get()->mouse(); | |||||
| auto keyboard = input::keyboard(); | |||||
| auto mouse = input::mouse(); | |||||
| ImGuiIO& io = ImGui::GetIO(); | ImGuiIO& io = ImGui::GetIO(); | ||||
| @@ -233,13 +233,13 @@ void gui::tick_game(float seconds) | |||||
| io.MouseDrawCursor = true; | io.MouseDrawCursor = true; | ||||
| // Update Keyboard | // Update Keyboard | ||||
| io.KeyCtrl = m_controller->IsKeyPressed((int)input::key::SC_LCtrl) | |||||
| || m_controller->IsKeyPressed((int)input::key::SC_RCtrl); | |||||
| io.KeyShift = m_controller->IsKeyPressed((int)input::key::SC_LShift) | |||||
| || m_controller->IsKeyPressed((int)input::key::SC_RShift); | |||||
| io.KeyCtrl = keyboard->key(input::key::SC_LCtrl) | |||||
| || keyboard->key(input::key::SC_RCtrl); | |||||
| io.KeyShift = keyboard->key(input::key::SC_LShift) | |||||
| || keyboard->key(input::key::SC_RShift); | |||||
| for (input::key k : input::all_keys()) | for (input::key k : input::all_keys()) | ||||
| io.KeysDown[(int)k] = m_controller->IsKeyPressed((int)k); | |||||
| io.KeysDown[(int)k] = keyboard->key(k); | |||||
| // Update text input | // Update text input | ||||
| if (io.WantTextInput) | if (io.WantTextInput) | ||||
| @@ -259,9 +259,9 @@ void gui::tick_game(float seconds) | |||||
| //msg::debug("%.2f/%.2f\n", io.MousePos.x, io.MousePos.y); | //msg::debug("%.2f/%.2f\n", io.MousePos.x, io.MousePos.y); | ||||
| io.MouseWheel = m_controller->GetAxisValue(axis_enum::Scroll); | io.MouseWheel = m_controller->GetAxisValue(axis_enum::Scroll); | ||||
| io.MouseDown[0] = m_controller->IsKeyPressed(key_enum::LeftClick); | |||||
| io.MouseDown[1] = m_controller->IsKeyPressed(key_enum::RightClick); | |||||
| io.MouseDown[2] = m_controller->IsKeyPressed(key_enum::MiddleClick); | |||||
| io.MouseDown[0] = mouse->button(input::button::BTN_Left); | |||||
| io.MouseDown[1] = mouse->button(input::button::BTN_Right); | |||||
| io.MouseDown[2] = mouse->button(input::button::BTN_Middle); | |||||
| // FIXME: handle key_enum::Focus? | // FIXME: handle key_enum::Focus? | ||||
| // Start the frame | // Start the frame | ||||
| @@ -47,11 +47,11 @@ input::input() | |||||
| // Create default mouse device | // Create default mouse device | ||||
| m_mouse = std::make_shared<InputDevice>(g_name_mouse.c_str()); | m_mouse = std::make_shared<InputDevice>(g_name_mouse.c_str()); | ||||
| m_mouse->AddKey(g_name_mouse_key_left.c_str()); | |||||
| m_mouse->AddKey(g_name_mouse_key_middle.c_str()); | |||||
| m_mouse->AddKey(g_name_mouse_key_right.c_str()); | |||||
| m_mouse->AddButton((int)input::button::BTN_Left, g_name_mouse_key_left.c_str()); | |||||
| m_mouse->AddButton((int)input::button::BTN_Middle, g_name_mouse_key_middle.c_str()); | |||||
| m_mouse->AddButton((int)input::button::BTN_Right, g_name_mouse_key_right.c_str()); | |||||
| m_mouse->AddButton((int)input::button::BTN_Focus, g_name_mouse_key_in_screen.c_str()); | |||||
| // Added to manage if mouse is in the screen or not. | // Added to manage if mouse is in the screen or not. | ||||
| m_mouse->AddKey(g_name_mouse_key_in_screen.c_str()); | |||||
| m_mouse->AddAxis(g_name_mouse_axis_x.c_str()); | m_mouse->AddAxis(g_name_mouse_axis_x.c_str()); | ||||
| m_mouse->AddAxis(g_name_mouse_axis_y.c_str()); | m_mouse->AddAxis(g_name_mouse_axis_y.c_str()); | ||||
| m_mouse->AddAxis(g_name_mouse_axis_xpixel.c_str()); | m_mouse->AddAxis(g_name_mouse_axis_xpixel.c_str()); | ||||
| @@ -130,6 +130,20 @@ void InputDevice::AddKey(int index, const char* name) | |||||
| m_key_names[index] = name; | m_key_names[index] = name; | ||||
| } | } | ||||
| void InputDevice::AddButton(int index, const char* name) | |||||
| { | |||||
| if (index == -1) | |||||
| index = (int)m_button_names.size(); | |||||
| while (index >= (int)m_button_names.size()) | |||||
| { | |||||
| m_button_names.push_back(""); | |||||
| m_buttons.push_back(false); | |||||
| } | |||||
| m_button_names[index] = name; | |||||
| } | |||||
| void InputDevice::AddAxis(int index, const char* name, float sensitivity) | void InputDevice::AddAxis(int index, const char* name, float sensitivity) | ||||
| { | { | ||||
| if (index == -1) | if (index == -1) | ||||
| @@ -15,6 +15,7 @@ | |||||
| #include <string> | #include <string> | ||||
| #include <vector> | #include <vector> | ||||
| #include <unordered_set> | |||||
| #include <memory> | #include <memory> | ||||
| namespace lol | namespace lol | ||||
| @@ -29,6 +30,7 @@ const std::string g_name_mouse_key_left("Left"); | |||||
| const std::string g_name_mouse_key_middle("Middle"); | const std::string g_name_mouse_key_middle("Middle"); | ||||
| const std::string g_name_mouse_key_right("Right"); | const std::string g_name_mouse_key_right("Right"); | ||||
| const std::string g_name_mouse_key_in_screen("InScreen"); | const std::string g_name_mouse_key_in_screen("InScreen"); | ||||
| const std::string g_name_mouse_axis_x("X"); | const std::string g_name_mouse_axis_x("X"); | ||||
| const std::string g_name_mouse_axis_y("Y"); | const std::string g_name_mouse_axis_y("Y"); | ||||
| const std::string g_name_mouse_axis_xpixel("XPixel"); | const std::string g_name_mouse_axis_xpixel("XPixel"); | ||||
| @@ -36,6 +38,45 @@ const std::string g_name_mouse_axis_ypixel("YPixel"); | |||||
| const std::string g_name_mouse_axis_scroll("Scroll"); | const std::string g_name_mouse_axis_scroll("Scroll"); | ||||
| const std::string g_name_mouse_cursor("Cursor"); | const std::string g_name_mouse_cursor("Cursor"); | ||||
| class input | |||||
| { | |||||
| public: | |||||
| static std::shared_ptr<input> get(); | |||||
| // Default devices | |||||
| static std::shared_ptr<class InputDevice> keyboard() { return get()->m_keyboard; } | |||||
| static std::shared_ptr<class InputDevice> mouse() { return get()->m_mouse; } | |||||
| // Keyboard API | |||||
| enum class key : uint16_t | |||||
| { | |||||
| #define _SC(id, str, name) SC_##name = id, | |||||
| #include "ui/keys.inc" | |||||
| }; | |||||
| enum class button : uint16_t | |||||
| { | |||||
| BTN_Left, | |||||
| BTN_Right, | |||||
| BTN_Middle, | |||||
| BTN_Focus, | |||||
| }; | |||||
| static std::vector<key> const &all_keys(); | |||||
| static std::string const &key_to_name(key k); | |||||
| static key name_to_key(std::string const &name); | |||||
| // Joystick API | |||||
| private: | |||||
| input(); | |||||
| std::shared_ptr<class InputDevice> m_keyboard; | |||||
| std::shared_ptr<class InputDevice> m_mouse; | |||||
| }; | |||||
| class InputDevice | class InputDevice | ||||
| { | { | ||||
| public: | public: | ||||
| @@ -76,6 +117,46 @@ public: | |||||
| return GetItemIndex(name, m_axis_names); | return GetItemIndex(name, m_axis_names); | ||||
| } | } | ||||
| // | |||||
| // Bindings section | |||||
| // | |||||
| void bind(input::key key, uint16_t event); | |||||
| void unbind(input::key key, uint16_t event); | |||||
| void bind(input::button button, uint16_t event); | |||||
| void unbind(input::button button, uint16_t event); | |||||
| // | |||||
| // Key, button etc. state | |||||
| // | |||||
| // Get the current state of the given key | |||||
| bool key(input::key key) const { return m_keys[(int)key]; } | |||||
| bool key_released(input::key key) const | |||||
| { | |||||
| return m_released_keys.find(key) != m_released_keys.end(); | |||||
| } | |||||
| bool key_pressed(input::key key) const | |||||
| { | |||||
| return m_pressed_keys.find(key) != m_pressed_keys.end(); | |||||
| } | |||||
| // Get the current state of the given button | |||||
| bool button(input::button button) const { return m_buttons[(int)button]; } | |||||
| bool button_released(input::button button) const | |||||
| { | |||||
| return m_released_buttons.find(button) != m_released_buttons.end(); | |||||
| } | |||||
| bool button_pressed(input::button button) const | |||||
| { | |||||
| return m_pressed_buttons.find(button) != m_pressed_buttons.end(); | |||||
| } | |||||
| // | // | ||||
| // Keyboard-specific section | // Keyboard-specific section | ||||
| // | // | ||||
| @@ -86,17 +167,19 @@ public: | |||||
| /** Get the current state of all keys */ | /** Get the current state of all keys */ | ||||
| std::vector<bool> const &keys() const { return m_keys; } | std::vector<bool> const &keys() const { return m_keys; } | ||||
| /** Get the current state of the given key, true being pressed and | |||||
| * false being released */ | |||||
| bool key(int index) const { return m_keys[index]; } | |||||
| /** Gets the latest contents of text input. */ | /** Gets the latest contents of text input. */ | ||||
| std::string text(); | std::string text(); | ||||
| bool capture_text(); | bool capture_text(); | ||||
| void capture_text(bool status); | void capture_text(bool status); | ||||
| // | |||||
| // Mouse-specific section | |||||
| // | |||||
| // Gets and sets whether the mouse cursor should be captured. | |||||
| void capture(bool value) { m_capture = value; } | |||||
| bool capture() const { return m_capture; } | |||||
| /** Gets the current value of the given axis. Devices should try to | /** Gets the current value of the given axis. Devices should try to | ||||
| * clamp this value between -1 and 1, though it is not guaranteed. */ | * clamp this value between -1 and 1, though it is not guaranteed. */ | ||||
| @@ -169,6 +252,13 @@ public: | |||||
| AddKey(-1, name); | AddKey(-1, name); | ||||
| } | } | ||||
| void AddButton(int id, char const * name); | |||||
| inline void AddButton(char const * name) | |||||
| { | |||||
| AddButton(-1, name); | |||||
| } | |||||
| void AddAxis(int id, char const * name, float sensitivity = 1.0f); | void AddAxis(int id, char const * name, float sensitivity = 1.0f); | ||||
| inline void AddAxis(char const * name, float sensitivity = 1.0f) | inline void AddAxis(char const * name, float sensitivity = 1.0f) | ||||
| @@ -184,15 +274,32 @@ public: | |||||
| } | } | ||||
| /* Internal functions for the platform-specific drivers. */ | /* Internal functions for the platform-specific drivers. */ | ||||
| void internal_begin_frame() | |||||
| { | |||||
| m_pressed_keys.clear(); | |||||
| m_released_keys.clear(); | |||||
| m_pressed_buttons.clear(); | |||||
| m_released_buttons.clear(); | |||||
| } | |||||
| void internal_set_cursor(int id, vec2 const & position, ivec2 const & pixel) | void internal_set_cursor(int id, vec2 const & position, ivec2 const & pixel) | ||||
| { | { | ||||
| m_cursors[id].uv = position; | m_cursors[id].uv = position; | ||||
| m_cursors[id].pixel = pixel; | m_cursors[id].pixel = pixel; | ||||
| } | } | ||||
| void internal_set_key(int id, bool state) | |||||
| void internal_set_key(input::key key, bool state) | |||||
| { | |||||
| if (m_keys[(int)key] != state) | |||||
| (state ? m_pressed_keys : m_released_keys).insert(key); | |||||
| m_keys[(int)key] = state; | |||||
| } | |||||
| void internal_set_button(input::button button, bool state) | |||||
| { | { | ||||
| m_keys[id] = state; | |||||
| if (m_buttons[(int)button] != state) | |||||
| (state ? m_pressed_buttons : m_released_buttons).insert(button); | |||||
| m_buttons[(int)button] = state; | |||||
| } | } | ||||
| void internal_add_text(std::string const &text) | void internal_add_text(std::string const &text) | ||||
| @@ -211,11 +318,15 @@ protected: | |||||
| std::string m_name; | std::string m_name; | ||||
| std::vector<std::string> m_key_names; | std::vector<std::string> m_key_names; | ||||
| std::vector<std::string> m_button_names; | |||||
| std::vector<std::string> m_axis_names; | std::vector<std::string> m_axis_names; | ||||
| std::vector<std::string> m_cursor_names; | std::vector<std::string> m_cursor_names; | ||||
| /** Key states (pressed/released) */ | |||||
| /** Key and button states (pressed/released) */ | |||||
| std::vector<bool> m_keys; | std::vector<bool> m_keys; | ||||
| std::unordered_set<input::key> m_pressed_keys, m_released_keys; | |||||
| std::vector<bool> m_buttons; | |||||
| std::unordered_set<input::button> m_pressed_buttons, m_released_buttons; | |||||
| /** Text input state */ | /** Text input state */ | ||||
| std::string m_text; | std::string m_text; | ||||
| @@ -228,6 +339,9 @@ protected: | |||||
| struct cursor_state { vec2 uv; ivec2 pixel; }; | struct cursor_state { vec2 uv; ivec2 pixel; }; | ||||
| std::vector<cursor_state> m_cursors; | std::vector<cursor_state> m_cursors; | ||||
| // Capture (for mouse devices) | |||||
| bool m_capture = false; | |||||
| private: | private: | ||||
| static array<InputDevice*> devices; | static array<InputDevice*> devices; | ||||
| @@ -251,49 +365,5 @@ private: | |||||
| } | } | ||||
| }; | }; | ||||
| class input | |||||
| { | |||||
| public: | |||||
| static std::shared_ptr<input> get(); | |||||
| // Default devices | |||||
| std::shared_ptr<InputDevice> keyboard() { return m_keyboard; } | |||||
| std::shared_ptr<InputDevice> mouse() { return m_mouse; } | |||||
| // Keyboard API | |||||
| enum class key : uint16_t | |||||
| { | |||||
| #define _SC(id, str, name) SC_##name = id, | |||||
| #include "ui/keys.inc" | |||||
| }; | |||||
| static std::vector<key> const &all_keys(); | |||||
| static std::string const &key_to_name(key k); | |||||
| 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(); | |||||
| std::shared_ptr<InputDevice> m_keyboard; | |||||
| std::shared_ptr<InputDevice> m_mouse; | |||||
| bool m_mouse_capture = false; | |||||
| }; | |||||
| } /* namespace lol */ | } /* namespace lol */ | ||||
| @@ -131,8 +131,8 @@ void SdlInput::tick(float seconds) | |||||
| /* FIXME: maybe we should make use of this? */ | /* FIXME: maybe we should make use of this? */ | ||||
| UNUSED(seconds); | UNUSED(seconds); | ||||
| auto keyboard = input::get()->keyboard(); | |||||
| auto mouse = input::get()->mouse(); | |||||
| auto keyboard = input::keyboard(); | |||||
| auto mouse = input::mouse(); | |||||
| /* Pump all joystick events because no event is coming to us. */ | /* Pump all joystick events because no event is coming to us. */ | ||||
| # if SDL_FORCE_POLL_JOYSTICK && !__EMSCRIPTEN__ | # if SDL_FORCE_POLL_JOYSTICK && !__EMSCRIPTEN__ | ||||
| @@ -140,12 +140,13 @@ void SdlInput::tick(float seconds) | |||||
| for (int j = 0; j < m_joysticks.count(); j++) | for (int j = 0; j < m_joysticks.count(); j++) | ||||
| { | { | ||||
| for (int i = 0; i < SDL_JoystickNumButtons(m_joysticks[j].m1); i++) | for (int i = 0; i < SDL_JoystickNumButtons(m_joysticks[j].m1); i++) | ||||
| m_joysticks[j].m2->internal_set_key(i, SDL_JoystickGetButton(m_joysticks[j].m1, i) != 0); | |||||
| m_joysticks[j].m2->internal_set_button((input::button)i, SDL_JoystickGetButton(m_joysticks[j].m1, i) != 0); | |||||
| for (int i = 0; i < SDL_JoystickNumAxes(m_joysticks[j].m1); i++) | for (int i = 0; i < SDL_JoystickNumAxes(m_joysticks[j].m1); i++) | ||||
| m_joysticks[j].m2->internal_set_axis(i, (float)SDL_JoystickGetAxis(m_joysticks[j].m1, i) / 32768.f); | m_joysticks[j].m2->internal_set_axis(i, (float)SDL_JoystickGetAxis(m_joysticks[j].m1, i) / 32768.f); | ||||
| } | } | ||||
| # endif | # endif | ||||
| keyboard->internal_begin_frame(); | |||||
| mouse->internal_set_axis(4, 0); | mouse->internal_set_axis(4, 0); | ||||
| if (keyboard->capture_text()) | if (keyboard->capture_text()) | ||||
| @@ -165,29 +166,29 @@ void SdlInput::tick(float seconds) | |||||
| case SDL_KEYDOWN: | case SDL_KEYDOWN: | ||||
| case SDL_KEYUP: | case SDL_KEYUP: | ||||
| switch (int sc = event.key.keysym.scancode) | |||||
| switch (auto sc = (input::key)event.key.keysym.scancode) | |||||
| { | { | ||||
| // Lock management | // Lock management | ||||
| case (int)input::key::SC_CapsLock: | |||||
| case (int)input::key::SC_ScrollLock: | |||||
| case (int)input::key::SC_NumLockClear: | |||||
| case input::key::SC_CapsLock: | |||||
| case input::key::SC_ScrollLock: | |||||
| case input::key::SC_NumLockClear: | |||||
| // Update status on key down only | // Update status on key down only | ||||
| if (event.type == SDL_KEYDOWN) | if (event.type == SDL_KEYDOWN) | ||||
| { | { | ||||
| int sc2 = sc; | |||||
| auto sc2 = sc; | |||||
| switch (sc) | switch (sc) | ||||
| { | { | ||||
| case (int)input::key::SC_CapsLock: | |||||
| sc2 = (int)input::key::SC_CapsLockStatus; | |||||
| case input::key::SC_CapsLock: | |||||
| sc2 = input::key::SC_CapsLockStatus; | |||||
| break; | break; | ||||
| case (int)input::key::SC_ScrollLock: | |||||
| sc2 = (int)input::key::SC_ScrollLockStatus; | |||||
| case input::key::SC_ScrollLock: | |||||
| sc2 = input::key::SC_ScrollLockStatus; | |||||
| break; | break; | ||||
| case (int)input::key::SC_NumLockClear: | |||||
| sc2 = (int)input::key::SC_NumLockClearStatus; | |||||
| case input::key::SC_NumLockClear: | |||||
| sc2 = input::key::SC_NumLockClearStatus; | |||||
| break; | break; | ||||
| } | } | ||||
| keyboard->internal_set_key(sc2, !keyboard->key((int)sc2)); | |||||
| keyboard->internal_set_key(sc2, !keyboard->key(sc2)); | |||||
| } | } | ||||
| LOL_ATTR_FALLTHROUGH | LOL_ATTR_FALLTHROUGH | ||||
| default: | default: | ||||
| @@ -205,7 +206,7 @@ void SdlInput::tick(float seconds) | |||||
| case SDL_MOUSEBUTTONDOWN: | case SDL_MOUSEBUTTONDOWN: | ||||
| case SDL_MOUSEBUTTONUP: | case SDL_MOUSEBUTTONUP: | ||||
| //event.button.which | //event.button.which | ||||
| mouse->internal_set_key(event.button.button - 1, event.type == SDL_MOUSEBUTTONDOWN); | |||||
| mouse->internal_set_button((input::button)(event.button.button - 1), event.type == SDL_MOUSEBUTTONDOWN); | |||||
| break; | break; | ||||
| case SDL_MOUSEWHEEL: | case SDL_MOUSEWHEEL: | ||||
| mouse->internal_set_axis(4, (float)event.button.y); | mouse->internal_set_axis(4, (float)event.button.y); | ||||
| @@ -216,11 +217,11 @@ void SdlInput::tick(float seconds) | |||||
| { | { | ||||
| case SDL_WINDOWEVENT_ENTER: | case SDL_WINDOWEVENT_ENTER: | ||||
| case SDL_WINDOWEVENT_FOCUS_GAINED: | case SDL_WINDOWEVENT_FOCUS_GAINED: | ||||
| mouse->internal_set_key(3, true); | |||||
| mouse->internal_set_button(input::button::BTN_Focus, true); | |||||
| break; | break; | ||||
| case SDL_WINDOWEVENT_LEAVE: | case SDL_WINDOWEVENT_LEAVE: | ||||
| case SDL_WINDOWEVENT_FOCUS_LOST: | case SDL_WINDOWEVENT_FOCUS_LOST: | ||||
| mouse->internal_set_key(3, false); | |||||
| mouse->internal_set_button(input::button::BTN_Focus, false); | |||||
| break; | break; | ||||
| case SDL_WINDOWEVENT_RESIZED: | case SDL_WINDOWEVENT_RESIZED: | ||||
| Video::Resize(ivec2(event.window.data1, event.window.data2)); | Video::Resize(ivec2(event.window.data1, event.window.data2)); | ||||
| @@ -247,9 +248,9 @@ void SdlInput::tick(float seconds) | |||||
| SDL_GetMouseState(&mouse_pos.x, &mouse_pos.y); | SDL_GetMouseState(&mouse_pos.x, &mouse_pos.y); | ||||
| mouse_pos.y = Video::GetSize().y - 1 - mouse_pos.y; | mouse_pos.y = Video::GetSize().y - 1 - mouse_pos.y; | ||||
| if (input::get()->mouse_capture() != m_mousecapture) | |||||
| if (mouse->capture() != m_mousecapture) | |||||
| { | { | ||||
| m_mousecapture = input::get()->mouse_capture(); | |||||
| m_mousecapture = mouse->capture(); | |||||
| SDL_SetRelativeMouseMode(m_mousecapture ? SDL_TRUE : SDL_FALSE); | SDL_SetRelativeMouseMode(m_mousecapture ? SDL_TRUE : SDL_FALSE); | ||||
| mouse_pos = ivec2(m_app * .5f); | mouse_pos = ivec2(m_app * .5f); | ||||