mirror of
https://github.com/BanjoRecomp/BanjoRecomp
synced 2026-05-24 06:50:47 -04:00
reimplement binding system in new menu
This commit is contained in:
@@ -103,13 +103,7 @@ namespace recomp {
|
||||
{ recomp::InputDevice::Keyboard, "Keyboard" },
|
||||
});
|
||||
|
||||
void start_scanning_input(InputDevice device);
|
||||
void stop_scanning_input();
|
||||
void finish_scanning_input(InputField scanned_field);
|
||||
void cancel_scanning_input();
|
||||
void config_menu_set_cont_or_kb(bool cont_interacted);
|
||||
InputField get_scanned_input();
|
||||
int get_scanned_input_index();
|
||||
|
||||
struct DefaultN64Mappings {
|
||||
std::vector<InputField> a;
|
||||
@@ -257,16 +251,19 @@ namespace recomp {
|
||||
|
||||
namespace recompinput {
|
||||
struct BindingState {
|
||||
bool is_scanning = false;
|
||||
bool found_binding = false;
|
||||
bool active = false;
|
||||
// Designates when binding has been cancelled or completed and the event queue should be purged/ignored.
|
||||
bool skip_events = false;
|
||||
int player_index = -1;
|
||||
recomp::GameInput game_input = recomp::GameInput::COUNT;
|
||||
int binding_index = -1;
|
||||
recomp::InputField new_binding = {};
|
||||
recomp::InputDevice device = recomp::InputDevice::COUNT;
|
||||
};
|
||||
|
||||
void start_scanning_for_binding(int player_index, recomp::GameInput game_input, int binding_index);
|
||||
void start_scanning_for_binding(int player_index, recomp::GameInput game_input, int binding_index, recomp::InputDevice device);
|
||||
void stop_scanning_for_binding();
|
||||
bool is_binding();
|
||||
|
||||
BindingState& get_binding_state();
|
||||
|
||||
|
||||
+59
-46
@@ -50,26 +50,45 @@ static struct {
|
||||
std::list<std::filesystem::path> files_dropped;
|
||||
} DropState;
|
||||
|
||||
std::atomic<recomp::InputDevice> scanning_device = recomp::InputDevice::COUNT;
|
||||
std::atomic<recomp::InputField> scanned_input;
|
||||
|
||||
static recompinput::BindingState binding_state;
|
||||
static recompinput::PlayerAssignmentState player_assignment_state{};
|
||||
|
||||
void recompinput::start_scanning_for_binding(int player_index, recomp::GameInput game_input, int binding_index) {
|
||||
binding_state.is_scanning = true;
|
||||
binding_state.found_binding = false;
|
||||
void recompinput::start_scanning_for_binding(int player_index, recomp::GameInput game_input, int binding_index, recomp::InputDevice device) {
|
||||
binding_state.active = true;
|
||||
binding_state.skip_events = false;
|
||||
binding_state.player_index = player_index;
|
||||
binding_state.game_input = game_input;
|
||||
binding_state.binding_index = binding_index;
|
||||
binding_state.device = device;
|
||||
}
|
||||
|
||||
void recompinput::stop_scanning_for_binding() {
|
||||
binding_state.is_scanning = false;
|
||||
binding_state.found_binding = false;
|
||||
binding_state.player_index = -1;
|
||||
binding_state.game_input = recomp::GameInput::COUNT;
|
||||
binding_state.binding_index = -1;
|
||||
binding_state = recompinput::BindingState{};
|
||||
binding_state.skip_events = true;
|
||||
}
|
||||
|
||||
bool recompinput::is_binding() {
|
||||
return binding_state.active;
|
||||
}
|
||||
|
||||
bool is_controller_being_bound(SDL_JoystickID joystick_id) {
|
||||
if (binding_state.device != recomp::InputDevice::Controller) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (recompinput::get_num_players() == 1) {
|
||||
return true;
|
||||
}
|
||||
|
||||
const auto& player = InputState.assigned_controllers[binding_state.player_index];
|
||||
if (player.controller != nullptr) {
|
||||
SDL_JoystickID assigned_id = SDL_JoystickInstanceID(SDL_GameControllerGetJoystick(player.controller));
|
||||
if (assigned_id == joystick_id) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
recompinput::BindingState& recompinput::get_binding_state() {
|
||||
@@ -176,7 +195,7 @@ void process_player_assignment(SDL_Event* event) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!player_assignment_state.is_assigning) {
|
||||
if (!recompinput::is_player_assignment_active()) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -238,27 +257,17 @@ void process_player_assignment(SDL_Event* event) {
|
||||
}
|
||||
|
||||
void set_scanned_input(recomp::InputField value) {
|
||||
scanning_device.store(recomp::InputDevice::COUNT);
|
||||
scanned_input.store(value);
|
||||
}
|
||||
|
||||
recomp::InputField recomp::get_scanned_input() {
|
||||
recomp::InputField ret = scanned_input.load();
|
||||
scanned_input.store({});
|
||||
return ret;
|
||||
}
|
||||
|
||||
void recomp::start_scanning_input(recomp::InputDevice device) {
|
||||
scanned_input.store({});
|
||||
scanning_device.store(device);
|
||||
}
|
||||
|
||||
void recomp::stop_scanning_input() {
|
||||
scanning_device.store(recomp::InputDevice::COUNT);
|
||||
recomp::set_input_binding(
|
||||
recomp::get_input_profile_for_player(binding_state.player_index, binding_state.device),
|
||||
binding_state.game_input,
|
||||
binding_state.binding_index,
|
||||
value
|
||||
);
|
||||
recompinput::stop_scanning_for_binding();
|
||||
}
|
||||
|
||||
void queue_if_enabled(SDL_Event* event) {
|
||||
if (!recomp::all_input_disabled()) {
|
||||
if (!recomp::all_input_disabled() && !binding_state.skip_events) {
|
||||
recompui::queue_event(*event);
|
||||
}
|
||||
}
|
||||
@@ -297,11 +306,11 @@ bool sdl_event_filter(void* userdata, SDL_Event* event) {
|
||||
) {
|
||||
recompui::toggle_fullscreen();
|
||||
}
|
||||
if (scanning_device != recomp::InputDevice::COUNT) {
|
||||
if (recompinput::is_binding()) {
|
||||
if (keyevent->keysym.scancode == SDL_Scancode::SDL_SCANCODE_ESCAPE) {
|
||||
recomp::cancel_scanning_input();
|
||||
recompinput::stop_scanning_for_binding();
|
||||
}
|
||||
else if (scanning_device == recomp::InputDevice::Keyboard) {
|
||||
else if (binding_state.device == recomp::InputDevice::Keyboard) {
|
||||
set_scanned_input({ recomp::InputType::Keyboard, keyevent->keysym.scancode });
|
||||
}
|
||||
}
|
||||
@@ -367,21 +376,21 @@ bool sdl_event_filter(void* userdata, SDL_Event* event) {
|
||||
queue_if_enabled(event);
|
||||
break;
|
||||
case SDL_EventType::SDL_CONTROLLERBUTTONDOWN:
|
||||
if (scanning_device != recomp::InputDevice::COUNT) {
|
||||
if (recompinput::is_binding() && is_controller_being_bound(event->cbutton.which)) {
|
||||
// TODO: Needs the controller profile index.
|
||||
auto menuToggleBinding0 = recomp::get_input_binding(0, recomp::GameInput::TOGGLE_MENU, 0);
|
||||
auto menuToggleBinding1 = recomp::get_input_binding(0, recomp::GameInput::TOGGLE_MENU, 1);
|
||||
// note - magic number: 0 is InputType::None
|
||||
if ((menuToggleBinding0.input_type != recomp::InputType::None && event->cbutton.button == menuToggleBinding0.input_id) ||
|
||||
(menuToggleBinding1.input_type != recomp::InputType::None && event->cbutton.button == menuToggleBinding1.input_id)) {
|
||||
recomp::cancel_scanning_input();
|
||||
recompinput::stop_scanning_for_binding();
|
||||
}
|
||||
else if (scanning_device == recomp::InputDevice::Controller) {
|
||||
else if (binding_state.device == recomp::InputDevice::Controller) {
|
||||
SDL_ControllerButtonEvent* button_event = &event->cbutton;
|
||||
auto scanned_input_index = recomp::get_scanned_input_index();
|
||||
if ((scanned_input_index == static_cast<int>(recomp::GameInput::TOGGLE_MENU) ||
|
||||
scanned_input_index == static_cast<int>(recomp::GameInput::ACCEPT_MENU) ||
|
||||
scanned_input_index == static_cast<int>(recomp::GameInput::APPLY_MENU)) && (
|
||||
recomp::GameInput scanning_game_input = binding_state.game_input;
|
||||
if ((scanning_game_input == recomp::GameInput::TOGGLE_MENU ||
|
||||
scanning_game_input == recomp::GameInput::ACCEPT_MENU ||
|
||||
scanning_game_input == recomp::GameInput::APPLY_MENU) && (
|
||||
button_event->button == SDL_GameControllerButton::SDL_CONTROLLER_BUTTON_DPAD_UP ||
|
||||
button_event->button == SDL_GameControllerButton::SDL_CONTROLLER_BUTTON_DPAD_DOWN ||
|
||||
button_event->button == SDL_GameControllerButton::SDL_CONTROLLER_BUTTON_DPAD_LEFT ||
|
||||
@@ -397,11 +406,11 @@ bool sdl_event_filter(void* userdata, SDL_Event* event) {
|
||||
}
|
||||
break;
|
||||
case SDL_EventType::SDL_CONTROLLERAXISMOTION:
|
||||
if (scanning_device == recomp::InputDevice::Controller) {
|
||||
auto scanned_input_index = recomp::get_scanned_input_index();
|
||||
if (scanned_input_index == static_cast<int>(recomp::GameInput::TOGGLE_MENU) ||
|
||||
scanned_input_index == static_cast<int>(recomp::GameInput::ACCEPT_MENU) ||
|
||||
scanned_input_index == static_cast<int>(recomp::GameInput::APPLY_MENU)) {
|
||||
if (is_controller_being_bound(event->caxis.which)) {
|
||||
recomp::GameInput scanning_game_input = binding_state.game_input;
|
||||
if (scanning_game_input == recomp::GameInput::TOGGLE_MENU ||
|
||||
scanning_game_input == recomp::GameInput::ACCEPT_MENU ||
|
||||
scanning_game_input == recomp::GameInput::APPLY_MENU) {
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -518,6 +527,8 @@ void recomp::handle_events() {
|
||||
SDL_SetRelativeMouseMode(cursor_locked ? SDL_TRUE : SDL_FALSE);
|
||||
}
|
||||
|
||||
binding_state.skip_events = false;
|
||||
|
||||
if (!started && ultramodern::is_game_started()) {
|
||||
started = true;
|
||||
recompui::process_game_started();
|
||||
@@ -952,7 +963,9 @@ bool recomp::game_input_disabled() {
|
||||
|
||||
bool recomp::all_input_disabled() {
|
||||
// Disable all input if an input is being polled.
|
||||
return scanning_device != recomp::InputDevice::COUNT || recompinput::is_player_assignment_active();
|
||||
return
|
||||
recompinput::is_player_assignment_active() ||
|
||||
recompinput::is_binding();
|
||||
}
|
||||
|
||||
bool recomp::get_single_controller_mode() {
|
||||
|
||||
@@ -105,35 +105,6 @@ static bool cont_active = true;
|
||||
|
||||
static recomp::InputDevice cur_device = recomp::InputDevice::Controller;
|
||||
|
||||
int recomp::get_scanned_input_index() {
|
||||
return scanned_input_index;
|
||||
}
|
||||
|
||||
void recomp::finish_scanning_input(recomp::InputField scanned_field) {
|
||||
// TODO: Needs the profile index.
|
||||
recomp::set_input_binding(0, static_cast<recomp::GameInput>(scanned_input_index), scanned_binding_index, scanned_field);
|
||||
scanned_input_index = -1;
|
||||
scanned_binding_index = -1;
|
||||
controls_model_handle.DirtyVariable("inputs");
|
||||
controls_model_handle.DirtyVariable("active_binding_input");
|
||||
controls_model_handle.DirtyVariable("active_binding_slot");
|
||||
nav_help_model_handle.DirtyVariable("nav_help__accept");
|
||||
nav_help_model_handle.DirtyVariable("nav_help__exit");
|
||||
graphics_model_handle.DirtyVariable("gfx_help__apply");
|
||||
}
|
||||
|
||||
void recomp::cancel_scanning_input() {
|
||||
recomp::stop_scanning_input();
|
||||
scanned_input_index = -1;
|
||||
scanned_binding_index = -1;
|
||||
controls_model_handle.DirtyVariable("inputs");
|
||||
controls_model_handle.DirtyVariable("active_binding_input");
|
||||
controls_model_handle.DirtyVariable("active_binding_slot");
|
||||
nav_help_model_handle.DirtyVariable("nav_help__accept");
|
||||
nav_help_model_handle.DirtyVariable("nav_help__exit");
|
||||
graphics_model_handle.DirtyVariable("gfx_help__apply");
|
||||
}
|
||||
|
||||
void recomp::config_menu_set_cont_or_kb(bool cont_interacted) {
|
||||
if (cont_active != cont_interacted) {
|
||||
cont_active = cont_interacted;
|
||||
@@ -638,7 +609,6 @@ public:
|
||||
[](Rml::DataModelHandle model_handle, Rml::Event& event, const Rml::VariantList& inputs) {
|
||||
scanned_input_index = inputs.at(0).Get<size_t>();
|
||||
scanned_binding_index = inputs.at(1).Get<size_t>();
|
||||
recomp::start_scanning_input(cur_device);
|
||||
model_handle.DirtyVariable("active_binding_input");
|
||||
model_handle.DirtyVariable("active_binding_slot");
|
||||
});
|
||||
|
||||
@@ -95,6 +95,8 @@ GameInputRow::~GameInputRow() {
|
||||
|
||||
void GameInputRow::update_bindings(BindingList &new_bindings) {
|
||||
for (size_t i = 0; i < new_bindings.size(); i++) {
|
||||
binding_buttons[i]->set_is_binding(false);
|
||||
|
||||
// skip update if no changes
|
||||
if (
|
||||
new_bindings[i].input_id == bindings[i].input_id &&
|
||||
@@ -103,7 +105,6 @@ void GameInputRow::update_bindings(BindingList &new_bindings) {
|
||||
}
|
||||
|
||||
binding_buttons[i]->set_binding(new_bindings[i].to_string());
|
||||
binding_buttons[i]->set_is_binding(false);
|
||||
bindings[i] = new_bindings[i];
|
||||
}
|
||||
}
|
||||
@@ -127,10 +128,8 @@ void GameInputRow::process_event(const Event &e) {
|
||||
ConfigPageControls::ConfigPageControls(
|
||||
Element *parent,
|
||||
int num_players,
|
||||
std::vector<GameInputContext> game_input_contexts,
|
||||
on_player_bind_callback on_player_bind
|
||||
std::vector<GameInputContext> game_input_contexts
|
||||
) : ConfigPage(parent) {
|
||||
this->on_player_bind = on_player_bind;
|
||||
this->game_input_contexts = game_input_contexts;
|
||||
this->num_players = num_players;
|
||||
this->multiplayer_enabled = num_players > 1;
|
||||
@@ -147,6 +146,10 @@ ConfigPageControls::ConfigPageControls(
|
||||
void ConfigPageControls::process_event(const Event &e) {
|
||||
switch (e.type) {
|
||||
case EventType::Update:
|
||||
if (awaiting_binding && !recompinput::is_binding()) {
|
||||
awaiting_binding = false;
|
||||
update_control_mappings();
|
||||
}
|
||||
if (last_update_index != update_index) {
|
||||
last_update_index = update_index;
|
||||
render_all();
|
||||
@@ -397,7 +400,17 @@ ConfigPageControls::~ConfigPageControls() {
|
||||
}
|
||||
|
||||
void ConfigPageControls::on_bind_click(recompinput::GameInput game_input, int input_index) {
|
||||
on_player_bind(this->selected_player, game_input, input_index);
|
||||
recompinput::InputDevice device;
|
||||
if (multiplayer_enabled) {
|
||||
device = recompinput::get_assigned_player_input_device(this->selected_player);
|
||||
} else {
|
||||
device = single_player_show_keyboard_mappings
|
||||
? recomp::InputDevice::Keyboard
|
||||
: recomp::InputDevice::Controller;
|
||||
}
|
||||
|
||||
recompinput::start_scanning_for_binding(this->selected_player, game_input, input_index, device);
|
||||
awaiting_binding = true;
|
||||
}
|
||||
|
||||
void ConfigPageControls::set_selected_player(int player) {
|
||||
|
||||
@@ -77,6 +77,8 @@ protected:
|
||||
|
||||
bool single_player_show_keyboard_mappings = false;
|
||||
|
||||
bool awaiting_binding = false;
|
||||
|
||||
std::vector<GameInputContext> game_input_contexts;
|
||||
PlayerBindings game_input_bindings;
|
||||
|
||||
@@ -105,8 +107,7 @@ public:
|
||||
ConfigPageControls(
|
||||
Element *parent,
|
||||
int num_players,
|
||||
std::vector<GameInputContext> game_input_contexts,
|
||||
on_player_bind_callback on_player_bind
|
||||
std::vector<GameInputContext> game_input_contexts
|
||||
);
|
||||
virtual ~ConfigPageControls();
|
||||
|
||||
|
||||
@@ -20,22 +20,6 @@ static std::vector<struct GameInputContext> temp_game_input_contexts = {
|
||||
};
|
||||
#undef DEFINE_INPUT
|
||||
|
||||
struct BindingInfo {
|
||||
int player_index;
|
||||
recompinput::GameInput game_input;
|
||||
int binding_index;
|
||||
bool is_scanning = false;
|
||||
};
|
||||
|
||||
static BindingInfo temp_binding_info = { 0, recompinput::GameInput::COUNT, 0 };
|
||||
|
||||
static void temp_on_bind_player(int player_index, recompinput::GameInput game_input, int binding_index) {
|
||||
temp_binding_info.player_index = player_index;
|
||||
temp_binding_info.game_input = game_input;
|
||||
temp_binding_info.binding_index = binding_index;
|
||||
temp_binding_info.is_scanning = true;
|
||||
}
|
||||
|
||||
ElementConfigPageControls::ElementConfigPageControls(const Rml::String& tag) : Rml::Element(tag) {
|
||||
SetProperty(Rml::PropertyId::Display, Rml::Style::Display::Block);
|
||||
SetProperty("width", "100%");
|
||||
@@ -47,8 +31,7 @@ ElementConfigPageControls::ElementConfigPageControls(const Rml::String& tag) : R
|
||||
controls_page = context.create_element<ConfigPageControls>(
|
||||
&this_compat,
|
||||
recompinput::get_num_players(),
|
||||
temp_game_input_contexts,
|
||||
temp_on_bind_player
|
||||
temp_game_input_contexts
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
+3
-6
@@ -584,6 +584,8 @@ void draw_hook(RT64::RenderCommandList* command_list, RT64::RenderFramebuffer* s
|
||||
static clock::time_point next_repeat_time = {};
|
||||
static int latest_controller_key_pressed = SDLK_UNKNOWN;
|
||||
|
||||
bool all_input_is_disabled = recomp::all_input_disabled();
|
||||
|
||||
while (recompui::try_deque_event(cur_event)) {
|
||||
bool context_capturing_input = recompui::is_context_capturing_input();
|
||||
bool context_capturing_mouse = recompui::is_context_capturing_mouse();
|
||||
@@ -596,7 +598,7 @@ void draw_hook(RT64::RenderCommandList* command_list, RT64::RenderFramebuffer* s
|
||||
}
|
||||
}
|
||||
|
||||
if (!recomp::all_input_disabled()) {
|
||||
if (!all_input_is_disabled) {
|
||||
bool is_mouse_input = false;
|
||||
// Implement some additional behavior for specific events on top of what RmlUi normally does with them.
|
||||
switch (cur_event.type) {
|
||||
@@ -747,11 +749,6 @@ void draw_hook(RT64::RenderCommandList* command_list, RT64::RenderFramebuffer* s
|
||||
}
|
||||
recomp::config_menu_set_cont_or_kb(ui_state->cont_is_active);
|
||||
|
||||
recomp::InputField scanned_field = recomp::get_scanned_input();
|
||||
if (scanned_field != recomp::InputField{}) {
|
||||
recomp::finish_scanning_input(scanned_field);
|
||||
}
|
||||
|
||||
ui_state->update_primary_input(mouse_moved, non_mouse_interacted);
|
||||
ui_state->update_focus(mouse_moved, non_mouse_interacted);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user