mirror of
https://github.com/Mr-Wiseguy/Zelda64Recomp.git
synced 2025-04-07 05:56:53 +02:00
Implement controlling input capturing for mod UI contexts
This commit is contained in:
parent
7261c055a1
commit
2dffaf6148
@ -49,7 +49,8 @@ namespace recompui {
|
||||
void hide_context(ContextId context);
|
||||
void hide_all_contexts();
|
||||
bool is_context_shown(ContextId context);
|
||||
bool is_context_taking_input();
|
||||
bool is_context_capturing_input();
|
||||
bool is_context_capturing_mouse();
|
||||
bool is_any_context_shown();
|
||||
|
||||
ContextId get_launcher_context_id();
|
||||
|
@ -103,7 +103,7 @@ bool sdl_event_filter(void* userdata, SDL_Event* event) {
|
||||
SDL_KeyboardEvent* keyevent = &event->key;
|
||||
|
||||
// Skip repeated events when not in the menu
|
||||
if (!recompui::is_context_taking_input() &&
|
||||
if (!recompui::is_context_capturing_input() &&
|
||||
event->key.repeat) {
|
||||
break;
|
||||
}
|
||||
@ -713,7 +713,7 @@ void recomp::set_right_analog_suppressed(bool suppressed) {
|
||||
|
||||
bool recomp::game_input_disabled() {
|
||||
// Disable input if any menu that blocks input is open.
|
||||
return recompui::is_context_taking_input();
|
||||
return recompui::is_context_capturing_input();
|
||||
}
|
||||
|
||||
bool recomp::all_input_disabled() {
|
||||
|
@ -34,6 +34,8 @@ namespace recompui {
|
||||
Element root_element;
|
||||
std::vector<Element*> loose_elements;
|
||||
std::unordered_set<ResourceId> to_update;
|
||||
bool captures_input = true;
|
||||
bool captures_mouse = true;
|
||||
Context(Rml::ElementDocument* document) : document(document), root_element(document) {}
|
||||
};
|
||||
} // namespace recompui
|
||||
@ -371,6 +373,47 @@ void recompui::ContextId::process_updates() {
|
||||
}
|
||||
}
|
||||
|
||||
bool recompui::ContextId::captures_input() {
|
||||
std::lock_guard lock{ context_state.all_contexts_lock };
|
||||
|
||||
Context* ctx = context_state.all_contexts.get(context_slotmap::key{ slot_id });
|
||||
if (ctx == nullptr) {
|
||||
return false;
|
||||
}
|
||||
return ctx->captures_input;
|
||||
|
||||
}
|
||||
|
||||
bool recompui::ContextId::captures_mouse() {
|
||||
std::lock_guard lock{ context_state.all_contexts_lock };
|
||||
|
||||
Context* ctx = context_state.all_contexts.get(context_slotmap::key{ slot_id });
|
||||
if (ctx == nullptr) {
|
||||
return false;
|
||||
}
|
||||
return ctx->captures_mouse;
|
||||
}
|
||||
|
||||
void recompui::ContextId::set_captures_input(bool captures_input) {
|
||||
std::lock_guard lock{ context_state.all_contexts_lock };
|
||||
|
||||
Context* ctx = context_state.all_contexts.get(context_slotmap::key{ slot_id });
|
||||
if (ctx == nullptr) {
|
||||
return;
|
||||
}
|
||||
ctx->captures_input = captures_input;
|
||||
}
|
||||
|
||||
void recompui::ContextId::set_captures_mouse(bool captures_mouse) {
|
||||
std::lock_guard lock{ context_state.all_contexts_lock };
|
||||
|
||||
Context* ctx = context_state.all_contexts.get(context_slotmap::key{ slot_id });
|
||||
if (ctx == nullptr) {
|
||||
return;
|
||||
}
|
||||
ctx->captures_mouse = captures_mouse;
|
||||
}
|
||||
|
||||
recompui::Style* recompui::ContextId::add_resource_impl(std::unique_ptr<Style>&& resource) {
|
||||
// Ensure a context is currently opened by this thread.
|
||||
if (opened_context_id == ContextId::null()) {
|
||||
|
@ -47,8 +47,11 @@ namespace recompui {
|
||||
|
||||
static constexpr ContextId null() { return ContextId{ .slot_id = uint32_t(-1) }; }
|
||||
|
||||
// TODO
|
||||
bool takes_input() { return true; }
|
||||
bool captures_input();
|
||||
bool captures_mouse();
|
||||
|
||||
void set_captures_input(bool captures_input);
|
||||
void set_captures_mouse(bool captures_input);
|
||||
};
|
||||
|
||||
ContextId create_context(const std::filesystem::path& path);
|
||||
|
@ -138,6 +138,20 @@ void recompui_hide_context(uint8_t* rdram, recomp_context* ctx) {
|
||||
recompui::hide_context(ui_context);
|
||||
}
|
||||
|
||||
void recompui_set_context_captures_input(uint8_t* rdram, recomp_context* ctx) {
|
||||
ContextId ui_context = get_context(rdram, ctx);
|
||||
bool captures_input = _arg<1, int>(rdram, ctx) != 0;
|
||||
|
||||
ui_context.set_captures_input(captures_input);
|
||||
}
|
||||
|
||||
void recompui_set_context_captures_mouse(uint8_t* rdram, recomp_context* ctx) {
|
||||
ContextId ui_context = get_context(rdram, ctx);
|
||||
bool captures_mouse = _arg<1, int>(rdram, ctx) != 0;
|
||||
|
||||
ui_context.set_captures_mouse(captures_mouse);
|
||||
}
|
||||
|
||||
// Resources
|
||||
void recompui_create_style(uint8_t* rdram, recomp_context* ctx) {
|
||||
ContextId ui_context = get_context(rdram, ctx);
|
||||
@ -780,6 +794,8 @@ void recompui::register_ui_exports() {
|
||||
REGISTER_FUNC(recompui_context_root);
|
||||
REGISTER_FUNC(recompui_show_context);
|
||||
REGISTER_FUNC(recompui_hide_context);
|
||||
REGISTER_FUNC(recompui_set_context_captures_input);
|
||||
REGISTER_FUNC(recompui_set_context_captures_mouse);
|
||||
REGISTER_FUNC(recompui_create_style);
|
||||
REGISTER_FUNC(recompui_create_element);
|
||||
REGISTER_FUNC(recompui_create_label);
|
||||
|
@ -151,7 +151,6 @@ Rml::Element* find_autofocus_element(Rml::Element* start) {
|
||||
struct ContextDetails {
|
||||
recompui::ContextId context;
|
||||
Rml::ElementDocument* document;
|
||||
bool takes_input;
|
||||
};
|
||||
|
||||
class UIState {
|
||||
@ -266,7 +265,7 @@ public:
|
||||
recompui::set_cursor_visible(mouse_is_active);
|
||||
}
|
||||
|
||||
Rml::ElementDocument* current_document = top_input_document();
|
||||
Rml::ElementDocument* current_document = top_mouse_document();
|
||||
if (current_document == nullptr) {
|
||||
return;
|
||||
}
|
||||
@ -286,7 +285,7 @@ public:
|
||||
}
|
||||
|
||||
void update_focus(bool mouse_moved, bool non_mouse_interacted) {
|
||||
Rml::ElementDocument* current_document = top_input_document();
|
||||
Rml::ElementDocument* current_document = top_mouse_document();
|
||||
|
||||
if (current_document == nullptr) {
|
||||
return;
|
||||
@ -341,12 +340,10 @@ public:
|
||||
recompui::message_box("Attemped to show the same context twice");
|
||||
assert(false);
|
||||
}
|
||||
bool takes_input = context.takes_input();
|
||||
Rml::ElementDocument* document = context.get_document();
|
||||
shown_contexts.push_back(ContextDetails{
|
||||
.context = context,
|
||||
.document = document,
|
||||
.takes_input = takes_input
|
||||
.document = document
|
||||
});
|
||||
|
||||
// auto& on_show = context.on_show;
|
||||
@ -383,8 +380,12 @@ public:
|
||||
return std::find_if(shown_contexts.begin(), shown_contexts.end(), [context](auto& c){ return c.context == context; }) != shown_contexts.end();
|
||||
}
|
||||
|
||||
bool is_context_taking_input() {
|
||||
return std::find_if(shown_contexts.begin(), shown_contexts.end(), [](auto& c){ return c.takes_input; }) != shown_contexts.end();
|
||||
bool is_context_capturing_input() {
|
||||
return std::find_if(shown_contexts.begin(), shown_contexts.end(), [](auto& c){ return c.context.captures_input(); }) != shown_contexts.end();
|
||||
}
|
||||
|
||||
bool is_context_capturing_mouse() {
|
||||
return std::find_if(shown_contexts.begin(), shown_contexts.end(), [](auto& c){ return c.context.captures_mouse(); }) != shown_contexts.end();
|
||||
}
|
||||
|
||||
bool is_any_context_shown() {
|
||||
@ -394,7 +395,17 @@ public:
|
||||
Rml::ElementDocument* top_input_document() {
|
||||
// Iterate backwards and stop at the first context that takes input.
|
||||
for (auto it = shown_contexts.rbegin(); it != shown_contexts.rend(); it++) {
|
||||
if (it->takes_input) {
|
||||
if (it->context.captures_input()) {
|
||||
return it->document;
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
Rml::ElementDocument* top_mouse_document() {
|
||||
// Iterate backwards and stop at the first context that takes input.
|
||||
for (auto it = shown_contexts.rbegin(); it != shown_contexts.rend(); it++) {
|
||||
if (it->context.captures_mouse()) {
|
||||
return it->document;
|
||||
}
|
||||
}
|
||||
@ -556,8 +567,10 @@ void draw_hook(RT64::RenderCommandList* command_list, RT64::RenderFramebuffer* s
|
||||
bool config_was_open = recompui::is_context_shown(recompui::get_config_context_id()) || recompui::is_context_shown(recompui::get_config_sub_menu_context_id());
|
||||
|
||||
while (recompui::try_deque_event(cur_event)) {
|
||||
bool context_taking_input = recompui::is_context_taking_input();
|
||||
bool context_capturing_input = recompui::is_context_capturing_input();
|
||||
bool context_capturing_mouse = recompui::is_context_capturing_mouse();
|
||||
if (!recomp::all_input_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) {
|
||||
case SDL_EventType::SDL_MOUSEMOTION: {
|
||||
@ -582,11 +595,17 @@ void draw_hook(RT64::RenderCommandList* command_list, RT64::RenderFramebuffer* s
|
||||
case SDL_EventType::SDL_MOUSEBUTTONDOWN:
|
||||
mouse_moved = true;
|
||||
mouse_clicked = true;
|
||||
is_mouse_input = true;
|
||||
break;
|
||||
|
||||
case SDL_EventType::SDL_MOUSEBUTTONUP:
|
||||
case SDL_EventType::SDL_MOUSEWHEEL:
|
||||
is_mouse_input = true;
|
||||
break;
|
||||
|
||||
case SDL_EventType::SDL_CONTROLLERBUTTONDOWN: {
|
||||
int rml_key = cont_button_to_key(cur_event.cbutton);
|
||||
if (context_taking_input && rml_key) {
|
||||
if (context_capturing_input && rml_key) {
|
||||
ui_state->context->ProcessKeyDown(RmlSDL::ConvertKey(rml_key), 0);
|
||||
}
|
||||
non_mouse_interacted = true;
|
||||
@ -619,7 +638,7 @@ void draw_hook(RT64::RenderCommandList* command_list, RT64::RenderFramebuffer* s
|
||||
*await_stick_return = true;
|
||||
non_mouse_interacted = true;
|
||||
int rml_key = cont_axis_to_key(cur_event.caxis, axis_value);
|
||||
if (context_taking_input && rml_key) {
|
||||
if (context_capturing_input && rml_key) {
|
||||
ui_state->context->ProcessKeyDown(RmlSDL::ConvertKey(rml_key), 0);
|
||||
}
|
||||
}
|
||||
@ -632,8 +651,16 @@ void draw_hook(RT64::RenderCommandList* command_list, RT64::RenderFramebuffer* s
|
||||
break;
|
||||
}
|
||||
|
||||
if (context_taking_input) {
|
||||
RmlSDL::InputEventHandler(ui_state->context, cur_event);
|
||||
// Send the event to RmlUi if this type of event is being captured.
|
||||
if (is_mouse_input) {
|
||||
if (context_capturing_mouse) {
|
||||
RmlSDL::InputEventHandler(ui_state->context, cur_event);
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (context_capturing_input) {
|
||||
RmlSDL::InputEventHandler(ui_state->context, cur_event);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -753,14 +780,24 @@ bool recompui::is_context_shown(ContextId context) {
|
||||
return ui_state->is_context_shown(context);
|
||||
}
|
||||
|
||||
bool recompui::is_context_taking_input() {
|
||||
bool recompui::is_context_capturing_input() {
|
||||
std::lock_guard lock{ui_state_mutex};
|
||||
|
||||
if (!ui_state) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return ui_state->is_context_taking_input();
|
||||
return ui_state->is_context_capturing_input();
|
||||
}
|
||||
|
||||
bool recompui::is_context_capturing_mouse() {
|
||||
std::lock_guard lock{ui_state_mutex};
|
||||
|
||||
if (!ui_state) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return ui_state->is_context_capturing_mouse();
|
||||
}
|
||||
|
||||
bool recompui::is_any_context_shown() {
|
||||
|
Loading…
x
Reference in New Issue
Block a user