Browse Source

Improve keyboard config menu. Add support for modifier keys in key mappings

master
C. J. Howard 1 year ago
parent
commit
adc5ceb6e5
19 changed files with 755 additions and 406 deletions
  1. +0
    -1
      CMakeLists.txt
  2. +16
    -9
      src/app/sdl/sdl-input-manager.cpp
  3. +8
    -0
      src/game/context.hpp
  4. +27
    -21
      src/game/controls.cpp
  5. +18
    -8
      src/game/menu.cpp
  6. +5
    -4
      src/game/state/boot.cpp
  7. +181
    -0
      src/game/state/collection-menu.cpp
  8. +65
    -0
      src/game/state/collection-menu.hpp
  9. +1
    -1
      src/game/state/controls-menu.cpp
  10. +115
    -156
      src/game/state/keyboard-config-menu.cpp
  11. +10
    -3
      src/game/state/keyboard-config-menu.hpp
  12. +1
    -1
      src/game/state/language-menu.cpp
  13. +9
    -6
      src/game/state/main-menu.cpp
  14. +106
    -49
      src/input/control-map.cpp
  15. +50
    -9
      src/input/control-map.hpp
  16. +2
    -2
      src/input/gamepad.cpp
  17. +3
    -2
      src/input/mapping.cpp
  18. +5
    -1
      src/input/mapping.hpp
  19. +133
    -133
      src/input/scancode.hpp

+ 0
- 1
CMakeLists.txt View File

@ -1,6 +1,5 @@
cmake_minimum_required(VERSION 3.25) cmake_minimum_required(VERSION 3.25)
option(APPLICATION_NAME "Application name" "Antkeeper") option(APPLICATION_NAME "Application name" "Antkeeper")
option(APPLICATION_VERSION "Application version string" "0.0.0") option(APPLICATION_VERSION "Application version string" "0.0.0")
option(APPLICATION_AUTHOR "Application author" "C. J. Howard") option(APPLICATION_AUTHOR "Application author" "C. J. Howard")

+ 16
- 9
src/app/sdl/sdl-input-manager.cpp View File

