diff options
| author | Hannes Schulze <haschu0103@outlook.de> | 2025-01-30 16:43:06 +0100 |
|---|---|---|
| committer | Hannes Schulze <haschu0103@outlook.de> | 2025-01-31 00:02:26 +0100 |
| commit | 307e07d6513f9524b7fcab5134494bd175465cd1 (patch) | |
| tree | ce025db2ea998bdcd8980a0ed443083f0daf8d35 /lib/nes/app/input/input-manager.cc | |
| parent | 5959349f341a2380c0c3f41ec40a1e8e0d969d00 (diff) | |
handle input devices in the c++ application
Diffstat (limited to 'lib/nes/app/input/input-manager.cc')
| -rw-r--r-- | lib/nes/app/input/input-manager.cc | 102 |
1 files changed, 102 insertions, 0 deletions
diff --git a/lib/nes/app/input/input-manager.cc b/lib/nes/app/input/input-manager.cc new file mode 100644 index 0000000..1c9db9e --- /dev/null +++ b/lib/nes/app/input/input-manager.cc @@ -0,0 +1,102 @@ +#include "nes/app/input/input-manager.hh" + +namespace nes +{ + namespace + { + class input_device_dummy final : public input_device + { + public: + explicit input_device_dummy() = default; + + static auto get_instance() -> input_device_dummy& + { + static auto res = input_device_dummy{}; + return res; + } + + auto read_key_up() -> bool override { return false; } + auto read_key_down() -> bool override { return false; } + auto read_key_left() -> bool override { return false; } + auto read_key_right() -> bool override { return false; } + auto read_key_a() -> bool override { return false; } + auto read_key_b() -> bool override { return false; } + auto read_key_select() -> bool override { return false; } + auto read_key_start() -> bool override { return false; } + }; + } // namespace + + input_manager::input_manager(input_device_keyboard& keyboard) + : keyboard_{ &keyboard } + { + fill_unassigned_inputs(); + } + + auto input_manager::add_controller(input_device_controller& controller) -> void + { + controllers_.append(controller); + if (controller.is_reliable()) + { + auto const index = controller.get_index(); + if (index != input_device_controller::index::unused) + { + // This controller was previously used and assigned an index -> replace the current device with this + // (known) controller. + auto const i = static_cast<std::size_t>(index); + if (inputs_[i].controller) + { + inputs_[i].controller->set_index(input_device_controller::index::unused); + } + + inputs_[i].controller = &controller; + inputs_[i].device = &controller; + } + + // There may be another free controller now. + fill_unassigned_inputs(); + } + } + + auto input_manager::remove_controller(input_device_controller& controller) -> void + { + controllers_.remove(controller); + fill_unassigned_inputs(); + } + + auto input_manager::fill_unassigned_inputs() -> void + { + auto it = controllers_.begin(); + input_device* fallback = keyboard_; + + for (auto i = std::size_t{ 0 }; i < input_count; ++i) + { + if (inputs_[i].controller != nullptr) { continue; } + + // This input is not assigned -> use the next available controller if available. + while (it != controllers_.end()) + { + auto controller = *it; + if (controller->is_reliable() && controller->get_index() == input_device_controller::index::unused) + { + break; + } + ++it; + } + + if (it != controllers_.end()) + { + // We've found an unused controller -> assign it. + inputs_[i].controller = *it; + inputs_[i].controller->set_index(static_cast<input_device_controller::index>(i)); + inputs_[i].device = *it; + } + else + { + // We're all out of controllers -> fall back to the keyboard (if this is the first missing controller) + // or nothing. + inputs_[i].device = fallback; + fallback = &input_device_dummy::get_instance(); // Only use the keyboard as a fallback once. + } + } + } +} // namespace nes
\ No newline at end of file |
