mirror of
https://github.com/Zelda64Recomp/Zelda64Recomp
synced 2026-06-20 16:21:39 -04:00
Migrate to N64ModernRuntime (#354)
This commit is contained in:
@@ -6,7 +6,7 @@
|
||||
|
||||
using ColourMap = Rml::UnorderedMap<Rml::String, Rml::Colourb>;
|
||||
|
||||
namespace recomp {
|
||||
namespace recompui {
|
||||
class PropertyParserColorHack : public Rml::PropertyParser {
|
||||
public:
|
||||
PropertyParserColorHack();
|
||||
|
||||
+73
-73
@@ -1,13 +1,13 @@
|
||||
#include "recomp_ui.h"
|
||||
#include "recomp_input.h"
|
||||
#include "recomp_sound.h"
|
||||
#include "recomp_config.h"
|
||||
#include "recomp_debug.h"
|
||||
#include "zelda_sound.h"
|
||||
#include "zelda_config.h"
|
||||
#include "zelda_debug.h"
|
||||
#include "promptfont.h"
|
||||
#include "../../ultramodern/config.hpp"
|
||||
#include "../../ultramodern/ultramodern.hpp"
|
||||
#include "ultramodern/config.hpp"
|
||||
#include "ultramodern/ultramodern.hpp"
|
||||
#include "RmlUi/Core.h"
|
||||
#include "rt64_layer.h"
|
||||
#include "ultramodern/rt64_layer.hpp"
|
||||
|
||||
ultramodern::GraphicsConfig new_options;
|
||||
Rml::DataModelHandle nav_help_model_handle;
|
||||
@@ -16,9 +16,9 @@ Rml::DataModelHandle controls_model_handle;
|
||||
Rml::DataModelHandle graphics_model_handle;
|
||||
Rml::DataModelHandle sound_options_model_handle;
|
||||
|
||||
recomp::PromptContext prompt_context;
|
||||
recompui::PromptContext prompt_context;
|
||||
|
||||
namespace recomp {
|
||||
namespace recompui {
|
||||
const std::unordered_map<ButtonVariant, std::string> button_variants {
|
||||
{ButtonVariant::Primary, "primary"},
|
||||
{ButtonVariant::Secondary, "secondary"},
|
||||
@@ -164,7 +164,7 @@ static bool cont_active = true;
|
||||
static recomp::InputDevice cur_device = recomp::InputDevice::Controller;
|
||||
|
||||
void recomp::finish_scanning_input(recomp::InputField scanned_field) {
|
||||
recomp::set_input_binding(static_cast<recomp::GameInput>(scanned_input_index), scanned_binding_index, cur_device, scanned_field);
|
||||
recomp::set_input_binding(static_cast<recomp::GameInput>(scanned_input_index), scanned_binding_index, cur_device, scanned_field);
|
||||
scanned_input_index = -1;
|
||||
scanned_binding_index = -1;
|
||||
controls_model_handle.DirtyVariable("inputs");
|
||||
@@ -173,7 +173,7 @@ void recomp::finish_scanning_input(recomp::InputField scanned_field) {
|
||||
}
|
||||
|
||||
void recomp::cancel_scanning_input() {
|
||||
recomp::stop_scanning_input();
|
||||
recomp::stop_scanning_input();
|
||||
scanned_input_index = -1;
|
||||
scanned_binding_index = -1;
|
||||
controls_model_handle.DirtyVariable("inputs");
|
||||
@@ -198,13 +198,13 @@ void recomp::config_menu_set_cont_or_kb(bool cont_interacted) {
|
||||
}
|
||||
|
||||
void close_config_menu_impl() {
|
||||
recomp::save_config();
|
||||
zelda64::save_config();
|
||||
|
||||
if (ultramodern::is_game_started()) {
|
||||
recomp::set_current_menu(recomp::Menu::None);
|
||||
recompui::set_current_menu(recompui::Menu::None);
|
||||
}
|
||||
else {
|
||||
recomp::set_current_menu(recomp::Menu::Launcher);
|
||||
recompui::set_current_menu(recompui::Menu::Launcher);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -241,8 +241,8 @@ void close_config_menu() {
|
||||
graphics_model_handle.DirtyAllVariables();
|
||||
close_config_menu_impl();
|
||||
},
|
||||
recomp::ButtonVariant::Success,
|
||||
recomp::ButtonVariant::Error,
|
||||
recompui::ButtonVariant::Success,
|
||||
recompui::ButtonVariant::Error,
|
||||
true,
|
||||
"config__close-menu-button"
|
||||
);
|
||||
@@ -252,7 +252,7 @@ void close_config_menu() {
|
||||
close_config_menu_impl();
|
||||
}
|
||||
|
||||
void recomp::open_quit_game_prompt() {
|
||||
void zelda64::open_quit_game_prompt() {
|
||||
prompt_context.open_prompt(
|
||||
"Are you sure you want to quit?",
|
||||
"Any progress since your last save will be lost.",
|
||||
@@ -262,8 +262,8 @@ void recomp::open_quit_game_prompt() {
|
||||
ultramodern::quit();
|
||||
},
|
||||
[]() {},
|
||||
recomp::ButtonVariant::Error,
|
||||
recomp::ButtonVariant::Tertiary,
|
||||
recompui::ButtonVariant::Error,
|
||||
recompui::ButtonVariant::Tertiary,
|
||||
true,
|
||||
"config__quit-game-button"
|
||||
);
|
||||
@@ -275,12 +275,12 @@ struct ControlOptionsContext {
|
||||
int gyro_sensitivity; // 0 to 100
|
||||
int mouse_sensitivity; // 0 to 100
|
||||
int joystick_deadzone; // 0 to 100
|
||||
recomp::TargetingMode targeting_mode;
|
||||
zelda64::TargetingMode targeting_mode;
|
||||
recomp::BackgroundInputMode background_input_mode;
|
||||
recomp::AutosaveMode autosave_mode;
|
||||
recomp::CameraInvertMode camera_invert_mode;
|
||||
recomp::AnalogCamMode analog_cam_mode;
|
||||
recomp::CameraInvertMode analog_camera_invert_mode;
|
||||
zelda64::AutosaveMode autosave_mode;
|
||||
zelda64::CameraInvertMode camera_invert_mode;
|
||||
zelda64::AnalogCamMode analog_cam_mode;
|
||||
zelda64::CameraInvertMode analog_camera_invert_mode;
|
||||
};
|
||||
|
||||
ControlOptionsContext control_options_context;
|
||||
@@ -329,11 +329,11 @@ void recomp::set_joystick_deadzone(int deadzone) {
|
||||
}
|
||||
}
|
||||
|
||||
recomp::TargetingMode recomp::get_targeting_mode() {
|
||||
zelda64::TargetingMode zelda64::get_targeting_mode() {
|
||||
return control_options_context.targeting_mode;
|
||||
}
|
||||
|
||||
void recomp::set_targeting_mode(recomp::TargetingMode mode) {
|
||||
void zelda64::set_targeting_mode(zelda64::TargetingMode mode) {
|
||||
control_options_context.targeting_mode = mode;
|
||||
if (general_model_handle) {
|
||||
general_model_handle.DirtyVariable("targeting_mode");
|
||||
@@ -357,44 +357,44 @@ void recomp::set_background_input_mode(recomp::BackgroundInputMode mode) {
|
||||
);
|
||||
}
|
||||
|
||||
recomp::AutosaveMode recomp::get_autosave_mode() {
|
||||
zelda64::AutosaveMode zelda64::get_autosave_mode() {
|
||||
return control_options_context.autosave_mode;
|
||||
}
|
||||
|
||||
void recomp::set_autosave_mode(recomp::AutosaveMode mode) {
|
||||
void zelda64::set_autosave_mode(zelda64::AutosaveMode mode) {
|
||||
control_options_context.autosave_mode = mode;
|
||||
if (general_model_handle) {
|
||||
general_model_handle.DirtyVariable("autosave_mode");
|
||||
}
|
||||
}
|
||||
|
||||
recomp::CameraInvertMode recomp::get_camera_invert_mode() {
|
||||
zelda64::CameraInvertMode zelda64::get_camera_invert_mode() {
|
||||
return control_options_context.camera_invert_mode;
|
||||
}
|
||||
|
||||
void recomp::set_camera_invert_mode(recomp::CameraInvertMode mode) {
|
||||
void zelda64::set_camera_invert_mode(zelda64::CameraInvertMode mode) {
|
||||
control_options_context.camera_invert_mode = mode;
|
||||
if (general_model_handle) {
|
||||
general_model_handle.DirtyVariable("camera_invert_mode");
|
||||
}
|
||||
}
|
||||
|
||||
recomp::AnalogCamMode recomp::get_analog_cam_mode() {
|
||||
zelda64::AnalogCamMode zelda64::get_analog_cam_mode() {
|
||||
return control_options_context.analog_cam_mode;
|
||||
}
|
||||
|
||||
void recomp::set_analog_cam_mode(recomp::AnalogCamMode mode) {
|
||||
void zelda64::set_analog_cam_mode(zelda64::AnalogCamMode mode) {
|
||||
control_options_context.analog_cam_mode = mode;
|
||||
if (general_model_handle) {
|
||||
general_model_handle.DirtyVariable("analog_cam_mode");
|
||||
}
|
||||
}
|
||||
|
||||
recomp::CameraInvertMode recomp::get_analog_camera_invert_mode() {
|
||||
zelda64::CameraInvertMode zelda64::get_analog_camera_invert_mode() {
|
||||
return control_options_context.analog_camera_invert_mode;
|
||||
}
|
||||
|
||||
void recomp::set_analog_camera_invert_mode(recomp::CameraInvertMode mode) {
|
||||
void zelda64::set_analog_camera_invert_mode(zelda64::CameraInvertMode mode) {
|
||||
control_options_context.analog_camera_invert_mode = mode;
|
||||
if (general_model_handle) {
|
||||
general_model_handle.DirtyVariable("analog_camera_invert_mode");
|
||||
@@ -417,43 +417,43 @@ struct SoundOptionsContext {
|
||||
|
||||
SoundOptionsContext sound_options_context;
|
||||
|
||||
void recomp::reset_sound_settings() {
|
||||
void zelda64::reset_sound_settings() {
|
||||
sound_options_context.reset();
|
||||
if (sound_options_model_handle) {
|
||||
sound_options_model_handle.DirtyAllVariables();
|
||||
}
|
||||
}
|
||||
|
||||
void recomp::set_main_volume(int volume) {
|
||||
void zelda64::set_main_volume(int volume) {
|
||||
sound_options_context.main_volume.store(volume);
|
||||
if (sound_options_model_handle) {
|
||||
sound_options_model_handle.DirtyVariable("main_volume");
|
||||
}
|
||||
}
|
||||
|
||||
int recomp::get_main_volume() {
|
||||
int zelda64::get_main_volume() {
|
||||
return sound_options_context.main_volume.load();
|
||||
}
|
||||
|
||||
void recomp::set_bgm_volume(int volume) {
|
||||
void zelda64::set_bgm_volume(int volume) {
|
||||
sound_options_context.bgm_volume.store(volume);
|
||||
if (sound_options_model_handle) {
|
||||
sound_options_model_handle.DirtyVariable("bgm_volume");
|
||||
}
|
||||
}
|
||||
|
||||
int recomp::get_bgm_volume() {
|
||||
int zelda64::get_bgm_volume() {
|
||||
return sound_options_context.bgm_volume.load();
|
||||
}
|
||||
|
||||
void recomp::set_low_health_beeps_enabled(bool enabled) {
|
||||
void zelda64::set_low_health_beeps_enabled(bool enabled) {
|
||||
sound_options_context.low_health_beeps_enabled.store((int)enabled);
|
||||
if (sound_options_model_handle) {
|
||||
sound_options_model_handle.DirtyVariable("low_health_beeps_enabled");
|
||||
}
|
||||
}
|
||||
|
||||
bool recomp::get_low_health_beeps_enabled() {
|
||||
bool zelda64::get_low_health_beeps_enabled() {
|
||||
return (bool)sound_options_context.low_health_beeps_enabled.load();
|
||||
}
|
||||
|
||||
@@ -471,7 +471,7 @@ struct DebugContext {
|
||||
bool debug_enabled = false;
|
||||
|
||||
DebugContext() {
|
||||
for (const auto& area : recomp::game_warps) {
|
||||
for (const auto& area : zelda64::game_warps) {
|
||||
area_names.emplace_back(area.name);
|
||||
}
|
||||
update_warp_names();
|
||||
@@ -479,15 +479,15 @@ struct DebugContext {
|
||||
|
||||
void update_warp_names() {
|
||||
scene_names.clear();
|
||||
for (const auto& scene : recomp::game_warps[area_index].scenes) {
|
||||
for (const auto& scene : zelda64::game_warps[area_index].scenes) {
|
||||
scene_names.emplace_back(scene.name);
|
||||
}
|
||||
|
||||
entrance_names = recomp::game_warps[area_index].scenes[scene_index].entrances;
|
||||
entrance_names = zelda64::game_warps[area_index].scenes[scene_index].entrances;
|
||||
}
|
||||
};
|
||||
|
||||
void recomp::update_rml_display_refresh_rate() {
|
||||
void recompui::update_rml_display_refresh_rate() {
|
||||
static uint32_t lastRate = 0;
|
||||
if (!graphics_model_handle) return;
|
||||
|
||||
@@ -500,7 +500,7 @@ void recomp::update_rml_display_refresh_rate() {
|
||||
|
||||
DebugContext debug_context;
|
||||
|
||||
class ConfigMenu : public recomp::MenuController {
|
||||
class ConfigMenu : public recompui::MenuController {
|
||||
public:
|
||||
ConfigMenu() {
|
||||
|
||||
@@ -511,13 +511,13 @@ public:
|
||||
Rml::ElementDocument* load_document(Rml::Context* context) override {
|
||||
return context->LoadDocument("assets/config_menu.rml");
|
||||
}
|
||||
void register_events(recomp::UiEventListenerInstancer& listener) override {
|
||||
recomp::register_event(listener, "apply_options",
|
||||
void register_events(recompui::UiEventListenerInstancer& listener) override {
|
||||
recompui::register_event(listener, "apply_options",
|
||||
[](const std::string& param, Rml::Event& event) {
|
||||
graphics_model_handle.DirtyVariable("options_changed");
|
||||
apply_graphics_config();
|
||||
});
|
||||
recomp::register_event(listener, "config_keydown",
|
||||
recompui::register_event(listener, "config_keydown",
|
||||
[](const std::string& param, Rml::Event& event) {
|
||||
if (!prompt_context.open && event.GetId() == Rml::EventId::Keydown) {
|
||||
auto key = event.GetParameter<Rml::Input::KeyIdentifier>("key_identifier", Rml::Input::KeyIdentifier::KI_UNKNOWN);
|
||||
@@ -533,23 +533,23 @@ public:
|
||||
}
|
||||
});
|
||||
// This needs to be separate from `close_config_menu` so it ensures that the event is only on the target
|
||||
recomp::register_event(listener, "close_config_menu_backdrop",
|
||||
recompui::register_event(listener, "close_config_menu_backdrop",
|
||||
[](const std::string& param, Rml::Event& event) {
|
||||
if (event.GetPhase() == Rml::EventPhase::Target) {
|
||||
close_config_menu();
|
||||
}
|
||||
});
|
||||
recomp::register_event(listener, "close_config_menu",
|
||||
recompui::register_event(listener, "close_config_menu",
|
||||
[](const std::string& param, Rml::Event& event) {
|
||||
close_config_menu();
|
||||
});
|
||||
|
||||
recomp::register_event(listener, "open_quit_game_prompt",
|
||||
recompui::register_event(listener, "open_quit_game_prompt",
|
||||
[](const std::string& param, Rml::Event& event) {
|
||||
recomp::open_quit_game_prompt();
|
||||
zelda64::open_quit_game_prompt();
|
||||
});
|
||||
|
||||
recomp::register_event(listener, "toggle_input_device",
|
||||
recompui::register_event(listener, "toggle_input_device",
|
||||
[](const std::string& param, Rml::Event& event) {
|
||||
cur_device = cur_device == recomp::InputDevice::Controller
|
||||
? recomp::InputDevice::Keyboard
|
||||
@@ -558,7 +558,7 @@ public:
|
||||
controls_model_handle.DirtyVariable("inputs");
|
||||
});
|
||||
|
||||
recomp::register_event(listener, "area_index_changed",
|
||||
recompui::register_event(listener, "area_index_changed",
|
||||
[](const std::string& param, Rml::Event& event) {
|
||||
debug_context.area_index = event.GetParameter<int>("value", 0);
|
||||
debug_context.scene_index = 0;
|
||||
@@ -570,7 +570,7 @@ public:
|
||||
debug_context.model_handle.DirtyVariable("entrance_names");
|
||||
});
|
||||
|
||||
recomp::register_event(listener, "scene_index_changed",
|
||||
recompui::register_event(listener, "scene_index_changed",
|
||||
[](const std::string& param, Rml::Event& event) {
|
||||
debug_context.scene_index = event.GetParameter<int>("value", 0);
|
||||
debug_context.entrance_index = 0;
|
||||
@@ -579,14 +579,14 @@ public:
|
||||
debug_context.model_handle.DirtyVariable("entrance_names");
|
||||
});
|
||||
|
||||
recomp::register_event(listener, "do_warp",
|
||||
recompui::register_event(listener, "do_warp",
|
||||
[](const std::string& param, Rml::Event& event) {
|
||||
recomp::do_warp(debug_context.area_index, debug_context.scene_index, debug_context.entrance_index);
|
||||
zelda64::do_warp(debug_context.area_index, debug_context.scene_index, debug_context.entrance_index);
|
||||
});
|
||||
|
||||
recomp::register_event(listener, "set_time",
|
||||
recompui::register_event(listener, "set_time",
|
||||
[](const std::string& param, Rml::Event& event) {
|
||||
recomp::set_time(debug_context.set_time_day, debug_context.set_time_hour, debug_context.set_time_minute);
|
||||
zelda64::set_time(debug_context.set_time_day, debug_context.set_time_hour, debug_context.set_time_minute);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -722,7 +722,7 @@ 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);
|
||||
recomp::start_scanning_input(cur_device);
|
||||
model_handle.DirtyVariable("active_binding_input");
|
||||
model_handle.DirtyVariable("active_binding_slot");
|
||||
});
|
||||
@@ -730,18 +730,18 @@ public:
|
||||
constructor.BindEventCallback("reset_input_bindings_to_defaults",
|
||||
[](Rml::DataModelHandle model_handle, Rml::Event& event, const Rml::VariantList& inputs) {
|
||||
if (cur_device == recomp::InputDevice::Controller) {
|
||||
recomp::reset_cont_input_bindings();
|
||||
zelda64::reset_cont_input_bindings();
|
||||
} else {
|
||||
recomp::reset_kb_input_bindings();
|
||||
zelda64::reset_kb_input_bindings();
|
||||
}
|
||||
model_handle.DirtyAllVariables();
|
||||
});
|
||||
|
||||
constructor.BindEventCallback("clear_input_bindings",
|
||||
[](Rml::DataModelHandle model_handle, Rml::Event& event, const Rml::VariantList& inputs) {
|
||||
recomp::GameInput input = static_cast<recomp::GameInput>(inputs.at(0).Get<size_t>());
|
||||
recomp::GameInput input = static_cast<recomp::GameInput>(inputs.at(0).Get<size_t>());
|
||||
for (size_t binding_index = 0; binding_index < recomp::bindings_per_input; binding_index++) {
|
||||
recomp::set_input_binding(input, binding_index, cur_device, recomp::InputField{});
|
||||
recomp::set_input_binding(input, binding_index, cur_device, recomp::InputField{});
|
||||
}
|
||||
model_handle.DirtyVariable("inputs");
|
||||
});
|
||||
@@ -776,7 +776,7 @@ public:
|
||||
|
||||
virtual int Size(void* ptr) override { return recomp::bindings_per_input; }
|
||||
virtual Rml::DataVariable Child(void* ptr, const Rml::DataAddressEntry& address) override {
|
||||
recomp::GameInput input = static_cast<recomp::GameInput>((uintptr_t)ptr);
|
||||
recomp::GameInput input = static_cast<recomp::GameInput>((uintptr_t)ptr);
|
||||
return Rml::DataVariable{&input_field_definition_instance, &recomp::get_input_binding(input, address.index, cur_device)};
|
||||
}
|
||||
};
|
||||
@@ -812,7 +812,7 @@ public:
|
||||
return Rml::DataVariable(&binding_array_var_instance, nullptr);
|
||||
}
|
||||
else {
|
||||
recomp::GameInput input = recomp::get_input_from_enum_name(address.name);
|
||||
recomp::GameInput input = recomp::get_input_from_enum_name(address.name);
|
||||
if (input != recomp::GameInput::COUNT) {
|
||||
return Rml::DataVariable(&binding_container_var_instance, (void*)(uintptr_t)input);
|
||||
}
|
||||
@@ -966,14 +966,14 @@ public:
|
||||
constructor.Bind("prompt__confirmLabel", &prompt_context.confirmLabel);
|
||||
constructor.Bind("prompt__cancelLabel", &prompt_context.cancelLabel);
|
||||
|
||||
constructor.BindEventCallback("prompt__on_click", &recomp::PromptContext::on_click, &prompt_context);
|
||||
constructor.BindEventCallback("prompt__on_click", &recompui::PromptContext::on_click, &prompt_context);
|
||||
|
||||
prompt_context.model_handle = constructor.GetModelHandle();
|
||||
}
|
||||
|
||||
void make_bindings(Rml::Context* context) override {
|
||||
// initially set cont state for ui help
|
||||
recomp::config_menu_set_cont_or_kb(recomp::get_cont_active());
|
||||
recomp::config_menu_set_cont_or_kb(recompui::get_cont_active());
|
||||
make_nav_help_bindings(context);
|
||||
make_general_bindings(context);
|
||||
make_controls_bindings(context);
|
||||
@@ -984,22 +984,22 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
std::unique_ptr<recomp::MenuController> recomp::create_config_menu() {
|
||||
std::unique_ptr<recompui::MenuController> recompui::create_config_menu() {
|
||||
return std::make_unique<ConfigMenu>();
|
||||
}
|
||||
|
||||
bool recomp::get_debug_mode_enabled() {
|
||||
bool zelda64::get_debug_mode_enabled() {
|
||||
return debug_context.debug_enabled;
|
||||
}
|
||||
|
||||
void recomp::set_debug_mode_enabled(bool enabled) {
|
||||
void zelda64::set_debug_mode_enabled(bool enabled) {
|
||||
debug_context.debug_enabled = enabled;
|
||||
if (debug_context.model_handle) {
|
||||
debug_context.model_handle.DirtyVariable("debug_enabled");
|
||||
}
|
||||
}
|
||||
|
||||
void recomp::update_supported_options() {
|
||||
void recompui::update_supported_options() {
|
||||
msaa2x_supported = ultramodern::RT64MaxMSAA() >= RT64::UserConfiguration::Antialiasing::MSAA2X;
|
||||
msaa4x_supported = ultramodern::RT64MaxMSAA() >= RT64::UserConfiguration::Antialiasing::MSAA4X;
|
||||
msaa8x_supported = ultramodern::RT64MaxMSAA() >= RT64::UserConfiguration::Antialiasing::MSAA8X;
|
||||
@@ -1010,7 +1010,7 @@ void recomp::update_supported_options() {
|
||||
graphics_model_handle.DirtyAllVariables();
|
||||
}
|
||||
|
||||
void recomp::toggle_fullscreen() {
|
||||
void recompui::toggle_fullscreen() {
|
||||
new_options.wm_option = (new_options.wm_option == ultramodern::WindowMode::Windowed) ? ultramodern::WindowMode::Fullscreen : ultramodern::WindowMode::Windowed;
|
||||
apply_graphics_config();
|
||||
graphics_model_handle.DirtyVariable("wm_option");
|
||||
|
||||
+48
-46
@@ -1,7 +1,7 @@
|
||||
#include "recomp_ui.h"
|
||||
#include "recomp_config.h"
|
||||
#include "recomp_game.h"
|
||||
#include "../../ultramodern/ultramodern.hpp"
|
||||
#include "zelda_config.h"
|
||||
#include "librecomp/game.hpp"
|
||||
#include "ultramodern/ultramodern.hpp"
|
||||
#include "RmlUi/Core.h"
|
||||
#include "nfd.h"
|
||||
#include <filesystem>
|
||||
@@ -11,6 +11,8 @@ std::string version_number = "v1.1.1";
|
||||
Rml::DataModelHandle model_handle;
|
||||
bool mm_rom_valid = false;
|
||||
|
||||
extern std::vector<recomp::GameEntry> supported_games;
|
||||
|
||||
void select_rom() {
|
||||
nfdnchar_t* native_path = nullptr;
|
||||
nfdresult_t result = NFD_OpenDialogN(&native_path, nullptr, 0, nullptr);
|
||||
@@ -21,39 +23,39 @@ void select_rom() {
|
||||
NFD_FreePathN(native_path);
|
||||
native_path = nullptr;
|
||||
|
||||
recomp::RomValidationError rom_error = recomp::select_rom(path, recomp::Game::MM);
|
||||
|
||||
switch (rom_error) {
|
||||
case recomp::RomValidationError::Good:
|
||||
mm_rom_valid = true;
|
||||
model_handle.DirtyVariable("mm_rom_valid");
|
||||
break;
|
||||
case recomp::RomValidationError::FailedToOpen:
|
||||
recomp::message_box("Failed to open ROM file.");
|
||||
break;
|
||||
case recomp::RomValidationError::NotARom:
|
||||
recomp::message_box("This is not a valid ROM file.");
|
||||
break;
|
||||
case recomp::RomValidationError::IncorrectRom:
|
||||
recomp::message_box("This ROM is not the correct game.");
|
||||
break;
|
||||
case recomp::RomValidationError::NotYet:
|
||||
recomp::message_box("This game isn't supported yet.");
|
||||
break;
|
||||
case recomp::RomValidationError::IncorrectVersion:
|
||||
recomp::message_box("This ROM is the correct game, but the wrong version.\nThis project requires the NTSC-U N64 version of the game.");
|
||||
break;
|
||||
case recomp::RomValidationError::OtherError:
|
||||
recomp::message_box("An unknown error has occurred.");
|
||||
break;
|
||||
}
|
||||
}
|
||||
recomp::RomValidationError rom_error = recomp::select_rom(path, supported_games[0].game_id);
|
||||
switch (rom_error) {
|
||||
case recomp::RomValidationError::Good:
|
||||
mm_rom_valid = true;
|
||||
model_handle.DirtyVariable("mm_rom_valid");
|
||||
break;
|
||||
case recomp::RomValidationError::FailedToOpen:
|
||||
recompui::message_box("Failed to open ROM file.");
|
||||
break;
|
||||
case recomp::RomValidationError::NotARom:
|
||||
recompui::message_box("This is not a valid ROM file.");
|
||||
break;
|
||||
case recomp::RomValidationError::IncorrectRom:
|
||||
recompui::message_box("This ROM is not the correct game.");
|
||||
break;
|
||||
case recomp::RomValidationError::NotYet:
|
||||
recompui::message_box("This game isn't supported yet.");
|
||||
break;
|
||||
case recomp::RomValidationError::IncorrectVersion:
|
||||
recompui::message_box(
|
||||
"This ROM is the correct game, but the wrong version.\nThis project requires the NTSC-U N64 version of the game.");
|
||||
break;
|
||||
case recomp::RomValidationError::OtherError:
|
||||
recompui::message_box("An unknown error has occurred.");
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class LauncherMenu : public recomp::MenuController {
|
||||
class LauncherMenu : public recompui::MenuController {
|
||||
public:
|
||||
LauncherMenu() {
|
||||
mm_rom_valid = recomp::is_rom_valid(recomp::Game::MM);
|
||||
mm_rom_valid = recomp::is_rom_valid(supported_games[0].game_id);
|
||||
}
|
||||
~LauncherMenu() override {
|
||||
|
||||
@@ -61,37 +63,37 @@ public:
|
||||
Rml::ElementDocument* load_document(Rml::Context* context) override {
|
||||
return context->LoadDocument("assets/launcher.rml");
|
||||
}
|
||||
void register_events(recomp::UiEventListenerInstancer& listener) override {
|
||||
recomp::register_event(listener, "select_rom",
|
||||
void register_events(recompui::UiEventListenerInstancer& listener) override {
|
||||
recompui::register_event(listener, "select_rom",
|
||||
[](const std::string& param, Rml::Event& event) {
|
||||
select_rom();
|
||||
}
|
||||
);
|
||||
recomp::register_event(listener, "rom_selected",
|
||||
recompui::register_event(listener, "rom_selected",
|
||||
[](const std::string& param, Rml::Event& event) {
|
||||
mm_rom_valid = true;
|
||||
model_handle.DirtyVariable("mm_rom_valid");
|
||||
}
|
||||
);
|
||||
recomp::register_event(listener, "start_game",
|
||||
recompui::register_event(listener, "start_game",
|
||||
[](const std::string& param, Rml::Event& event) {
|
||||
recomp::start_game(recomp::Game::MM);
|
||||
recomp::set_current_menu(recomp::Menu::None);
|
||||
recomp::start_game(supported_games[0].game_id);
|
||||
recompui::set_current_menu(recompui::Menu::None);
|
||||
}
|
||||
);
|
||||
recomp::register_event(listener, "open_controls",
|
||||
recompui::register_event(listener, "open_controls",
|
||||
[](const std::string& param, Rml::Event& event) {
|
||||
recomp::set_current_menu(recomp::Menu::Config);
|
||||
recomp::set_config_submenu(recomp::ConfigSubmenu::Controls);
|
||||
recompui::set_current_menu(recompui::Menu::Config);
|
||||
recompui::set_config_submenu(recompui::ConfigSubmenu::Controls);
|
||||
}
|
||||
);
|
||||
recomp::register_event(listener, "open_settings",
|
||||
recompui::register_event(listener, "open_settings",
|
||||
[](const std::string& param, Rml::Event& event) {
|
||||
recomp::set_current_menu(recomp::Menu::Config);
|
||||
recomp::set_config_submenu(recomp::ConfigSubmenu::General);
|
||||
recompui::set_current_menu(recompui::Menu::Config);
|
||||
recompui::set_config_submenu(recompui::ConfigSubmenu::General);
|
||||
}
|
||||
);
|
||||
recomp::register_event(listener, "exit_game",
|
||||
recompui::register_event(listener, "exit_game",
|
||||
[](const std::string& param, Rml::Event& event) {
|
||||
ultramodern::quit();
|
||||
}
|
||||
@@ -107,6 +109,6 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
std::unique_ptr<recomp::MenuController> recomp::create_launcher_menu() {
|
||||
std::unique_ptr<recompui::MenuController> recompui::create_launcher_menu() {
|
||||
return std::make_unique<LauncherMenu>();
|
||||
}
|
||||
|
||||
+55
-50
@@ -4,16 +4,22 @@
|
||||
|
||||
#include <fstream>
|
||||
#include <filesystem>
|
||||
#ifdef _WIN32
|
||||
#include <SDL_video.h>
|
||||
#else
|
||||
#include <SDL2/SDL_video.h>
|
||||
#endif
|
||||
|
||||
|
||||
#include "recomp_ui.h"
|
||||
#include "recomp_input.h"
|
||||
#include "recomp_game.h"
|
||||
#include "recomp_config.h"
|
||||
#include "librecomp/game.hpp"
|
||||
#include "zelda_config.h"
|
||||
#include "ui_rml_hacks.hpp"
|
||||
|
||||
#include "concurrentqueue.h"
|
||||
|
||||
#include "rt64_layer.h"
|
||||
#include "ultramodern/rt64_layer.hpp"
|
||||
#include "rt64_render_hooks.h"
|
||||
#include "rt64_render_interface_builders.h"
|
||||
|
||||
@@ -718,7 +724,7 @@ Rml::Element* get_target(Rml::ElementDocument* document, Rml::Element* element)
|
||||
return element;
|
||||
}
|
||||
|
||||
namespace recomp {
|
||||
namespace recompui {
|
||||
class UiEventListener : public Rml::EventListener {
|
||||
event_handler_t* handler_;
|
||||
Rml::String param_;
|
||||
@@ -759,7 +765,7 @@ namespace recomp {
|
||||
};
|
||||
}
|
||||
|
||||
void recomp::register_event(UiEventListenerInstancer& listener, const std::string& name, event_handler_t* handler) {
|
||||
void recompui::register_event(UiEventListenerInstancer& listener, const std::string& name, event_handler_t* handler) {
|
||||
listener.register_event(name, handler);
|
||||
}
|
||||
|
||||
@@ -779,8 +785,8 @@ Rml::Element* find_autofocus_element(Rml::Element* start) {
|
||||
struct UIContext {
|
||||
struct UIRenderContext render;
|
||||
class {
|
||||
std::unordered_map<recomp::Menu, std::unique_ptr<recomp::MenuController>> menus;
|
||||
std::unordered_map<recomp::Menu, Rml::ElementDocument*> documents;
|
||||
std::unordered_map<recompui::Menu, std::unique_ptr<recompui::MenuController>> menus;
|
||||
std::unordered_map<recompui::Menu, Rml::ElementDocument*> documents;
|
||||
Rml::ElementDocument* current_document;
|
||||
Rml::Element* prev_focused;
|
||||
bool mouse_is_active_changed = false;
|
||||
@@ -794,13 +800,13 @@ struct UIContext {
|
||||
std::unique_ptr<SystemInterface_SDL> system_interface;
|
||||
std::unique_ptr<RmlRenderInterface_RT64> render_interface;
|
||||
Rml::Context* context;
|
||||
recomp::UiEventListenerInstancer event_listener_instancer;
|
||||
recompui::UiEventListenerInstancer event_listener_instancer;
|
||||
|
||||
void unload() {
|
||||
render_interface.reset();
|
||||
}
|
||||
|
||||
void swap_document(recomp::Menu menu) {
|
||||
void swap_document(recompui::Menu menu) {
|
||||
if (current_document != nullptr) {
|
||||
Rml::Element* window_el = current_document->GetElementById("window");
|
||||
if (window_el != nullptr) {
|
||||
@@ -831,7 +837,7 @@ struct UIContext {
|
||||
mouse_is_active_initialized = false;
|
||||
}
|
||||
|
||||
void swap_config_menu(recomp::ConfigSubmenu submenu) {
|
||||
void swap_config_menu(recompui::ConfigSubmenu submenu) {
|
||||
if (current_document != nullptr) {
|
||||
Rml::Element* config_tabset_base = current_document->GetElementById("config_tabset");
|
||||
if (config_tabset_base != nullptr) {
|
||||
@@ -911,7 +917,7 @@ struct UIContext {
|
||||
}
|
||||
|
||||
if (mouse_is_active_initialized) {
|
||||
recomp::set_cursor_visible(mouse_is_active);
|
||||
recompui::set_cursor_visible(mouse_is_active);
|
||||
}
|
||||
|
||||
if (current_document == nullptr) {
|
||||
@@ -939,7 +945,6 @@ struct UIContext {
|
||||
if (cont_is_active || non_mouse_interacted) {
|
||||
if (non_mouse_interacted) {
|
||||
auto focusedEl = current_document->GetFocusLeafNode();
|
||||
Rml::Variant* ti = focusedEl == nullptr ? nullptr : focusedEl->GetAttribute("tab-index");
|
||||
if (focusedEl == nullptr || RecompRml::CanFocusElement(focusedEl) != RecompRml::CanFocus::Yes) {
|
||||
Rml::Element* element = find_autofocus_element(current_document);
|
||||
if (element != nullptr) {
|
||||
@@ -981,14 +986,14 @@ struct UIContext {
|
||||
}
|
||||
}
|
||||
|
||||
void add_menu(recomp::Menu menu, std::unique_ptr<recomp::MenuController>&& controller) {
|
||||
void add_menu(recompui::Menu menu, std::unique_ptr<recompui::MenuController>&& controller) {
|
||||
menus.emplace(menu, std::move(controller));
|
||||
}
|
||||
|
||||
void update_config_menu_loop(bool menu_changed) {
|
||||
static int prevTab = -1;
|
||||
if (menu_changed) prevTab = -1;
|
||||
recomp::update_rml_display_refresh_rate();
|
||||
recompui::update_rml_display_refresh_rate();
|
||||
|
||||
Rml::ElementTabSet *tabset = (Rml::ElementTabSet *)current_document->GetElementById("config_tabset");
|
||||
if (tabset == nullptr) return;
|
||||
@@ -1022,7 +1027,7 @@ struct UIContext {
|
||||
void update_prompt_loop(void) {
|
||||
static bool wasShowingPrompt = false;
|
||||
|
||||
recomp::PromptContext *ctx = recomp::get_prompt_context();
|
||||
recompui::PromptContext *ctx = recompui::get_prompt_context();
|
||||
if (!ctx->open && wasShowingPrompt) {
|
||||
Rml::Element* focused = current_document->GetFocusLeafNode();
|
||||
if (focused) focused->Blur();
|
||||
@@ -1088,8 +1093,8 @@ struct UIContext {
|
||||
|
||||
Rml::Element *confirmButton = current_document->GetElementById("prompt__confirm-button");
|
||||
Rml::Element *cancelButton = current_document->GetElementById("prompt__cancel-button");
|
||||
if (confirmButton != nullptr) confirmButton->SetClassNames("button button--" + recomp::button_variants.at(ctx->confirmVariant));
|
||||
if (cancelButton != nullptr) cancelButton->SetClassNames( "button button--" + recomp::button_variants.at(ctx->cancelVariant));
|
||||
if (confirmButton != nullptr) confirmButton->SetClassNames("button button--" + recompui::button_variants.at(ctx->confirmVariant));
|
||||
if (cancelButton != nullptr) cancelButton->SetClassNames( "button button--" + recompui::button_variants.at(ctx->cancelVariant));
|
||||
}
|
||||
} rml;
|
||||
};
|
||||
@@ -1100,7 +1105,7 @@ std::mutex ui_context_mutex{};
|
||||
// TODO make this not be global
|
||||
extern SDL_Window* window;
|
||||
|
||||
void recomp::get_window_size(int& width, int& height) {
|
||||
void recompui::get_window_size(int& width, int& height) {
|
||||
SDL_GetWindowSizeInPixels(window, &width, &height);
|
||||
}
|
||||
|
||||
@@ -1110,8 +1115,8 @@ void init_hook(RT64::RenderInterface* interface, RT64::RenderDevice* device) {
|
||||
#endif
|
||||
ui_context = std::make_unique<UIContext>();
|
||||
|
||||
ui_context->rml.add_menu(recomp::Menu::Config, recomp::create_config_menu());
|
||||
ui_context->rml.add_menu(recomp::Menu::Launcher, recomp::create_launcher_menu());
|
||||
ui_context->rml.add_menu(recompui::Menu::Config, recompui::create_config_menu());
|
||||
ui_context->rml.add_menu(recompui::Menu::Launcher, recompui::create_launcher_menu());
|
||||
|
||||
ui_context->render.interface = interface;
|
||||
ui_context->render.device = device;
|
||||
@@ -1129,7 +1134,7 @@ void init_hook(RT64::RenderInterface* interface, RT64::RenderDevice* device) {
|
||||
Rml::Initialise();
|
||||
|
||||
// Apply the hack to replace RmlUi's default color parser with one that conforms to HTML5 alpha parsing for SASS compatibility
|
||||
recomp::apply_color_hack();
|
||||
recompui::apply_color_hack();
|
||||
|
||||
int width, height;
|
||||
SDL_GetWindowSizeInPixels(window, &width, &height);
|
||||
@@ -1167,16 +1172,16 @@ void init_hook(RT64::RenderInterface* interface, RT64::RenderDevice* device) {
|
||||
|
||||
moodycamel::ConcurrentQueue<SDL_Event> ui_event_queue{};
|
||||
|
||||
void recomp::queue_event(const SDL_Event& event) {
|
||||
void recompui::queue_event(const SDL_Event& event) {
|
||||
ui_event_queue.enqueue(event);
|
||||
}
|
||||
|
||||
bool recomp::try_deque_event(SDL_Event& out) {
|
||||
bool recompui::try_deque_event(SDL_Event& out) {
|
||||
return ui_event_queue.try_dequeue(out);
|
||||
}
|
||||
|
||||
std::atomic<recomp::Menu> open_menu = recomp::Menu::Launcher;
|
||||
std::atomic<recomp::ConfigSubmenu> open_config_submenu = recomp::ConfigSubmenu::Count;
|
||||
std::atomic<recompui::Menu> open_menu = recompui::Menu::Launcher;
|
||||
std::atomic<recompui::ConfigSubmenu> open_config_submenu = recompui::ConfigSubmenu::Count;
|
||||
|
||||
int cont_button_to_key(SDL_ControllerButtonEvent& button) {
|
||||
switch (button.button) {
|
||||
@@ -1236,15 +1241,15 @@ void apply_background_input_mode() {
|
||||
last_input_mode = cur_input_mode;
|
||||
}
|
||||
|
||||
bool recomp::get_cont_active() {
|
||||
bool recompui::get_cont_active() {
|
||||
return ui_context->rml.cont_is_active;
|
||||
}
|
||||
|
||||
void recomp::set_cont_active(bool active) {
|
||||
void recompui::set_cont_active(bool active) {
|
||||
ui_context->rml.cont_is_active = active;
|
||||
}
|
||||
|
||||
void recomp::activate_mouse() {
|
||||
void recompui::activate_mouse() {
|
||||
ui_context->rml.update_primary_input(true, false);
|
||||
ui_context->rml.update_focus(true, false);
|
||||
}
|
||||
@@ -1267,12 +1272,12 @@ void draw_hook(RT64::RenderCommandList* command_list, RT64::RenderFramebuffer* s
|
||||
bool reload_sheets = is_reload_held && !was_reload_held;
|
||||
was_reload_held = is_reload_held;
|
||||
|
||||
static recomp::Menu prev_menu = recomp::Menu::None;
|
||||
recomp::Menu cur_menu = open_menu.load();
|
||||
static recompui::Menu prev_menu = recompui::Menu::None;
|
||||
recompui::Menu cur_menu = open_menu.load();
|
||||
|
||||
if (reload_sheets) {
|
||||
ui_context->rml.load_documents();
|
||||
prev_menu = recomp::Menu::None;
|
||||
prev_menu = recompui::Menu::None;
|
||||
}
|
||||
|
||||
bool menu_changed = cur_menu != prev_menu;
|
||||
@@ -1280,10 +1285,10 @@ void draw_hook(RT64::RenderCommandList* command_list, RT64::RenderFramebuffer* s
|
||||
ui_context->rml.swap_document(cur_menu);
|
||||
}
|
||||
|
||||
recomp::ConfigSubmenu config_submenu = open_config_submenu.load();
|
||||
if (config_submenu != recomp::ConfigSubmenu::Count) {
|
||||
recompui::ConfigSubmenu config_submenu = open_config_submenu.load();
|
||||
if (config_submenu != recompui::ConfigSubmenu::Count) {
|
||||
ui_context->rml.swap_config_menu(config_submenu);
|
||||
open_config_submenu.store(recomp::ConfigSubmenu::Count);
|
||||
open_config_submenu.store(recompui::ConfigSubmenu::Count);
|
||||
}
|
||||
|
||||
prev_menu = cur_menu;
|
||||
@@ -1296,15 +1301,15 @@ void draw_hook(RT64::RenderCommandList* command_list, RT64::RenderFramebuffer* s
|
||||
bool cont_interacted = false;
|
||||
bool kb_interacted = false;
|
||||
|
||||
if (cur_menu == recomp::Menu::Config) {
|
||||
if (cur_menu == recompui::Menu::Config) {
|
||||
ui_context->rml.update_config_menu_loop(menu_changed);
|
||||
}
|
||||
if (cur_menu != recomp::Menu::None) {
|
||||
if (cur_menu != recompui::Menu::None) {
|
||||
ui_context->rml.update_prompt_loop();
|
||||
}
|
||||
|
||||
while (recomp::try_deque_event(cur_event)) {
|
||||
bool menu_is_open = cur_menu != recomp::Menu::None;
|
||||
while (recompui::try_deque_event(cur_event)) {
|
||||
bool menu_is_open = cur_menu != recompui::Menu::None;
|
||||
|
||||
if (!recomp::all_input_disabled()) {
|
||||
// Implement some additional behavior for specific events on top of what RmlUi normally does with them.
|
||||
@@ -1323,7 +1328,7 @@ void draw_hook(RT64::RenderCommandList* command_list, RT64::RenderFramebuffer* s
|
||||
last_mouse_pos[1] = cur_event.motion.y;
|
||||
|
||||
// if controller is the primary input, don't use mouse movement to allow cursor to reactivate
|
||||
if (recomp::get_cont_active()) {
|
||||
if (recompui::get_cont_active()) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -1401,15 +1406,15 @@ void draw_hook(RT64::RenderCommandList* command_list, RT64::RenderFramebuffer* s
|
||||
}
|
||||
|
||||
if (open_config) {
|
||||
cur_menu = recomp::Menu::Config;
|
||||
open_menu.store(recomp::Menu::Config);
|
||||
cur_menu = recompui::Menu::Config;
|
||||
open_menu.store(recompui::Menu::Config);
|
||||
ui_context->rml.swap_document(cur_menu);
|
||||
}
|
||||
}
|
||||
} // end dequeue event loop
|
||||
|
||||
if (cont_interacted || kb_interacted || mouse_clicked) {
|
||||
recomp::set_cont_active(cont_interacted);
|
||||
recompui::set_cont_active(cont_interacted);
|
||||
}
|
||||
recomp::config_menu_set_cont_or_kb(ui_context->rml.cont_is_active);
|
||||
|
||||
@@ -1421,7 +1426,7 @@ void draw_hook(RT64::RenderCommandList* command_list, RT64::RenderFramebuffer* s
|
||||
ui_context->rml.update_primary_input(mouse_moved, non_mouse_interacted);
|
||||
ui_context->rml.update_focus(mouse_moved, non_mouse_interacted);
|
||||
|
||||
if (cur_menu != recomp::Menu::None) {
|
||||
if (cur_menu != recompui::Menu::None) {
|
||||
int width = swap_chain_framebuffer->getWidth();
|
||||
int height = swap_chain_framebuffer->getHeight();
|
||||
|
||||
@@ -1457,25 +1462,25 @@ void set_rt64_hooks() {
|
||||
RT64::SetRenderHooks(init_hook, draw_hook, deinit_hook);
|
||||
}
|
||||
|
||||
void recomp::set_current_menu(Menu menu) {
|
||||
void recompui::set_current_menu(Menu menu) {
|
||||
open_menu.store(menu);
|
||||
if (menu == recomp::Menu::None) {
|
||||
if (menu == recompui::Menu::None) {
|
||||
ui_context->rml.system_interface->SetMouseCursor("arrow");
|
||||
}
|
||||
}
|
||||
|
||||
void recomp::set_config_submenu(recomp::ConfigSubmenu submenu) {
|
||||
void recompui::set_config_submenu(recompui::ConfigSubmenu submenu) {
|
||||
open_config_submenu.store(submenu);
|
||||
}
|
||||
|
||||
void recomp::destroy_ui() {
|
||||
void recompui::destroy_ui() {
|
||||
}
|
||||
|
||||
recomp::Menu recomp::get_current_menu() {
|
||||
recompui::Menu recompui::get_current_menu() {
|
||||
return open_menu.load();
|
||||
}
|
||||
|
||||
void recomp::message_box(const char* msg) {
|
||||
SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, recomp::program_name.data(), msg, nullptr);
|
||||
void recompui::message_box(const char* msg) {
|
||||
SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, zelda64::program_name.data(), msg, nullptr);
|
||||
printf("[ERROR] %s\n", msg);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user