@ -127,7 +127,7 @@ void sdl_input_manager::update()
const input::scancode scancode = static_cast<input::scancode>(event.key.keysym.scancode); const input::scancode scancode = static_cast<input::scancode>(event.key.keysym.scancode);
// Rebuild modifier keys bit mask // Rebuild modifier keys bit mask
if (event.key.keysym.mod != sdl_key_mod)
if (sdl_key_mod != event.key.keysym.mod)
{ {
sdl_key_mod = event.key.keysym.mod; sdl_key_mod = event.key.keysym.mod;
@ -140,6 +140,10 @@ void sdl_input_manager::update()
modifier_keys |= input::modifier_key::left_ctrl; modifier_keys |= input::modifier_key::left_ctrl;
if (sdl_key_mod & KMOD_RCTRL) if (sdl_key_mod & KMOD_RCTRL)
modifier_keys |= input::modifier_key::right_ctrl; modifier_keys |= input::modifier_key::right_ctrl;
if (sdl_key_mod & KMOD_LALT)
modifier_keys |= input::modifier_key::left_alt;
if (sdl_key_mod & KMOD_RALT)
modifier_keys |= input::modifier_key::right_alt;
if (sdl_key_mod & KMOD_LGUI) if (sdl_key_mod & KMOD_LGUI)
modifier_keys |= input::modifier_key::left_gui; modifier_keys |= input::modifier_key::left_gui;
if (sdl_key_mod & KMOD_RGUI) if (sdl_key_mod & KMOD_RGUI)
@ -237,14 +241,19 @@ void sdl_input_manager::update()
if (SDL_IsGameController(event.cdevice.which)) if (SDL_IsGameController(event.cdevice.which))
{ {
SDL_GameController* sdl_controller = SDL_GameControllerOpen(event.cdevice.which); SDL_GameController* sdl_controller = SDL_GameControllerOpen(event.cdevice.which);
const char* controller_name = SDL_GameControllerNameForIndex(event.cdevice.which);
if (sdl_controller) if (sdl_controller)
{ {
// Get gamepad name
const char* controller_name = SDL_GameControllerNameForIndex(event.cdevice.which);
if (!controller_name)
{
controller_name = "";
}
if (auto it = gamepad_map.find(event.cdevice.which); it != gamepad_map.end()) if (auto it = gamepad_map.find(event.cdevice.which); it != gamepad_map.end())
{ {
// Gamepad reconnected // Gamepad reconnected
debug::log::info("Reconnected gamepad \"{}\"", controller_name);
debug::log::info("Reconnected gamepad {}", event.cdevice.which);
it->second->connect(); it->second->connect();
} }
else else
@ -257,7 +266,7 @@ void sdl_input_manager::update()
::uuid gamepad_uuid; ::uuid gamepad_uuid;
std::memcpy(gamepad_uuid.data.data(), sdl_guid.data, gamepad_uuid.data.size()); std::memcpy(gamepad_uuid.data.data(), sdl_guid.data, gamepad_uuid.data.size());
debug::log::info("Connected gamepad \"{}\" (UUID: {})", controller_name, gamepad_uuid.string());
debug::log::info("Connected gamepad {}; name: \"{}\"; UUID: {}", event.cdevice.which, controller_name, gamepad_uuid.string());
// Create new gamepad // Create new gamepad
input::gamepad* gamepad = new input::gamepad(); input::gamepad* gamepad = new input::gamepad();
@ -275,7 +284,7 @@ void sdl_input_manager::update()
} }
else else
{ {
debug::log::error("Failed to connected gamepad \"{}\": {}", controller_name, SDL_GetError());
debug::log::error("Failed to connect gamepad {}: {}", event.cdevice.which, SDL_GetError());
SDL_ClearError(); SDL_ClearError();
} }
} }
@ -289,15 +298,13 @@ void sdl_input_manager::update()
if (sdl_controller) if (sdl_controller)
{ {
const char* controller_name = SDL_GameControllerNameForIndex(event.cdevice.which);
SDL_GameControllerClose(sdl_controller); SDL_GameControllerClose(sdl_controller);
if (auto it = gamepad_map.find(event.cdevice.which); it != gamepad_map.end()) if (auto it = gamepad_map.find(event.cdevice.which); it != gamepad_map.end())
{ {
it->second->disconnect(); it->second->disconnect();
} }
debug::log::info("Disconnected gamepad \"{}\"", controller_name);
debug::log::info("Disconnected gamepad {}", event.cdevice.which);
} }
break; break;

+ 8
- 0
src/game/context.hpp View File

@ -192,6 +192,14 @@ struct context
input::control menu_modifier_control; input::control menu_modifier_control;
std::vector<std::shared_ptr<::event::subscription>> menu_control_subscriptions; std::vector<std::shared_ptr<::event::subscription>> menu_control_subscriptions;
std::vector<std::shared_ptr<::event::subscription>> menu_mouse_subscriptions; std::vector<std::shared_ptr<::event::subscription>> menu_mouse_subscriptions;
input::control_map movement_controls;
input::control move_forward_control;
input::control move_back_control;
input::control move_left_control;
input::control move_right_control;
input::control move_up_control;
input::control move_down_control;
input::control pause_control;
// Debugging // Debugging
math::moving_average<float, 15> average_frame_time; math::moving_average<float, 15> average_frame_time;

+ 27
- 21
src/game/controls.cpp View File

@ -22,6 +22,7 @@
#include "game/menu.hpp" #include "game/menu.hpp"
#include "resources/resource-manager.hpp" #include "resources/resource-manager.hpp"
#include "resources/json.hpp" #include "resources/json.hpp"
#include "input/modifier-key.hpp"
namespace game { namespace game {
@ -29,7 +30,9 @@ void setup_window_controls(game::context& ctx)
{ {
// Map window controls // Map window controls
ctx.window_controls.add_mapping(ctx.fullscreen_control, input::key_mapping(nullptr, input::scancode::f11, false)); ctx.window_controls.add_mapping(ctx.fullscreen_control, input::key_mapping(nullptr, input::scancode::f11, false));
ctx.window_controls.add_mapping(ctx.fullscreen_control, input::key_mapping(nullptr, input::scancode::enter, false, input::modifier_key::alt));
ctx.window_controls.add_mapping(ctx.screenshot_control, input::key_mapping(nullptr, input::scancode::f12, false)); ctx.window_controls.add_mapping(ctx.screenshot_control, input::key_mapping(nullptr, input::scancode::f12, false));
ctx.window_controls.add_mapping(ctx.screenshot_control, input::key_mapping(nullptr, input::scancode::print_screen, false));
// Setup fullscreen control // Setup fullscreen control
ctx.window_control_subscriptions.emplace_back ctx.window_control_subscriptions.emplace_back
@ -203,10 +206,10 @@ void enable_menu_controls(game::context& ctx)
ctx.menu_controls.connect(ctx.input_manager->get_event_queue()); ctx.menu_controls.connect(ctx.input_manager->get_event_queue());
// Function to select menu item at mouse position // Function to select menu item at mouse position
auto select_menu_item = [&ctx](const math::vector<float, 2>& mouse_position)
auto select_menu_item = [&ctx](const math::vector<float, 2>& mouse_position) -> bool
{ {
const float padding = config::menu_mouseover_padding * ctx.menu_font.get_font_metrics().size; const float padding = config::menu_mouseover_padding * ctx.menu_font.get_font_metrics().size;
for (std::size_t i = 0; i < ctx.menu_item_texts.size(); ++i) for (std::size_t i = 0; i < ctx.menu_item_texts.size(); ++i)
{ {
auto [name, value] = ctx.menu_item_texts[i]; auto [name, value] = ctx.menu_item_texts[i];
@ -240,10 +243,12 @@ void enable_menu_controls(game::context& ctx)
{ {
*ctx.menu_item_index = static_cast<int>(i); *ctx.menu_item_index = static_cast<int>(i);
game::menu::update_text_color(ctx); game::menu::update_text_color(ctx);
break;
return true;
} }
} }
} }
return false;
}; };
// Enable menu mouse tracking // Enable menu mouse tracking
@ -266,29 +271,30 @@ void enable_menu_controls(game::context& ctx)
[&ctx, select_menu_item](const auto& event) [&ctx, select_menu_item](const auto& event)
{ {
// Select menu item at mouse position (if any) // Select menu item at mouse position (if any)
select_menu_item(math::vector<float, 2>(event.position));
// Determine appropriate menu item callback
auto callback = ctx.menu_select_callbacks[*ctx.menu_item_index];
if (event.button == input::mouse_button::left)
if (select_menu_item(math::vector<float, 2>(event.position)))
{ {
if (ctx.menu_left_callbacks[*ctx.menu_item_index])
// Determine appropriate menu item callback
auto callback = ctx.menu_select_callbacks[*ctx.menu_item_index];
if (event.button == input::mouse_button::left)
{ {
callback = ctx.menu_left_callbacks[*ctx.menu_item_index];
if (ctx.menu_left_callbacks[*ctx.menu_item_index])
{
callback = ctx.menu_left_callbacks[*ctx.menu_item_index];
}
} }
}
else if (event.button == input::mouse_button::right)
{
if (ctx.menu_right_callbacks[*ctx.menu_item_index])
else if (event.button == input::mouse_button::right)
{ {
callback = ctx.menu_right_callbacks[*ctx.menu_item_index];
if (ctx.menu_right_callbacks[*ctx.menu_item_index])
{
callback = ctx.menu_right_callbacks[*ctx.menu_item_index];
}
}
// Invoke menu item callback
if (callback)
{
callback();
} }
}
// Invoke menu item callback
if (callback)
{
callback();
} }
} }
) )

+ 18
- 8
src/game/menu.cpp View File

@ -85,29 +85,37 @@ void update_text_tweens(game::context& ctx)
void align_text(game::context& ctx, bool center, bool has_back, float anchor_y) void align_text(game::context& ctx, bool center, bool has_back, float anchor_y)
{ {
const vec2 viewport_size = vec2(ctx.window->get_viewport_size()); const vec2 viewport_size = vec2(ctx.window->get_viewport_size());
const vec2 viewport_center = viewport_size * 0.5f; const vec2 viewport_center = viewport_size * 0.5f;
const float viewport_padding = viewport_size.y() * (1.0f / 9.0f);
// Calculate menu width // Calculate menu width
float m_width = ctx.menu_font.get_glyph_metrics(U'M').width;
float column_spacing = m_width * 2.0f;
const float min_two_column_row_width = m_width * 18.0f;
float menu_width = 0.0f; float menu_width = 0.0f;
float menu_spacing = ctx.menu_font.get_glyph_metrics(U'M').width;
for (auto [name, value]: ctx.menu_item_texts) for (auto [name, value]: ctx.menu_item_texts)
{ {
float row_width = 0.0f; float row_width = 0.0f;
// Add name width to width
// Add name width to row width
const auto& name_bounds = static_cast<const geom::aabb<float>&>(name->get_local_bounds()); const auto& name_bounds = static_cast<const geom::aabb<float>&>(name->get_local_bounds());
row_width += name_bounds.max_point.x() - name_bounds.min_point.x(); row_width += name_bounds.max_point.x() - name_bounds.min_point.x();
if (value) if (value)
{ {
// Add value width to width
//const auto& value_bounds = static_cast<const geom::aabb<float>&>(value->get_local_bounds());
//row_width += value_bounds.max_point.x() - value_bounds.min_point.x();
// Add value width to row width
const auto& value_bounds = static_cast<const geom::aabb<float>&>(value->get_local_bounds());
row_width += value_bounds.max_point.x() - value_bounds.min_point.x();
// Add spacing to row width
row_width += menu_spacing * 8.0f;
// Add column spacing to row width
row_width += column_spacing;
row_width = std::max<float>(min_two_column_row_width, row_width);
} }
menu_width = std::max<float>(menu_width, row_width); menu_width = std::max<float>(menu_width, row_width);
@ -130,7 +138,9 @@ void align_text(game::context& ctx, bool center, bool has_back, float anchor_y)
float x = menu_x; float x = menu_x;
float y = menu_y - ctx.menu_font.get_font_metrics().linespace * i; float y = menu_y - ctx.menu_font.get_font_metrics().linespace * i;
if (has_back && i == ctx.menu_item_texts.size() - 1) if (has_back && i == ctx.menu_item_texts.size() - 1)
y -= ctx.menu_font.get_font_metrics().linespace;
{
y = viewport_padding;// + ctx.menu_font.get_font_metrics().linespace;
}
if (center || i == ctx.menu_item_texts.size() - 1) if (center || i == ctx.menu_item_texts.size() - 1)
{ {

+ 5
- 4
src/game/state/boot.cpp View File

@ -35,6 +35,7 @@
#include "game/strings.hpp" #include "game/strings.hpp"
#include "game/state/boot.hpp" #include "game/state/boot.hpp"
#include "game/state/splash.hpp" #include "game/state/splash.hpp"
#include "game/state/main-menu.hpp"
#include "game/system/astronomy.hpp" #include "game/system/astronomy.hpp"
#include "game/system/atmosphere.hpp" #include "game/system/atmosphere.hpp"
#include "game/system/behavior.hpp" #include "game/system/behavior.hpp"
@ -133,8 +134,8 @@ boot::boot(game::context& ctx, int argc, const char* const* argv):
debug::log::trace("Boot up complete"); debug::log::trace("Boot up complete");
// Push splash state
ctx.state_machine.emplace(new game::state::splash(ctx));
// Push next state
ctx.state_machine.emplace(new game::state::main_menu(ctx, true));
// Enter main loop // Enter main loop
debug::log::trace("Entered main loop"); debug::log::trace("Entered main loop");
@ -847,8 +848,8 @@ void boot::setup_scenes()
float clip_right = viewport_size[0]; float clip_right = viewport_size[0];
float clip_top = 0.0f; float clip_top = 0.0f;
float clip_bottom = viewport_size[1]; float clip_bottom = viewport_size[1];
float clip_near = 0.0f;
float clip_far = 1000.0f;
float clip_near = -100.0f;
float clip_far = 100.0f;
ctx.ui_camera->set_orthographic(clip_left, clip_right, clip_top, clip_bottom, clip_near, clip_far); ctx.ui_camera->set_orthographic(clip_left, clip_right, clip_top, clip_bottom, clip_near, clip_far);
ctx.ui_camera->look_at({0.0f, 0.0f, 0.0f}, {0.0f, 0.0f, -1.0f}, {0.0f, 1.0f, 0.0f}); ctx.ui_camera->look_at({0.0f, 0.0f, 0.0f}, {0.0f, 0.0f, -1.0f}, {0.0f, 1.0f, 0.0f});
ctx.ui_camera->update_tweens(); ctx.ui_camera->update_tweens();

+ 181
- 0
src/game/state/collection-menu.cpp View File

@ -0,0 +1,181 @@
/*
* Copyright (C) 2023 Christopher J. Howard
*
* This file is part of Antkeeper source code.
*
* Antkeeper source code 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.
*
* Antkeeper source code 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 Antkeeper source code. If not, see <http://www.gnu.org/licenses/>.
*/
#include "game/state/collection-menu.hpp"
#include "game/state/main-menu.hpp"
#include "game/controls.hpp"
#include "scene/text.hpp"
#include "debug/log.hpp"
#include "game/menu.hpp"
#include "game/strings.hpp"
#include "utility/hash/fnv1a.hpp"
#include "resources/resource-manager.hpp"
#include "animation/screen-transition.hpp"
#include "animation/ease.hpp"
#include "render/passes/clear-pass.hpp"
using namespace hash::literals;
namespace game {
namespace state {
collection_menu::collection_menu(game::context& ctx):
game::state::base(ctx)
{
debug::log::trace("Entering collection menu state...");
// Enable color buffer clearing in UI pass
ctx.ui_clear_pass->set_cleared_buffers(true, true, false);
// Construct box material
box_material.set_blend_mode(render::blend_mode::translucent);
box_material.set_shader_program(ctx.resource_manager->load<gl::shader_program>("ui-element-untextured.glsl"));
box_material.add_property<float4>("tint")->set_value(float4{0.5f, 0.5f, 0.5f, 1});
box_material.update_tweens();
// Construct box billboard
box_billboard.set_material(&box_material);
// Construct selection material
selection_material.set_blend_mode(render::blend_mode::translucent);
selection_material.set_shader_program(ctx.resource_manager->load<gl::shader_program>("ui-element-untextured.glsl"));
selection_material.add_property<float4>("tint")->set_value(float4{1, 1, 1, 1});
selection_material.update_tweens();
// Construct selection billboard
selection_billboard.set_material(&selection_material);
// Add box and selection billboard to UI scene
ctx.ui_scene->add_object(&box_billboard);
ctx.ui_scene->add_object(&selection_billboard);
row_count = 64;
column_count = 6;
selected_row = 0;
selected_column = 0;
resize_box();
mouse_moved_subscription = ctx.input_manager->get_event_queue().subscribe<input::mouse_moved_event>
(
[&](const auto& event)
{
}
);
mouse_button_pressed_subscription = ctx.input_manager->get_event_queue().subscribe<input::mouse_button_pressed_event>
(
[&](const auto& event)
{
const auto& viewport_size = ctx.window->get_viewport_size();
const float2 mouse_position =
{
static_cast<float>(event.position.x()),
static_cast<float>(viewport_size.y() - event.position.y() + 1)
};
if (box_bounds.contains(mouse_position))
{
int column = static_cast<int>((mouse_position.x() - box_bounds.min.x()) / selection_size);
int row = static_cast<int>((box_bounds.max.y() - mouse_position.y()) / selection_size);
if (column != selected_column || row != selected_row)
{
selected_column = column;
selected_row = row;
selection_billboard.set_translation
(
{
(box_bounds.min.x() + selection_size * 0.5f) + selection_size * selected_column,
(box_bounds.max.y() - selection_size * 0.5f) - selection_size * selected_row ,
0.0f
}
);
selection_billboard.update_tweens();
debug::log::debug("selected colony: ({}, {})", selected_column, selected_row);
}
}
}
);
window_resized_subscription = ctx.window->get_resized_channel().subscribe
(
[&](const auto& event)
{
this->resize_box();
}
);
// Queue enable menu controls
//ctx.function_queue.push(std::bind(game::enable_menu_controls, std::ref(ctx)));
// Fade in from black
ctx.fade_transition->transition(config::title_fade_in_duration, true, ease<float>::out_cubic);
debug::log::trace("Entered collection menu state");
}
collection_menu::~collection_menu()
{
debug::log::trace("Exiting collection menu state...");
// Destruct menu
//game::disable_menu_controls(ctx);
debug::log::trace("Exited collection menu state");
}
void collection_menu::resize_box()
{
const float padding = 64.0f;
const auto viewport_size = float2(ctx.window->get_viewport_size());
box_bounds.min.x() = viewport_size.x() * 0.5f + padding;
box_bounds.max.x() = viewport_size.x() - padding;
selection_size = (box_bounds.max.x() - box_bounds.min.x()) / static_cast<float>(column_count);
box_bounds.max.y() = viewport_size.y() - padding;
box_bounds.min.y() = std::max<float>(padding, box_bounds.max.y() - selection_size * row_count);
const float2 box_size = box_bounds.size();
const float2 box_center = box_bounds.center();
// Resize box
box_billboard.set_scale({box_size.x() * 0.5f, box_size.y() * 0.5f, 1.0f});
box_billboard.set_translation({box_center.x(), box_center.y(), -1.0f});
box_billboard.update_tweens();
// Resize selection
selection_billboard.set_scale({selection_size * 0.5f, selection_size * 0.5f, 1.0f});
selection_billboard.set_translation
(
{
(box_bounds.min.x() + selection_size * 0.5f) + selection_size * selected_column,
(box_bounds.max.y() - selection_size * 0.5f) - selection_size * selected_row,
0.0f
}
);
selection_billboard.update_tweens();
}
} // namespace state
} // namespace game

+ 65
- 0
src/game/state/collection-menu.hpp View File

@ -0,0 +1,65 @@
/*
* Copyright (C) 2023 Christopher J. Howard
*
* This file is part of Antkeeper source code.
*
* Antkeeper source code 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.
*
* Antkeeper source code 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 Antkeeper source code. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef ANTKEEPER_GAME_STATE_COLLECTION_MENU_HPP
#define ANTKEEPER_GAME_STATE_COLLECTION_MENU_HPP
#include "game/state/base.hpp"
#include "event/subscription.hpp"
#include "render/material.hpp"
#include "scene/billboard.hpp"
#include "animation/animation.hpp"
#include "geom/primitive/rectangle.hpp"
#include <memory>
namespace game {
namespace state {
class collection_menu: public game::state::base
{
public:
collection_menu(game::context& ctx);
virtual ~collection_menu();
private:
void resize_box();
render::material selection_material;
scene::billboard selection_billboard;
animation<float> selection_snap_animation;
render::material box_material;
scene::billboard box_billboard;
std::shared_ptr<event::subscription> mouse_moved_subscription;
std::shared_ptr<event::subscription> mouse_button_pressed_subscription;
std::shared_ptr<event::subscription> window_resized_subscription;
geom::primitive::rectangle<float> box_bounds;
int row_count;
int column_count;
int selected_row;
int selected_column;
float selection_size;
};
} // namespace state
} // namespace game
#endif // ANTKEEPER_GAME_STATE_COLLECTION_MENU_HPP

+ 1
- 1
src/game/state/controls-menu.cpp View File

@ -58,7 +58,7 @@ controls_menu::controls_menu(game::context& ctx):
game::menu::update_text_color(ctx); game::menu::update_text_color(ctx);
game::menu::update_text_font(ctx); game::menu::update_text_font(ctx);
game::menu::align_text(ctx);
game::menu::align_text(ctx, true);
game::menu::update_text_tweens(ctx); game::menu::update_text_tweens(ctx);
game::menu::add_text_to_ui(ctx); game::menu::add_text_to_ui(ctx);
game::menu::setup_animations(ctx); game::menu::setup_animations(ctx);

+ 115
- 156
src/game/state/keyboard-config-menu.cpp View File

@ -27,6 +27,8 @@
#include "game/controls.hpp" #include "game/controls.hpp"
#include "game/strings.hpp" #include "game/strings.hpp"
#include "utility/hash/fnv1a.hpp" #include "utility/hash/fnv1a.hpp"
#include <format>
#include <utility>
using namespace hash::literals; using namespace hash::literals;
@ -38,17 +40,14 @@ keyboard_config_menu::keyboard_config_menu(game::context& ctx):
{ {
debug::log::trace("Entering keyboard config menu state..."); debug::log::trace("Entering keyboard config menu state...");
// Add camera control menu items
add_control_item("move_forward");
add_control_item("move_back");
add_control_item("move_left");
add_control_item("move_right");
add_control_item("move_up");
add_control_item("move_down");
// Add application control menu items
add_control_item("toggle_fullscreen");
add_control_item("screenshot");
// Add control menu items
add_control_item(ctx.movement_controls, ctx.move_forward_control, "control_move_forward"_fnv1a32);
add_control_item(ctx.movement_controls, ctx.move_back_control, "control_move_back"_fnv1a32);
add_control_item(ctx.movement_controls, ctx.move_left_control, "control_move_left"_fnv1a32);
add_control_item(ctx.movement_controls, ctx.move_right_control, "control_move_right"_fnv1a32);
add_control_item(ctx.movement_controls, ctx.move_up_control, "control_move_up"_fnv1a32);
add_control_item(ctx.movement_controls, ctx.move_down_control, "control_move_down"_fnv1a32);
add_control_item(ctx.movement_controls, ctx.pause_control, "control_pause"_fnv1a32);
// Construct menu item texts // Construct menu item texts
scene::text* back_text = new scene::text(); scene::text* back_text = new scene::text();
@ -131,105 +130,82 @@ keyboard_config_menu::~keyboard_config_menu()
debug::log::trace("Exited keyboard config menu state..."); debug::log::trace("Exited keyboard config menu state...");
} }
std::string keyboard_config_menu::get_binding_string(input::control* control)
std::string keyboard_config_menu::get_mapping_string(const input::control_map& control_map, const input::control& control)
{ {
std::string binding_string;
/*
auto mappings = ctx.input_event_router->get_mappings(control);
for (input::mapping* mapping: *mappings)
std::string mapping_string;
if (auto key_mappings = control_map.get_key_mappings(control); !key_mappings.empty())
{ {
std::string mapping_string;
const auto& key_mapping = key_mappings.front();
switch (mapping->get_type())
// Get name of scancode string from scancode
std::string scancode_string_name = std::format("scancode_{:02x}", std::to_underlying(key_mapping.scancode));
// Set mapping string to scancode string
mapping_string = get_string(ctx, hash::fnv1a32(scancode_string_name.data(), scancode_string_name.length()));
}
else if (auto mouse_button_mappings = control_map.get_mouse_button_mappings(control); !mouse_button_mappings.empty())
{
const auto& mouse_button_mapping = mouse_button_mappings.front();
switch (mouse_button_mapping.button)
{ {
case input::mapping_type::key:
{
const input::key_mapping* key_mapping = static_cast<const input::key_mapping*>(mapping);
const char* scancode_name = input::keyboard::get_scancode_name(key_mapping->scancode);
mapping_string = scancode_name;
case input::mouse_button::left:
mapping_string = get_string(ctx, "mouse_button_left"_fnv1a32);
break; break;
}
case input::mapping_type::mouse_wheel:
{
const input::mouse_wheel_mapping* wheel_mapping = static_cast<const input::mouse_wheel_mapping*>(mapping);
switch (wheel_mapping->axis)
{
case input::mouse_wheel_axis::negative_x:
mapping_string = (*ctx.strings)["mouse_wheel_left"];
break;
case input::mouse_wheel_axis::positive_x:
mapping_string = (*ctx.strings)["mouse_wheel_right"];
break;
case input::mouse_wheel_axis::negative_y:
mapping_string = (*ctx.strings)["mouse_wheel_down"];
break;
case input::mouse_wheel_axis::positive_y:
mapping_string = (*ctx.strings)["mouse_wheel_up"];
break;
default:
break;
}
case input::mouse_button::middle:
mapping_string = get_string(ctx, "mouse_button_middle"_fnv1a32);
break; break;
}
case input::mapping_type::mouse_button:
{
const input::mouse_button_mapping* button_mapping = static_cast<const input::mouse_button_mapping*>(mapping);
if (button_mapping->button == 1)
{
mapping_string = (*ctx.strings)["mouse_button_left"];
}
else if (button_mapping->button == 2)
{
mapping_string = (*ctx.strings)["mouse_button_middle"];
}
else if (button_mapping->button == 3)
{
mapping_string = (*ctx.strings)["mouse_button_right"];
}
else
{
const std::string& format = (*ctx.strings)["mouse_button_n"];
char buffer[64];
std::snprintf(buffer, 64, format.c_str(), button_mapping->button);
mapping_string = buffer;
}
case input::mouse_button::right:
mapping_string = get_string(ctx, "mouse_button_right"_fnv1a32);
break; break;
}
default: default:
{
std::string format_string = get_string(ctx, "mouse_button_n_format"_fnv1a32);
mapping_string = std::vformat(format_string, std::make_format_args(std::to_underlying(mouse_button_mapping.button)));
break; break;
}
} }
}
else if (auto mouse_scroll_mappings = control_map.get_mouse_scroll_mappings(control); !mouse_scroll_mappings.empty())
{
const auto& mouse_scroll_mapping = mouse_scroll_mappings.front();
if (!mapping_string.empty())
if (mouse_scroll_mapping.axis == input::mouse_scroll_axis::x)
{
if (!mouse_scroll_mapping.direction)
{
mapping_string = get_string(ctx, "mouse_scroll_left"_fnv1a32);
}
else
{
mapping_string = get_string(ctx, "mouse_scroll_right"_fnv1a32);
}
}
else
{ {
if (binding_string.empty())
if (!mouse_scroll_mapping.direction)
{ {
binding_string = mapping_string;
mapping_string = get_string(ctx, "mouse_scroll_up"_fnv1a32);
} }
else else
{ {
binding_string += " " + mapping_string;
mapping_string = get_string(ctx, "mouse_scroll_down"_fnv1a32);
} }
} }
} }
*/
return binding_string;
else
{
mapping_string = get_string(ctx, "control_unmapped"_fnv1a32);
}
return mapping_string;
} }
void keyboard_config_menu::add_control_item(const std::string& control_name)
void keyboard_config_menu::add_control_item(input::control_map& control_map, input::control& control, std::uint32_t control_name_hash)
{ {
// Get pointer to control
//input::control* control = ctx.controls[control_name];
// Construct texts // Construct texts
scene::text* name_text = new scene::text(); scene::text* name_text = new scene::text();
scene::text* value_text = new scene::text(); scene::text* value_text = new scene::text();
@ -237,88 +213,71 @@ void keyboard_config_menu::add_control_item(const std::string& control_name)
// Add texts to list of menu item texts // Add texts to list of menu item texts
ctx.menu_item_texts.push_back({name_text, value_text}); ctx.menu_item_texts.push_back({name_text, value_text});
// Set content of name text
name_text->set_content(control_name);
// Set control name and mapping texts
name_text->set_content(get_string(ctx, control_name_hash));
value_text->set_content(get_mapping_string(control_map, control));
// Set content of value text
//value_text->set_content(get_binding_string( control));
auto select_callback = [this, &ctx = this->ctx, value_text]()
// Callback invoked when an input has been mapped to the control
auto input_mapped_callback = [this, &ctx = this->ctx, control_map = &control_map, control = &control, value_text](const auto& event)
{ {
// Disable menu controls
ctx.function_queue.push(std::bind(game::disable_menu_controls, std::ref(ctx)));
// Remove key mappings, mouse button mappings, and mouse scroll mappings mapped to the control
control_map->remove_mappings(*control, input::mapping_type::key);
control_map->remove_mappings(*control, input::mapping_type::mouse_button);
control_map->remove_mappings(*control, input::mapping_type::mouse_scroll);
// Clear binding string from value text
value_text->set_content(get_string(ctx, "ellipsis"_fnv1a32));
//if (event.mapping.scancode != input::scancode::escape && event.mapping.scancode != input::scancode::backspace)
{
// Map generated input mapping to the control
control_map->add_mapping(*control, event.mapping);
}
// Update control mapping text
value_text->set_content(this->get_mapping_string(*control_map, *control));
game::menu::align_text(ctx); game::menu::align_text(ctx);
game::menu::update_text_tweens(ctx); game::menu::update_text_tweens(ctx);
/*
// Remove keyboard and mouse event mappings from control
ctx.input_event_router->remove_mappings(control, input::mapping_type::key);
ctx.input_event_router->remove_mappings(control, input::mapping_type::mouse_motion);
ctx.input_event_router->remove_mappings(control, input::mapping_type::mouse_wheel);
ctx.input_event_router->remove_mappings(control, input::mapping_type::mouse_button);
// Queue disabling of input mapper re-enabling of menu controls
ctx.function_queue.push
(
[&ctx]()
{
ctx.input_mapper.disconnect();
game::enable_menu_controls(ctx);
}
);
};
// Callback invoked when the control menu item has been selected
auto select_callback = [this, &ctx = this->ctx, control_map = &control_map, control = &control, value_text, input_mapped_callback]()
{
// Set control mapping text to "..."
value_text->set_content(get_string(ctx, "control_mapping"_fnv1a32));
game::menu::align_text(ctx);
game::menu::update_text_tweens(ctx);
// Setup input mapped callbacks
key_mapped_subscription = ctx.input_mapper.get_key_mapped_channel().subscribe
(
input_mapped_callback
);
mouse_button_mapped_subscription = ctx.input_mapper.get_mouse_button_mapped_channel().subscribe
(
input_mapped_callback
);
mouse_scroll_mapped_subscription = ctx.input_mapper.get_mouse_scroll_mapped_channel().subscribe
(
input_mapped_callback
);
// Setup input binding listener
ctx.input_listener->set_callback
// Queue disabling of menu controls and enabling of input mapper
ctx.function_queue.push
( (
[this, &ctx, control, value_text](const event_base& event)
[&]()
{ {
auto id = event.get_event_type_id();
if (id == key_pressed_event::event_type_id)
{
// Map key pressed event to control
const key_pressed_event& key_event = static_cast<const key_pressed_event&>(event);
if (key_event.scancode != input::scancode::escape && key_event.scancode != input::scancode::backspace)
ctx.input_event_router->add_mapping(input::key_mapping(control, key_event.keyboard, key_event.scancode));
}
else if (id == mouse_wheel_scrolled_event::event_type_id)
{
// Map mouse wheel scrolled event to control
const mouse_wheel_scrolled_event& wheel_event = static_cast<const mouse_wheel_scrolled_event&>(event);
input::mouse_wheel_axis axis;
if (wheel_event.x < 0)
axis = input::mouse_wheel_axis::negative_x;
else if (wheel_event.x > 0)
axis = input::mouse_wheel_axis::positive_x;
else if (wheel_event.y < 0)
axis = input::mouse_wheel_axis::negative_y;
else if (wheel_event.y > 0)
axis = input::mouse_wheel_axis::positive_y;
else
return;
ctx.input_event_router->add_mapping(input::mouse_wheel_mapping(control, wheel_event.mouse, axis));
}
else if (id == mouse_button_pressed_event::event_type_id)
{
// Map mouse button pressed event to control
const mouse_button_pressed_event& button_event = static_cast<const mouse_button_pressed_event&>(event);
ctx.input_event_router->add_mapping(input::mouse_button_mapping(control, button_event.mouse, button_event.button));
}
else
{
return;
}
// Update menu text
value_text->set_content(this->get_binding_string(control));
game::menu::align_text(ctx);
game::menu::update_text_tweens(ctx);
// Disable input listener
ctx.input_listener->set_enabled(false);
ctx.input_listener->set_callback(nullptr);
// Queue menu control setup
ctx.function_queue.push(std::bind(game::menu::setup_controls, std::ref(ctx)));
game::disable_menu_controls(ctx);
ctx.input_mapper.connect(ctx.input_manager->get_event_queue());
} }
); );
ctx.input_listener->set_enabled(true);
*/
}; };
// Register menu item callbacks // Register menu item callbacks

+ 10
- 3
src/game/state/keyboard-config-menu.hpp View File

@ -22,7 +22,10 @@
#include "game/state/base.hpp" #include "game/state/base.hpp"
#include "input/control.hpp" #include "input/control.hpp"
#include <string>
#include "input/control-map.hpp"
#include "event/subscription.hpp"
#include <cstdint>
#include <memory>
namespace game { namespace game {
namespace state { namespace state {
@ -34,8 +37,12 @@ public:
virtual ~keyboard_config_menu(); virtual ~keyboard_config_menu();
private: private:
std::string get_binding_string(input::control* control);
void add_control_item(const std::string& control_name);
std::string get_mapping_string(const input::control_map& control_map, const input::control& control);
void add_control_item(input::control_map& control_map, input::control& control, std::uint32_t control_name_hash);
std::shared_ptr<event::subscription> key_mapped_subscription;
std::shared_ptr<event::subscription> mouse_button_mapped_subscription;
std::shared_ptr<event::subscription> mouse_scroll_mapped_subscription;
}; };
} // namespace state } // namespace state

+ 1
- 1
src/game/state/language-menu.cpp View File

@ -181,7 +181,7 @@ language_menu::~language_menu()
game::menu::remove_text_from_ui(ctx); game::menu::remove_text_from_ui(ctx);
game::menu::delete_text(ctx); game::menu::delete_text(ctx);
debug::log::trace("Exited language menu state...");
debug::log::trace("Exited language menu state");
} }
void language_menu::update_text_content() void language_menu::update_text_content()

+ 9
- 6
src/game/state/main-menu.cpp View File

@ -27,14 +27,16 @@
#include "game/component/model.hpp" #include "game/component/model.hpp"
#include "game/component/steering.hpp" #include "game/component/steering.hpp"
#include "game/component/transform.hpp" #include "game/component/transform.hpp"
#include "game/controls.hpp"
#include "game/ecoregion.hpp" #include "game/ecoregion.hpp"
#include "game/menu.hpp" #include "game/menu.hpp"
#include "game/state/collection-menu.hpp"
#include "game/state/extras-menu.hpp" #include "game/state/extras-menu.hpp"
#include "game/state/nuptial-flight.hpp" #include "game/state/nuptial-flight.hpp"
#include "game/state/options-menu.hpp" #include "game/state/options-menu.hpp"
#include "game/strings.hpp" #include "game/strings.hpp"
#include "game/world.hpp" #include "game/world.hpp"
#include "game/controls.hpp"
#include "math/glsl.hpp"
#include "math/projection.hpp" #include "math/projection.hpp"
#include "physics/light/exposure.hpp" #include "physics/light/exposure.hpp"
#include "render/model.hpp" #include "render/model.hpp"
@ -43,7 +45,6 @@
#include "render/passes/sky-pass.hpp" #include "render/passes/sky-pass.hpp"
#include "resources/resource-manager.hpp" #include "resources/resource-manager.hpp"
#include "utility/hash/fnv1a.hpp" #include "utility/hash/fnv1a.hpp"
#include "math/glsl.hpp"
#include <limits> #include <limits>
using namespace hash::literals; using namespace hash::literals;
@ -126,7 +127,7 @@ main_menu::main_menu(game::context& ctx, bool fade_in):
ctx.function_queue.push(std::bind(game::disable_menu_controls, std::ref(ctx))); ctx.function_queue.push(std::bind(game::disable_menu_controls, std::ref(ctx)));
// Create change state function // Create change state function
auto change_state_nuptial_flight = [&ctx]()
auto change_state = [&ctx]()
{ {
// Queue change to nuptial state // Queue change to nuptial state
ctx.function_queue.push ctx.function_queue.push
@ -134,7 +135,8 @@ main_menu::main_menu(game::context& ctx, bool fade_in):
[&ctx]() [&ctx]()
{ {
ctx.state_machine.pop(); ctx.state_machine.pop();
ctx.state_machine.emplace(new game::state::nuptial_flight(ctx));
//ctx.state_machine.emplace(new game::state::nuptial_flight(ctx));
ctx.state_machine.emplace(new game::state::collection_menu(ctx));
} }
); );
}; };
@ -146,8 +148,9 @@ main_menu::main_menu(game::context& ctx, bool fade_in):
game::menu::fade_out(ctx, nullptr); game::menu::fade_out(ctx, nullptr);
// Start fade out to white // Start fade out to white
ctx.fade_transition_color->set_value({1, 1, 1});
ctx.fade_transition->transition(config::new_colony_fade_out_duration, false, ease<float>::out_cubic, false, change_state_nuptial_flight);
//ctx.fade_transition_color->set_value({1, 1, 1});
ctx.fade_transition_color->set_value({0, 0, 0});
ctx.fade_transition->transition(config::new_colony_fade_out_duration, false, ease<float>::out_cubic, false, change_state);
}; };
auto select_options_callback = [this, &ctx]() auto select_options_callback = [this, &ctx]()
{ {

+ 106
- 49
src/input/control-map.cpp View File

@ -46,71 +46,37 @@ void control_map::disconnect()
subscriptions.clear(); subscriptions.clear();
} }
void control_map::add_mapping(control& control, const mapping& mapping)
void control_map::add_mapping(control& control, gamepad_axis_mapping mapping)
{ {
switch (mapping.get_mapping_type())
{
case mapping_type::gamepad_axis:
add_mapping(control, static_cast<const gamepad_axis_mapping&>(mapping));
break;
case mapping_type::gamepad_button:
add_mapping(control, static_cast<const gamepad_button_mapping&>(mapping));
break;
case mapping_type::key:
add_mapping(control, static_cast<const key_mapping&>(mapping));
break;
case mapping_type::mouse_button:
add_mapping(control, static_cast<const mouse_button_mapping&>(mapping));
break;
case mapping_type::mouse_motion:
add_mapping(control, static_cast<const mouse_motion_mapping&>(mapping));
break;
case mapping_type::mouse_scroll:
add_mapping(control, static_cast<const mouse_scroll_mapping&>(mapping));
break;
default:
//std::unreachable();
break;
}
}
void control_map::add_mapping(control& control, gamepad_axis_mapping&& mapping)
{
gamepad_axis_mappings.emplace_back(&control, mapping);
gamepad_axis_mappings.emplace_back(&control, std::move(mapping));
} }
void control_map::add_mapping(control& control, gamepad_button_mapping&& mapping)
void control_map::add_mapping(control& control, gamepad_button_mapping mapping)
{ {
gamepad_button_mappings.emplace_back(&control, mapping);
gamepad_button_mappings.emplace_back(&control, std::move(mapping));
} }
void control_map::add_mapping(control& control, key_mapping&& mapping)
void control_map::add_mapping(control& control, key_mapping mapping)
{ {
key_mappings.emplace_back(&control, mapping);
key_mappings.emplace_back(&control, std::move(mapping));
} }
void control_map::add_mapping(control& control, mouse_button_mapping&& mapping)
void control_map::add_mapping(control& control, mouse_button_mapping mapping)
{ {
mouse_button_mappings.emplace_back(&control, mapping);
mouse_button_mappings.emplace_back(&control, std::move(mapping));
} }
void control_map::add_mapping(control& control, mouse_motion_mapping&& mapping)
void control_map::add_mapping(control& control, mouse_motion_mapping mapping)
{ {
mouse_motion_mappings.emplace_back(&control, mapping);
mouse_motion_mappings.emplace_back(&control, std::move(mapping));
} }
void control_map::add_mapping(control& control, mouse_scroll_mapping&& mapping)
void control_map::add_mapping(control& control, mouse_scroll_mapping mapping)
{ {
mouse_scroll_mappings.emplace_back(&control, mapping);
mouse_scroll_mappings.emplace_back(&control, std::move(mapping));
} }
void control_map::remove_mappings(control& control, mapping_type type)
void control_map::remove_mappings(const control& control, mapping_type type)
{ {
auto predicate = [&](const auto& tuple) -> bool auto predicate = [&](const auto& tuple) -> bool
{ {
@ -149,7 +115,7 @@ void control_map::remove_mappings(control& control, mapping_type type)
} }
} }
void control_map::remove_mappings(control& control)
void control_map::remove_mappings(const control& control)
{ {
auto predicate = [&](const auto& tuple) -> bool auto predicate = [&](const auto& tuple) -> bool
{ {
@ -222,7 +188,8 @@ void control_map::handle_key_pressed(const key_pressed_event& event)
for (const auto& [control, mapping]: key_mappings) for (const auto& [control, mapping]: key_mappings)
{ {
if (mapping.scancode == event.scancode && if (mapping.scancode == event.scancode &&
(!mapping.keyboard || mapping.keyboard == event.keyboard))
(!mapping.keyboard || mapping.keyboard == event.keyboard) &&
(!mapping.modifiers || (mapping.modifiers & event.modifiers)))
{ {
if (!event.repeat) if (!event.repeat)
{ {
@ -307,4 +274,94 @@ void control_map::handle_mouse_button_released(const mouse_button_released_event
} }
} }
std::vector<gamepad_axis_mapping> control_map::get_gamepad_axis_mappings(const control& control) const
{
std::vector<gamepad_axis_mapping> mappings;
for (const auto& [mapped_control, mapping]: gamepad_axis_mappings)
{
if (mapped_control == &control)
{
mappings.emplace_back(mapping);
}
}
return mappings;
}
std::vector<gamepad_button_mapping> control_map::get_gamepad_button_mappings(const control& control) const
{
std::vector<gamepad_button_mapping> mappings;
for (const auto& [mapped_control, mapping]: gamepad_button_mappings)
{
if (mapped_control == &control)
{
mappings.emplace_back(mapping);
}
}
return mappings;
}
std::vector<key_mapping> control_map::get_key_mappings(const control& control) const
{
std::vector<key_mapping> mappings;
for (const auto& [mapped_control, mapping]: key_mappings)
{
if (mapped_control == &control)
{
mappings.emplace_back(mapping);
}
}
return mappings;
}
std::vector<mouse_button_mapping> control_map::get_mouse_button_mappings(const control& control) const
{
std::vector<mouse_button_mapping> mappings;
for (const auto& [mapped_control, mapping]: mouse_button_mappings)
{
if (mapped_control == &control)
{
mappings.emplace_back(mapping);
}
}
return mappings;
}
std::vector<mouse_motion_mapping> control_map::get_mouse_motion_mappings(const control& control) const
{
std::vector<mouse_motion_mapping> mappings;
for (const auto& [mapped_control, mapping]: mouse_motion_mappings)
{
if (mapped_control == &control)
{
mappings.emplace_back(mapping);
}
}
return mappings;
}
std::vector<mouse_scroll_mapping> control_map::get_mouse_scroll_mappings(const control& control) const
{
std::vector<mouse_scroll_mapping> mappings;
for (const auto& [mapped_control, mapping]: mouse_scroll_mappings)
{
if (mapped_control == &control)
{
mappings.emplace_back(mapping);
}
}
return mappings;
}
} // namespace input } // namespace input

+ 50
- 9
src/input/control-map.hpp View File

@ -59,13 +59,12 @@ public:
* @param mapping Input mapping to add. * @param mapping Input mapping to add.
*/ */
/// @{ /// @{
void add_mapping(control& control, const mapping& mapping);
void add_mapping(control& control, gamepad_axis_mapping&& mapping);
void add_mapping(control& control, gamepad_button_mapping&& mapping);
void add_mapping(control& control, key_mapping&& mapping);
void add_mapping(control& control, mouse_button_mapping&& mapping);
void add_mapping(control& control, mouse_motion_mapping&& mapping);
void add_mapping(control& control, mouse_scroll_mapping&& mapping);
void add_mapping(control& control, gamepad_axis_mapping mapping);
void add_mapping(control& control, gamepad_button_mapping mapping);
void add_mapping(control& control, key_mapping mapping);
void add_mapping(control& control, mouse_button_mapping mapping);
void add_mapping(control& control, mouse_motion_mapping mapping);
void add_mapping(control& control, mouse_scroll_mapping mapping);
/// @} /// @}
/** /**
@ -74,20 +73,62 @@ public:
* @param control Control from which input will be unmapped. * @param control Control from which input will be unmapped.
* @param type Type of input mapping to remove. * @param type Type of input mapping to remove.
*/ */
void remove_mappings(control& control, mapping_type type);
void remove_mappings(const control& control, mapping_type type);
/** /**
* Unmaps all input from a control. * Unmaps all input from a control.
* *
* @param control Control from which input will be unmapped. * @param control Control from which input will be unmapped.
*/ */
void remove_mappings(control& control);
void remove_mappings(const control& control);
/** /**
* Unmaps all input from all controls in the control map. * Unmaps all input from all controls in the control map.
*/ */
void remove_mappings(); void remove_mappings();
/**
* Returns all of the gamepad axis mappings associated with a control.
*
* @param control Control with which associated mappings will be returned.
*/
std::vector<gamepad_axis_mapping> get_gamepad_axis_mappings(const control& control) const;
/**
* Returns all of the gamepad button mappings associated with a control.
*
* @param control Control with which associated mappings will be returned.
*/
std::vector<gamepad_button_mapping> get_gamepad_button_mappings(const control& control) const;
/**
* Returns all of the key mappings associated with a control.
*
* @param control Control with which associated mappings will be returned.
*/
std::vector<key_mapping> get_key_mappings(const control& control) const;
/**
* Returns all of the mouse button mappings associated with a control.
*
* @param control Control with which associated mappings will be returned.
*/
std::vector<mouse_button_mapping> get_mouse_button_mappings(const control& control) const;
/**
* Returns all of the mouse motion mappings associated with a control.
*
* @param control Control with which associated mappings will be returned.
*/
std::vector<mouse_motion_mapping> get_mouse_motion_mappings(const control& control) const;
/**
* Returns all of the mouse scroll associated with a control.
*
* @param control Control with which associated mappings will be returned.
*/
std::vector<mouse_scroll_mapping> get_mouse_scroll_mappings(const control& control) const;
private: private:
void handle_gamepad_axis_moved(const gamepad_axis_moved_event& event); void handle_gamepad_axis_moved(const gamepad_axis_moved_event& event);
void handle_gamepad_button_pressed(const gamepad_button_pressed_event& event); void handle_gamepad_button_pressed(const gamepad_button_pressed_event& event);

+ 2
- 2
src/input/gamepad.cpp View File

@ -34,8 +34,8 @@ gamepad::gamepad():
for (int i = 0; i < 6; ++i) for (int i = 0; i < 6; ++i)
{ {
axis_positions[i] = 0.0f; axis_positions[i] = 0.0f;
axis_activation_min[i] = 0.0f;
axis_activation_max[i] = 1.0f;
axis_activation_min[i] = 0.15f;
axis_activation_max[i] = 0.98f;
axis_response_curves[i] = gamepad_response_curve::linear; axis_response_curves[i] = gamepad_response_curve::linear;
} }
} }

+ 3
- 2
src/input/mapping.cpp View File

@ -32,10 +32,11 @@ gamepad_button_mapping::gamepad_button_mapping(input::gamepad* gamepad, gamepad_
button(button) button(button)
{} {}
key_mapping::key_mapping(input::keyboard* keyboard, input::scancode scancode, bool repeat):
key_mapping::key_mapping(input::keyboard* keyboard, input::scancode scancode, bool repeat, std::uint16_t modifiers):
keyboard(keyboard), keyboard(keyboard),
scancode(scancode), scancode(scancode),
repeat(repeat)
repeat(repeat),
modifiers(modifiers)
{} {}
mouse_button_mapping::mouse_button_mapping(input::mouse* mouse, mouse_button button): mouse_button_mapping::mouse_button_mapping(input::mouse* mouse, mouse_button button):

+ 5
- 1
src/input/mapping.hpp View File

@ -136,9 +136,10 @@ public:
* @param keyboard Pointer to the keyboard to map, or `nullptr` if input from any keyboard will be mapped. * @param keyboard Pointer to the keyboard to map, or `nullptr` if input from any keyboard will be mapped.
* @param scancode Scancode of the key to map. * @param scancode Scancode of the key to map.
* @param repeat `false` if the mapping should ignore key repeats, `true` otherwise. * @param repeat `false` if the mapping should ignore key repeats, `true` otherwise.
* @param modifiers Modifier keys bitmask.
*/ */
/// @{ /// @{
key_mapping(input::keyboard* keyboard, input::scancode scancode, bool repeat = false);
key_mapping(input::keyboard* keyboard, input::scancode scancode, bool repeat = false, std::uint16_t modifiers = 0);
key_mapping() = default; key_mapping() = default;
/// @} /// @}
@ -159,6 +160,9 @@ public:
/// `false` if the mapping ignores key repeats, `true` otherwise. /// `false` if the mapping ignores key repeats, `true` otherwise.
bool repeat; bool repeat;
/// Modifier keys bitbask.
std::uint16_t modifiers;
}; };
/** /**

+ 133
- 133
src/input/scancode.hpp View File

@ -41,12 +41,12 @@ enum class scancode: std::uint16_t
d = 0x07, d = 0x07,
e = 0x08, e = 0x08,
f = 0x09, f = 0x09,
g = 0x0A,
h = 0x0B,
i = 0x0C,
j = 0x0D,
k = 0x0E,
l = 0x0F,
g = 0x0a,
h = 0x0b,
i = 0x0c,
j = 0x0d,
k = 0x0e,
l = 0x0f,
m = 0x10, m = 0x10,
n = 0x11, n = 0x11,
o = 0x12, o = 0x12,
@ -57,12 +57,12 @@ enum class scancode: std::uint16_t
t = 0x17, t = 0x17,
u = 0x18, u = 0x18,
v = 0x19, v = 0x19,
w = 0x1A,
x = 0x1B,
y = 0x1C,
z = 0x1D,
digit_1 = 0x1E,
digit_2 = 0x1F,
w = 0x1a,
x = 0x1b,
y = 0x1c,
z = 0x1d,
digit_1 = 0x1e,
digit_2 = 0x1f,
digit_3 = 0x20, digit_3 = 0x20,
digit_4 = 0x21, digit_4 = 0x21,
digit_5 = 0x22, digit_5 = 0x22,
@ -73,12 +73,12 @@ enum class scancode: std::uint16_t
digit_0 = 0x27, digit_0 = 0x27,
enter = 0x28, enter = 0x28,
escape = 0x29, escape = 0x29,
backspace = 0x2A,
tab = 0x2B,
space = 0x2C,
minus = 0x2D,
equal = 0x2E,
left_brace = 0x2F,
backspace = 0x2a,
tab = 0x2b,
space = 0x2c,
minus = 0x2d,
equal = 0x2e,
left_brace = 0x2f,
right_brace = 0x30, right_brace = 0x30,
backslash = 0x31, backslash = 0x31,
non_us_hash = 0x32, non_us_hash = 0x32,
@ -89,12 +89,12 @@ enum class scancode: std::uint16_t
dot = 0x37, dot = 0x37,
slash = 0x38, slash = 0x38,
caps_lock = 0x39, caps_lock = 0x39,
f1 = 0x3A,
f2 = 0x3B,
f3 = 0x3C,
f4 = 0x3D,
f5 = 0x3E,
f6 = 0x3F,
f1 = 0x3a,
f2 = 0x3b,
f3 = 0x3c,
f4 = 0x3d,
f5 = 0x3e,
f6 = 0x3f,
f7 = 0x40, f7 = 0x40,
f8 = 0x41, f8 = 0x41,
f9 = 0x42, f9 = 0x42,
@ -105,12 +105,12 @@ enum class scancode: std::uint16_t
scroll_lock = 0x47, scroll_lock = 0x47,
pause = 0x48, pause = 0x48,
insert = 0x49, insert = 0x49,
home = 0x4A,
page_up = 0x4B,
del = 0x4C,
end = 0x4D,
page_down = 0x4E,
right = 0x4F,
home = 0x4a,
page_up = 0x4b,
del = 0x4c,
end = 0x4d,
page_down = 0x4e,
right = 0x4f,
left = 0x50, left = 0x50,
down = 0x51, down = 0x51,
up = 0x52, up = 0x52,
@ -121,12 +121,12 @@ enum class scancode: std::uint16_t
kp_plus = 0x57, kp_plus = 0x57,
kp_enter = 0x58, kp_enter = 0x58,
kp_1 = 0x59, kp_1 = 0x59,
kp_2 = 0x5A,
kp_3 = 0x5B,
kp_4 = 0x5C,
kp_5 = 0x5D,
kp_6 = 0x5E,
kp_7 = 0x5F,
kp_2 = 0x5a,
kp_3 = 0x5b,
kp_4 = 0x5c,
kp_5 = 0x5d,
kp_6 = 0x5e,
kp_7 = 0x5f,
kp_8 = 0x60, kp_8 = 0x60,
kp_9 = 0x61, kp_9 = 0x61,
kp_0 = 0x62, kp_0 = 0x62,
@ -137,12 +137,12 @@ enum class scancode: std::uint16_t
kp_equal = 0x67, kp_equal = 0x67,
f13 = 0x68, f13 = 0x68,
f14 = 0x69, f14 = 0x69,
f15 = 0x6A,
f16 = 0x6B,
f17 = 0x6C,
f18 = 0x6D,
f19 = 0x6E,
f20 = 0x6F,
f15 = 0x6a,
f16 = 0x6b,
f17 = 0x6c,
f18 = 0x6d,
f19 = 0x6e,
f20 = 0x6f,
f21 = 0x70, f21 = 0x70,
f22 = 0x71, f22 = 0x71,
f23 = 0x72, f23 = 0x72,
@ -153,12 +153,12 @@ enum class scancode: std::uint16_t
select = 0x77, select = 0x77,
stop = 0x78, stop = 0x78,
again = 0x79, again = 0x79,
undo = 0x7A,
cut = 0x7B,
copy = 0x7C,
paste = 0x7D,
find = 0x7E,
mute = 0x7F,
undo = 0x7a,
cut = 0x7b,
copy = 0x7c,
paste = 0x7d,
find = 0x7e,
mute = 0x7f,
volume_up = 0x80, volume_up = 0x80,
volume_down = 0x81, volume_down = 0x81,
locking_caps_lock = 0x82, locking_caps_lock = 0x82,
@ -169,12 +169,12 @@ enum class scancode: std::uint16_t
international_1 = 0x87, international_1 = 0x87,
international_2 = 0x88, international_2 = 0x88,
international_3 = 0x89, international_3 = 0x89,
international_4 = 0x8A,
international_5 = 0x8B,
international_6 = 0x8C,
international_7 = 0x8D,
international_8 = 0x8E,
international_9 = 0x8F,
international_4 = 0x8a,
international_5 = 0x8b,
international_6 = 0x8c,
international_7 = 0x8d,
international_8 = 0x8e,
international_9 = 0x8f,
lang_1 = 0x90, lang_1 = 0x90,
lang_2 = 0x91, lang_2 = 0x91,
lang_3 = 0x92, lang_3 = 0x92,
@ -185,85 +185,85 @@ enum class scancode: std::uint16_t
lang_8 = 0x97, lang_8 = 0x97,
lang_9 = 0x98, lang_9 = 0x98,
alt_erase = 0x99, alt_erase = 0x99,
sys_req = 0x9A,
cancel = 0x9B,
clear = 0x9C,
prior = 0x9D,
return_2 = 0x9E,
separator = 0x9F,
_out = 0xA0,
oper = 0xA1,
clear_again = 0xA2,
cr_sel = 0xA3,
ex_sel = 0xA4,
// reserved = 0xA5,
// reserved = 0xA6,
// reserved = 0xA7,
// reserved = 0xA8,
// reserved = 0xA9,
// reserved = 0xAA,
// reserved = 0xAB,
// reserved = 0xAC,
// reserved = 0xAD,
// reserved = 0xAE,
// reserved = 0xAF,
kp_00 = 0xB0,
kp_000 = 0xB1,
thousands_separator = 0xB2,
decimal_separator = 0xB3,
currency_unit = 0xB4,
currency_sub_unit = 0xB5,
kp_left_paren = 0xB6,
kp_right_paren = 0xB7,
kp_left_brace = 0xB8,
kp_right_brace = 0xB9,
kp_tab = 0xBA,
kp_backspace = 0xBB,
kp_a = 0xBC,
kp_b = 0xBD,
kp_c = 0xBE,
kp_d = 0xBF,
kp_e = 0xC0,
kp_f = 0xC1,
kp_xor = 0xC2,
kp_power = 0xC3,
kp_percent = 0xC4,
kp_less = 0xC5,
kp_greater = 0xC6,
kp_ampersand = 0xC7,
kp_double_ampersand = 0xC8,
kp_vertical_bar = 0xC9,
kp_double_vertical_bar = 0xCA,
kp_colon = 0xCB,
kp_hash = 0xCC,
kp_space = 0xCD,
kp_at = 0xCE,
kp_exclam = 0xCF,
kp_mem_store = 0xD0,
kp_mem_recall = 0xD1,
kp_mem_clear = 0xD2,
kp_mem_add = 0xD3,
kp_mem_subtract = 0xD4,
kp_mem_multiply = 0xD5,
kp_mem_divide = 0xD6,
kp_plus_minus = 0xD7,
kp_clear = 0xD8,
kp_clear_entry = 0xD9,
kp_binary = 0xDA,
kp_octal = 0xDB,
kp_decimal = 0xDC,
kp_hexadecimal = 0xDD,
// reserved = 0xDE,
// reserved = 0xDF,
left_ctrl = 0xE0,
left_shift = 0xE1,
left_alt = 0xE2,
left_gui = 0xE3,
right_ctrl = 0xE4,
right_shift = 0xE5,
right_alt = 0xE6,
right_gui = 0xE7
// reserved = 0xE8-0xFFFF
sys_req = 0x9a,
cancel = 0x9b,
clear = 0x9c,
prior = 0x9d,
return_2 = 0x9e,
separator = 0x9f,
_out = 0xa0,
oper = 0xa1,
clear_again = 0xa2,
cr_sel = 0xa3,
ex_sel = 0xa4,
// reserved = 0xa5,
// reserved = 0xa6,
// reserved = 0xa7,
// reserved = 0xa8,
// reserved = 0xa9,
// reserved = 0xaa,
// reserved = 0xab,
// reserved = 0xac,
// reserved = 0xad,
// reserved = 0xae,
// reserved = 0xaf,
kp_00 = 0xb0,
kp_000 = 0xb1,
thousands_separator = 0xb2,
decimal_separator = 0xb3,
currency_unit = 0xb4,
currency_sub_unit = 0xb5,
kp_left_paren = 0xb6,
kp_right_paren = 0xb7,
kp_left_brace = 0xb8,
kp_right_brace = 0xb9,
kp_tab = 0xba,
kp_backspace = 0xbb,
kp_a = 0xbc,
kp_b = 0xbd,
kp_c = 0xbe,
kp_d = 0xbf,
kp_e = 0xc0,
kp_f = 0xc1,
kp_xor = 0xc2,
kp_power = 0xc3,
kp_percent = 0xc4,
kp_less = 0xc5,
kp_greater = 0xc6,
kp_ampersand = 0xc7,
kp_double_ampersand = 0xc8,
kp_vertical_bar = 0xc9,
kp_double_vertical_bar = 0xca,
kp_colon = 0xcb,
kp_hash = 0xcc,
kp_space = 0xcd,
kp_at = 0xce,
kp_exclam = 0xcf,
kp_mem_store = 0xd0,
kp_mem_recall = 0xd1,
kp_mem_clear = 0xd2,
kp_mem_add = 0xd3,
kp_mem_subtract = 0xd4,
kp_mem_multiply = 0xd5,
kp_mem_divide = 0xd6,
kp_plus_minus = 0xd7,
kp_clear = 0xd8,
kp_clear_entry = 0xd9,
kp_binary = 0xda,
kp_octal = 0xdb,
kp_decimal = 0xdc,
kp_hexadecimal = 0xdd,
// reserved = 0xde,
// reserved = 0xdf,
left_ctrl = 0xe0,
left_shift = 0xe1,
left_alt = 0xe2,
left_gui = 0xe3,
right_ctrl = 0xe4,
right_shift = 0xe5,
right_alt = 0xe6,
right_gui = 0xe7
// reserved = 0xe8-0xffff
}; };
} // namespace input } // namespace input

Loading…
Cancel
Save