diff --git a/src/app/input-manager.hpp b/src/app/input-manager.hpp index 048172b..626ee1c 100644 --- a/src/app/input-manager.hpp +++ b/src/app/input-manager.hpp @@ -50,6 +50,16 @@ public: */ virtual void update() = 0; + /** + * Makes the cursor visible. + */ + virtual void show_cursor() = 0; + + /** + * Makes the cursor invisible. + */ + virtual void hide_cursor() = 0; + /** * Returns the event queue associated with registered input devices. */ diff --git a/src/app/sdl/sdl-input-manager.cpp b/src/app/sdl/sdl-input-manager.cpp index 1693f88..c3b657d 100644 --- a/src/app/sdl/sdl-input-manager.cpp +++ b/src/app/sdl/sdl-input-manager.cpp @@ -298,7 +298,7 @@ void sdl_input_manager::update() debug::log::info("Disconnected gamepad \"{}\"", controller_name); } - + break; } @@ -311,4 +311,20 @@ void sdl_input_manager::update() this->event_queue.flush(); } +void sdl_input_manager::show_cursor() +{ + if (SDL_ShowCursor(SDL_ENABLE) < 0) + { + debug::log::error("Failed to show cursor: \"{}\"", SDL_GetError()); + } +} + +void sdl_input_manager::hide_cursor() +{ + if (SDL_ShowCursor(SDL_DISABLE) < 0) + { + debug::log::error("Failed to hide cursor: \"{}\"", SDL_GetError()); + } +} + } // namespace app diff --git a/src/app/sdl/sdl-input-manager.hpp b/src/app/sdl/sdl-input-manager.hpp index 8457fe9..b4d4e00 100644 --- a/src/app/sdl/sdl-input-manager.hpp +++ b/src/app/sdl/sdl-input-manager.hpp @@ -43,6 +43,8 @@ public: virtual ~sdl_input_manager(); virtual void update(); + virtual void show_cursor(); + virtual void hide_cursor(); private: input::keyboard keyboard; diff --git a/src/game/context.hpp b/src/game/context.hpp index 10322d4..d4cea21 100644 --- a/src/game/context.hpp +++ b/src/game/context.hpp @@ -154,6 +154,12 @@ struct context // Input management and input event handling app::input_manager* input_manager; std::shared_ptr<::event::subscription> application_quit_subscription; + std::shared_ptr<::event::subscription> gamepad_axis_moved_subscription; + std::shared_ptr<::event::subscription> gamepad_button_pressed_subscription; + std::shared_ptr<::event::subscription> mouse_button_pressed_subscription; + std::shared_ptr<::event::subscription> mouse_moved_subscription; + std::shared_ptr<::event::subscription> mouse_scrolled_subscription; + bool gamepad_active; // Localization and internationalization std::uint16_t language_index; diff --git a/src/game/controls.cpp b/src/game/controls.cpp index 1347fd4..16a01a2 100644 --- a/src/game/controls.cpp +++ b/src/game/controls.cpp @@ -181,7 +181,7 @@ void setup_menu_controls(game::context& ctx) // Set activation threshold for menu navigation controls to mitigate drifting gamepad axes auto menu_control_threshold = [](float x) -> bool { - return x > 0.1f; + return x > 0.5f; }; ctx.menu_up_control.set_threshold_function(menu_control_threshold); ctx.menu_down_control.set_threshold_function(menu_control_threshold); diff --git a/src/game/state/boot.cpp b/src/game/state/boot.cpp index 5ba82fc..1310feb 100644 --- a/src/game/state/boot.cpp +++ b/src/game/state/boot.cpp @@ -468,6 +468,65 @@ void boot::setup_input() ctx.closed = true; } ); + + // Gamepad deactivation function + auto deactivate_gamepad = [&ctx = this->ctx](const auto& event) + { + if (ctx.gamepad_active) + { + ctx.gamepad_active = false; + ctx.input_manager->show_cursor(); + } + }; + + // Setup gamepad activation callbacks + ctx.gamepad_axis_moved_subscription = ctx.input_manager->get_event_queue().subscribe + ( + [&](const auto& event) + { + if (!ctx.gamepad_active && std::abs(event.position) > 0.1f) + { + ctx.gamepad_active = true; + ctx.input_manager->hide_cursor(); + } + } + ); + ctx.gamepad_button_pressed_subscription = ctx.input_manager->get_event_queue().subscribe + ( + [&ctx = this->ctx](const auto& event) + { + if (!ctx.gamepad_active) + { + ctx.gamepad_active = true; + ctx.input_manager->hide_cursor(); + } + } + ); + + // Setup gamepad deactivation callbacks + ctx.mouse_button_pressed_subscription = ctx.input_manager->get_event_queue().subscribe + ( + deactivate_gamepad + ); + ctx.mouse_moved_subscription = ctx.input_manager->get_event_queue().subscribe + ( + deactivate_gamepad + ); + ctx.mouse_scrolled_subscription = ctx.input_manager->get_event_queue().subscribe + ( + deactivate_gamepad + ); + + // Activate gamepad if one is connected + if (!ctx.input_manager->get_gamepads().empty()) + { + ctx.gamepad_active = true; + ctx.input_manager->hide_cursor(); + } + else + { + ctx.gamepad_active = false; + } } void boot::load_strings() diff --git a/src/game/state/main-menu.cpp b/src/game/state/main-menu.cpp index 740800c..7c613d4 100644 --- a/src/game/state/main-menu.cpp +++ b/src/game/state/main-menu.cpp @@ -214,6 +214,9 @@ main_menu::main_menu(game::context& ctx, bool fade_in): // Fade to black then quit ctx.fade_transition->transition(config::quit_fade_out_duration, false, ease::out_cubic, false, [&ctx](){ctx.closed=true;}); + + // Quit immediately + //ctx.function_queue.push([&ctx](){ctx.closed=true;}); }; // Build list of menu select callbacks