mirror of
https://github.com/Zelda64Recomp/Zelda64Recomp.git
synced 2025-10-30 08:03:03 +00:00
Add mod UI API exports for slider, password input, and label radio and expose RmlUi debugger on F8
This commit is contained in:
parent
1c6f445503
commit
d614634bf1
16 changed files with 283 additions and 32 deletions
10
include/overloaded.h
Normal file
10
include/overloaded.h
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
#ifndef __OVERLOADED_H__
|
||||
#define __OVERLOADED_H__
|
||||
|
||||
// Helper for std::visit
|
||||
template<class... Ts>
|
||||
struct overloaded : Ts... { using Ts::operator()...; };
|
||||
template<class... Ts>
|
||||
overloaded(Ts...) -> overloaded<Ts...>;
|
||||
|
||||
#endif
|
||||
|
|
@ -6,6 +6,7 @@
|
|||
#define HLSL_CPU
|
||||
#include "hle/rt64_application.h"
|
||||
#include "rt64_render_hooks.h"
|
||||
#include "overloaded.h"
|
||||
|
||||
#include "ultramodern/ultramodern.hpp"
|
||||
#include "ultramodern/config.hpp"
|
||||
|
|
@ -14,12 +15,6 @@
|
|||
#include "recomp_ui.h"
|
||||
#include "concurrentqueue.h"
|
||||
|
||||
// Helper class for variant visiting.
|
||||
template<class... Ts>
|
||||
struct overloaded : Ts... { using Ts::operator()...; };
|
||||
template<class... Ts>
|
||||
overloaded(Ts...) -> overloaded<Ts...>;
|
||||
|
||||
static RT64::UserConfiguration::Antialiasing device_max_msaa = RT64::UserConfiguration::Antialiasing::None;
|
||||
static bool sample_positions_supported = false;
|
||||
static bool high_precision_fb_enabled = false;
|
||||
|
|
|
|||
|
|
@ -6,7 +6,6 @@ namespace recompui {
|
|||
|
||||
Container::Container(Element *parent, FlexDirection direction, JustifyContent justify_content) : Element(parent) {
|
||||
set_display(Display::Flex);
|
||||
set_flex(1.0f, 1.0f);
|
||||
set_flex_direction(direction);
|
||||
set_justify_content(justify_content);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
#include "RmlUi/Core/StringUtilities.h"
|
||||
|
||||
#include "overloaded.h"
|
||||
#include "recomp_ui.h"
|
||||
#include "ui_element.h"
|
||||
#include "../core/ui_context.h"
|
||||
|
|
@ -28,6 +29,9 @@ Element::Element(Element* parent, uint32_t events_enabled, Rml::String base_clas
|
|||
base = base_owning.get();
|
||||
}
|
||||
|
||||
set_display(Display::Block);
|
||||
set_property(Rml::PropertyId::BoxSizing, Rml::Style::BoxSizing::BorderBox);
|
||||
|
||||
register_event_listeners(events_enabled);
|
||||
}
|
||||
|
||||
|
|
@ -372,6 +376,39 @@ float Element::get_client_height() {
|
|||
return base->GetClientHeight();
|
||||
}
|
||||
|
||||
uint32_t Element::get_input_value_u32() {
|
||||
ElementValue value = get_element_value();
|
||||
|
||||
return std::visit(overloaded {
|
||||
[](double d) { return (uint32_t)d; },
|
||||
[](float f) { return (uint32_t)f; },
|
||||
[](uint32_t u) { return u; },
|
||||
[](std::monostate) { return 0U; }
|
||||
}, value);
|
||||
}
|
||||
|
||||
float Element::get_input_value_float() {
|
||||
ElementValue value = get_element_value();
|
||||
|
||||
return std::visit(overloaded {
|
||||
[](double d) { return (float)d; },
|
||||
[](float f) { return f; },
|
||||
[](uint32_t u) { return (float)u; },
|
||||
[](std::monostate) { return 0.0f; }
|
||||
}, value);
|
||||
}
|
||||
|
||||
double Element::get_input_value_double() {
|
||||
ElementValue value = get_element_value();
|
||||
|
||||
return std::visit(overloaded {
|
||||
[](double d) { return d; },
|
||||
[](float f) { return (double)f; },
|
||||
[](uint32_t u) { return (double)u; },
|
||||
[](std::monostate) { return 0.0; }
|
||||
}, value);
|
||||
}
|
||||
|
||||
void Element::queue_update() {
|
||||
ContextId cur_context = get_current_context();
|
||||
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@
|
|||
#include <ultramodern/ultra64.h>
|
||||
|
||||
#include <unordered_set>
|
||||
#include <variant>
|
||||
|
||||
namespace recompui {
|
||||
struct UICallback {
|
||||
|
|
@ -15,6 +16,8 @@ struct UICallback {
|
|||
PTR(void) userdata;
|
||||
};
|
||||
|
||||
using ElementValue = std::variant<uint32_t, float, double, std::monostate>;
|
||||
|
||||
class ContextId;
|
||||
class Element : public Style, public Rml::EventListener {
|
||||
friend ContextId create_context(const std::filesystem::path& path);
|
||||
|
|
@ -52,6 +55,8 @@ protected:
|
|||
// Use of this method in inherited classes is discouraged unless it's necessary.
|
||||
void set_attribute(const Rml::String &attribute_key, const Rml::String &attribute_value);
|
||||
virtual void process_event(const Event &e);
|
||||
virtual ElementValue get_element_value() { return std::monostate{}; }
|
||||
virtual void set_input_value(const ElementValue&) {}
|
||||
public:
|
||||
// Used for backwards compatibility with legacy UI elements.
|
||||
Element(Rml::Element *base);
|
||||
|
|
@ -80,6 +85,12 @@ public:
|
|||
float get_client_height();
|
||||
void queue_update();
|
||||
void register_callback(ContextId context, PTR(void) callback, PTR(void) userdata);
|
||||
uint32_t get_input_value_u32();
|
||||
float get_input_value_float();
|
||||
double get_input_value_double();
|
||||
void set_input_value_u32(uint32_t val) { set_input_value(val); }
|
||||
void set_input_value_float(float val) { set_input_value(val); }
|
||||
void set_input_value_double(double val) { set_input_value(val); }
|
||||
};
|
||||
|
||||
void queue_ui_callback(recompui::ResourceId resource, const Event& e, const UICallback& callback);
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
#include "overloaded.h"
|
||||
#include "ui_radio.h"
|
||||
|
||||
namespace recompui {
|
||||
|
|
@ -14,14 +15,15 @@ namespace recompui {
|
|||
set_line_height(20.0f);
|
||||
set_font_weight(400);
|
||||
set_font_style(FontStyle::Normal);
|
||||
set_border_color(Color{ 242, 242, 242, 255 });
|
||||
set_border_bottom_width(0.0f);
|
||||
set_border_color(Color{ 242, 242, 242, 0 });
|
||||
set_border_bottom_width(1.0f);
|
||||
set_color(Color{ 255, 255, 255, 153 });
|
||||
set_padding_bottom(8.0f);
|
||||
set_text_transform(TextTransform::Uppercase);
|
||||
set_height_auto();
|
||||
hover_style.set_color(Color{ 255, 255, 255, 204 });
|
||||
checked_style.set_color(Color{ 255, 255, 255, 255 });
|
||||
checked_style.set_border_bottom_width(1.0f);
|
||||
checked_style.set_border_color(Color{ 242, 242, 242, 255 });
|
||||
|
||||
add_style(&hover_style, { hover_state });
|
||||
add_style(&checked_style, { checked_state });
|
||||
|
|
@ -70,10 +72,19 @@ namespace recompui {
|
|||
void Radio::option_selected(uint32_t index) {
|
||||
set_index_internal(index, false, true);
|
||||
}
|
||||
|
||||
void Radio::set_input_value(const ElementValue& val) {
|
||||
std::visit(overloaded {
|
||||
[this](uint32_t u) { set_index(u); },
|
||||
[this](float f) { set_index(f); },
|
||||
[this](double d) { set_index(d); },
|
||||
[](std::monostate) {}
|
||||
}, val);
|
||||
}
|
||||
|
||||
Radio::Radio(Element *parent) : Container(parent, FlexDirection::Row, JustifyContent::FlexStart) {
|
||||
set_gap(24.0f);
|
||||
set_flex_grow(0.0f);
|
||||
set_align_items(AlignItems::FlexStart);
|
||||
}
|
||||
|
||||
Radio::~Radio() {
|
||||
|
|
|
|||
|
|
@ -26,6 +26,8 @@ namespace recompui {
|
|||
|
||||
void set_index_internal(uint32_t index, bool setup, bool trigger_callbacks);
|
||||
void option_selected(uint32_t index);
|
||||
void set_input_value(const ElementValue& val) override;
|
||||
ElementValue get_element_value() override { return get_index(); }
|
||||
public:
|
||||
Radio(Element *parent);
|
||||
virtual ~Radio();
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
#include "overloaded.h"
|
||||
#include "ui_slider.h"
|
||||
|
||||
#include <cmath>
|
||||
|
|
@ -44,7 +45,8 @@ namespace recompui {
|
|||
|
||||
void Slider::update_circle_position() {
|
||||
double ratio = std::clamp((value - min_value) / (max_value - min_value), 0.0, 1.0);
|
||||
circle_element->set_left(slider_width_dp * ratio);
|
||||
float slider_relative_left = slider_element->get_absolute_left() - get_absolute_left();
|
||||
circle_element->set_left(ratio * 100.0, Unit::Percent);
|
||||
}
|
||||
|
||||
void Slider::update_label_text() {
|
||||
|
|
@ -60,13 +62,23 @@ namespace recompui {
|
|||
|
||||
value_label->set_text(text_buffer);
|
||||
}
|
||||
|
||||
void Slider::set_input_value(const ElementValue& val) {
|
||||
std::visit(overloaded {
|
||||
[this](uint32_t u) { set_value(u); },
|
||||
[this](float f) { set_value(f); },
|
||||
[this](double d) { set_value(d); },
|
||||
[](std::monostate) {}
|
||||
}, val);
|
||||
}
|
||||
|
||||
Slider::Slider(Element *parent, SliderType type) : Element(parent) {
|
||||
this->type = type;
|
||||
|
||||
set_display(Display::Flex);
|
||||
set_flex(1.0f, 1.0f, 100.0f, Unit::Percent);
|
||||
set_flex_direction(FlexDirection::Row);
|
||||
set_text_align(TextAlign::Left);
|
||||
set_min_width(120.0f);
|
||||
|
||||
ContextId context = get_current_context();
|
||||
|
||||
|
|
@ -76,7 +88,7 @@ namespace recompui {
|
|||
value_label->set_max_width(60.0f);
|
||||
|
||||
slider_element = context.create_element<Element>(this);
|
||||
slider_element->set_width(slider_width_dp);
|
||||
slider_element->set_flex(1.0f, 0.0f);
|
||||
|
||||
{
|
||||
bar_element = context.create_element<Clickable>(slider_element, true);
|
||||
|
|
@ -87,11 +99,11 @@ namespace recompui {
|
|||
bar_element->add_pressed_callback([this](float x, float y){ bar_clicked(x, y); });
|
||||
bar_element->add_dragged_callback([this](float x, float y, recompui::DragPhase phase){ bar_dragged(x, y, phase); });
|
||||
|
||||
circle_element = context.create_element<Clickable>(slider_element, true);
|
||||
circle_element = context.create_element<Clickable>(bar_element, true);
|
||||
circle_element->set_position(Position::Relative);
|
||||
circle_element->set_width(16.0f);
|
||||
circle_element->set_height(16.0f);
|
||||
circle_element->set_margin_top(-8.0f);
|
||||
circle_element->set_margin_top(-7.0f);
|
||||
circle_element->set_margin_right(-8.0f);
|
||||
circle_element->set_margin_left(-8.0f);
|
||||
circle_element->set_background_color(Color{ 204, 204, 204, 255 });
|
||||
|
|
|
|||
|
|
@ -22,7 +22,6 @@ namespace recompui {
|
|||
double min_value = 0.0;
|
||||
double max_value = 100.0;
|
||||
double step_value = 0.0;
|
||||
float slider_width_dp = 300.0;
|
||||
std::vector<std::function<void(double)>> value_changed_callbacks;
|
||||
|
||||
void set_value_internal(double v, bool setup, bool trigger_callbacks);
|
||||
|
|
@ -32,6 +31,8 @@ namespace recompui {
|
|||
void update_value_from_mouse(float x);
|
||||
void update_circle_position();
|
||||
void update_label_text();
|
||||
void set_input_value(const ElementValue& val) override;
|
||||
ElementValue get_element_value() override { return get_value(); }
|
||||
|
||||
public:
|
||||
Slider(Element *parent, SliderType type);
|
||||
|
|
|
|||
|
|
@ -21,9 +21,11 @@ namespace recompui {
|
|||
}
|
||||
}
|
||||
|
||||
TextInput::TextInput(Element *parent) : Element(parent, Events(EventType::Text), "input") {
|
||||
TextInput::TextInput(Element *parent, bool text_visible) : Element(parent, Events(EventType::Text), "input") {
|
||||
if (!text_visible) {
|
||||
set_attribute("type", "password");
|
||||
}
|
||||
set_min_width(60.0f);
|
||||
set_max_width(400.0f);
|
||||
set_border_color(Color{ 242, 242, 242, 255 });
|
||||
set_border_bottom_width(1.0f);
|
||||
set_padding_bottom(6.0f);
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ namespace recompui {
|
|||
protected:
|
||||
virtual void process_event(const Event &e) override;
|
||||
public:
|
||||
TextInput(Element *parent);
|
||||
TextInput(Element *parent, bool text_visible = true);
|
||||
void set_text(std::string_view text);
|
||||
const std::string &get_text();
|
||||
void add_text_changed_callback(std::function<void(const std::string &)> callback);
|
||||
|
|
|
|||
|
|
@ -116,6 +116,16 @@ void recompui_destroy_element(uint8_t* rdram, recomp_context* ctx) {
|
|||
}
|
||||
}
|
||||
|
||||
void recompui_create_button(uint8_t* rdram, recomp_context* ctx) {
|
||||
ContextId ui_context = get_context(rdram, ctx);
|
||||
Element* parent = arg_element<1>(rdram, ctx, ui_context);
|
||||
std::string text = _arg_string<2>(rdram, ctx);
|
||||
uint32_t style = _arg<3, uint32_t>(rdram, ctx);
|
||||
|
||||
Button* ret = ui_context.create_element<Button>(parent, text, static_cast<ButtonStyle>(style));
|
||||
return_resource(ctx, ret->get_resource_id());
|
||||
}
|
||||
|
||||
void recompui_create_label(uint8_t* rdram, recomp_context* ctx) {
|
||||
ContextId ui_context = get_context(rdram, ctx);
|
||||
Element* parent = arg_element<1>(rdram, ctx, ui_context);
|
||||
|
|
@ -143,13 +153,43 @@ void recompui_create_textinput(uint8_t* rdram, recomp_context* ctx) {
|
|||
return_resource(ctx, ret->get_resource_id());
|
||||
}
|
||||
|
||||
void recompui_create_button(uint8_t* rdram, recomp_context* ctx) {
|
||||
void recompui_create_passwordinput(uint8_t* rdram, recomp_context* ctx) {
|
||||
ContextId ui_context = get_context(rdram, ctx);
|
||||
Element* parent = arg_element<1>(rdram, ctx, ui_context);
|
||||
std::string text = _arg_string<2>(rdram, ctx);
|
||||
uint32_t style = _arg<3, uint32_t>(rdram, ctx);
|
||||
|
||||
Button* ret = ui_context.create_element<Button>(parent, text, static_cast<ButtonStyle>(style));
|
||||
Element* ret = ui_context.create_element<TextInput>(parent, false);
|
||||
return_resource(ctx, ret->get_resource_id());
|
||||
}
|
||||
|
||||
void recompui_create_labelradio(uint8_t* rdram, recomp_context* ctx) {
|
||||
ContextId ui_context = get_context(rdram, ctx);
|
||||
Element* parent = arg_element<1>(rdram, ctx, ui_context);
|
||||
PTR(PTR(char)) options = _arg<2, PTR(PTR(char))>(rdram, ctx);
|
||||
uint32_t num_options = _arg<3, uint32_t>(rdram, ctx);
|
||||
|
||||
Radio* ret = ui_context.create_element<Radio>(parent);
|
||||
|
||||
for (size_t i = 0; i < num_options; i++) {
|
||||
ret->add_option(decode_string(rdram, MEM_W(sizeof(uint32_t) * i, options)));
|
||||
}
|
||||
|
||||
return_resource(ctx, ret->get_resource_id());
|
||||
}
|
||||
|
||||
void recompui_create_slider(uint8_t* rdram, recomp_context* ctx) {
|
||||
ContextId ui_context = get_context(rdram, ctx);
|
||||
Element* parent = arg_element<1>(rdram, ctx, ui_context);
|
||||
uint32_t type = _arg<2, uint32_t>(rdram, ctx);
|
||||
float min_value = arg_float3(rdram, ctx);
|
||||
float max_value = arg_float4(rdram, ctx);
|
||||
float step = arg_float5(rdram, ctx);
|
||||
float initial_value = arg_float6(rdram, ctx);
|
||||
|
||||
Slider* ret = ui_context.create_element<Slider>(parent, static_cast<SliderType>(type));
|
||||
ret->set_min_value(min_value);
|
||||
ret->set_max_value(max_value);
|
||||
ret->set_step_value(step);
|
||||
ret->set_value(initial_value);
|
||||
return_resource(ctx, ret->get_resource_id());
|
||||
}
|
||||
|
||||
|
|
@ -699,7 +739,33 @@ void recompui_set_tab_index(uint8_t* rdram, recomp_context* ctx) {
|
|||
resource->set_tab_index(static_cast<TabIndex>(tab_index));
|
||||
}
|
||||
|
||||
// Text
|
||||
// Values
|
||||
void recompui_get_input_value_u32(uint8_t* rdram, recomp_context* ctx) {
|
||||
Style* resource = arg_style<0>(rdram, ctx);
|
||||
|
||||
if (!resource->is_element()) {
|
||||
recompui::message_box("Fatal error in mod - attempted to get value of non-element");
|
||||
assert(false);
|
||||
ultramodern::error_handling::quick_exit(__FILE__, __LINE__, __FUNCTION__);
|
||||
}
|
||||
|
||||
Element* element = static_cast<Element*>(resource);
|
||||
_return<uint32_t>(ctx, element->get_input_value_u32());
|
||||
}
|
||||
|
||||
void recompui_get_input_value_float(uint8_t* rdram, recomp_context* ctx) {
|
||||
Style* resource = arg_style<0>(rdram, ctx);
|
||||
|
||||
if (!resource->is_element()) {
|
||||
recompui::message_box("Fatal error in mod - attempted to get value of non-element");
|
||||
assert(false);
|
||||
ultramodern::error_handling::quick_exit(__FILE__, __LINE__, __FUNCTION__);
|
||||
}
|
||||
|
||||
Element* element = static_cast<Element*>(resource);
|
||||
_return<float>(ctx, element->get_input_value_float());
|
||||
}
|
||||
|
||||
void recompui_get_input_text(uint8_t* rdram, recomp_context* ctx) {
|
||||
Style* resource = arg_style<0>(rdram, ctx);
|
||||
|
||||
|
|
@ -714,6 +780,34 @@ void recompui_get_input_text(uint8_t* rdram, recomp_context* ctx) {
|
|||
return_string(rdram, ctx, ret);
|
||||
}
|
||||
|
||||
void recompui_set_input_value_u32(uint8_t* rdram, recomp_context* ctx) {
|
||||
Style* resource = arg_style<0>(rdram, ctx);
|
||||
uint32_t value = _arg<1, uint32_t>(rdram, ctx);
|
||||
|
||||
if (!resource->is_element()) {
|
||||
recompui::message_box("Fatal error in mod - attempted to set value of non-element");
|
||||
assert(false);
|
||||
ultramodern::error_handling::quick_exit(__FILE__, __LINE__, __FUNCTION__);
|
||||
}
|
||||
|
||||
Element* element = static_cast<Element*>(resource);
|
||||
element->set_input_value_u32(value);
|
||||
}
|
||||
|
||||
void recompui_set_input_value_float(uint8_t* rdram, recomp_context* ctx) {
|
||||
Style* resource = arg_style<0>(rdram, ctx);
|
||||
float value = _arg_float_a1(rdram, ctx);
|
||||
|
||||
if (!resource->is_element()) {
|
||||
recompui::message_box("Fatal error in mod - attempted to set value of non-element");
|
||||
assert(false);
|
||||
ultramodern::error_handling::quick_exit(__FILE__, __LINE__, __FUNCTION__);
|
||||
}
|
||||
|
||||
Element* element = static_cast<Element*>(resource);
|
||||
element->set_input_value_float(value);
|
||||
}
|
||||
|
||||
void recompui_set_input_text(uint8_t* rdram, recomp_context* ctx) {
|
||||
Style* resource = arg_style<0>(rdram, ctx);
|
||||
|
||||
|
|
@ -766,10 +860,13 @@ void recompui::register_ui_exports() {
|
|||
REGISTER_FUNC(recompui_create_style);
|
||||
REGISTER_FUNC(recompui_create_element);
|
||||
REGISTER_FUNC(recompui_destroy_element);
|
||||
REGISTER_FUNC(recompui_create_button);
|
||||
REGISTER_FUNC(recompui_create_label);
|
||||
// REGISTER_FUNC(recompui_create_span);
|
||||
REGISTER_FUNC(recompui_create_textinput);
|
||||
REGISTER_FUNC(recompui_create_button);
|
||||
REGISTER_FUNC(recompui_create_passwordinput);
|
||||
REGISTER_FUNC(recompui_create_labelradio);
|
||||
REGISTER_FUNC(recompui_create_slider);
|
||||
REGISTER_FUNC(recompui_set_visibility);
|
||||
REGISTER_FUNC(recompui_set_position);
|
||||
REGISTER_FUNC(recompui_set_left);
|
||||
|
|
@ -841,7 +938,11 @@ void recompui::register_ui_exports() {
|
|||
REGISTER_FUNC(recompui_set_column_gap);
|
||||
REGISTER_FUNC(recompui_set_drag);
|
||||
REGISTER_FUNC(recompui_set_tab_index);
|
||||
REGISTER_FUNC(recompui_get_input_value_u32);
|
||||
REGISTER_FUNC(recompui_get_input_value_float);
|
||||
REGISTER_FUNC(recompui_get_input_text);
|
||||
REGISTER_FUNC(recompui_set_input_value_u32);
|
||||
REGISTER_FUNC(recompui_set_input_value_float);
|
||||
REGISTER_FUNC(recompui_set_input_text);
|
||||
REGISTER_FUNC(recompui_register_callback);
|
||||
register_ui_image_exports();
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
#include "concurrentqueue.h"
|
||||
|
||||
#include "overloaded.h"
|
||||
#include "recomp_ui.h"
|
||||
|
||||
#include "core/ui_context.h"
|
||||
|
|
@ -24,11 +25,6 @@
|
|||
|
||||
#include "../patches/ui_funcs.h"
|
||||
|
||||
template<class... Ts>
|
||||
struct overloaded : Ts... { using Ts::operator()...; };
|
||||
template<class... Ts>
|
||||
overloaded(Ts...) -> overloaded<Ts...>;
|
||||
|
||||
struct QueuedCallback {
|
||||
recompui::ResourceId resource;
|
||||
recompui::Event event;
|
||||
|
|
|
|||
|
|
@ -67,6 +67,7 @@ ConfigOptionSlider::ConfigOptionSlider(Element *parent, double value, double min
|
|||
this->callback = callback;
|
||||
|
||||
slider = get_current_context().create_element<Slider>(this, percent ? SliderType::Percent : SliderType::Double);
|
||||
slider->set_max_width(380.0f);
|
||||
slider->set_min_value(min_value);
|
||||
slider->set_max_value(max_value);
|
||||
slider->set_step_value(step_value);
|
||||
|
|
@ -84,6 +85,7 @@ ConfigOptionTextInput::ConfigOptionTextInput(Element *parent, std::string_view v
|
|||
this->callback = callback;
|
||||
|
||||
text_input = get_current_context().create_element<TextInput>(this);
|
||||
text_input->set_max_width(400.0f);
|
||||
text_input->set_text(value);
|
||||
text_input->add_text_changed_callback([this](const std::string &text){ text_changed(text); });
|
||||
}
|
||||
|
|
@ -147,7 +149,7 @@ ConfigSubMenu::ConfigSubMenu(Element *parent) : Element(parent) {
|
|||
header_container = context.create_element<Container>(this, FlexDirection::Row, JustifyContent::FlexStart);
|
||||
header_container->set_flex_grow(0.0f);
|
||||
header_container->set_align_items(AlignItems::Center);
|
||||
header_container->set_padding_left(12.0f);
|
||||
header_container->set_padding(12.0f);
|
||||
header_container->set_gap(24.0f);
|
||||
|
||||
{
|
||||
|
|
|
|||
|
|
@ -18,6 +18,56 @@ inline ContextId get_context(uint8_t* rdram, recomp_context* ctx) {
|
|||
return ContextId{ .slot_id = context_id };
|
||||
}
|
||||
|
||||
inline float arg_float2(uint8_t* rdram, recomp_context* ctx) {
|
||||
union {
|
||||
float f32;
|
||||
uint32_t u32;
|
||||
} val;
|
||||
|
||||
val.u32 = _arg<2, uint32_t>(rdram, ctx);
|
||||
return val.f32;
|
||||
}
|
||||
|
||||
inline float arg_float3(uint8_t* rdram, recomp_context* ctx) {
|
||||
union {
|
||||
float f32;
|
||||
uint32_t u32;
|
||||
} val;
|
||||
|
||||
val.u32 = _arg<3, uint32_t>(rdram, ctx);
|
||||
return val.f32;
|
||||
}
|
||||
|
||||
inline float arg_float4(uint8_t* rdram, recomp_context* ctx) {
|
||||
union {
|
||||
float f32;
|
||||
uint32_t u32;
|
||||
} val;
|
||||
|
||||
val.u32 = MEM_W(0x10, ctx->r29);
|
||||
return val.f32;
|
||||
}
|
||||
|
||||
inline float arg_float5(uint8_t* rdram, recomp_context* ctx) {
|
||||
union {
|
||||
float f32;
|
||||
uint32_t u32;
|
||||
} val;
|
||||
|
||||
val.u32 = MEM_W(0x14, ctx->r29);
|
||||
return val.f32;
|
||||
}
|
||||
|
||||
inline float arg_float6(uint8_t* rdram, recomp_context* ctx) {
|
||||
union {
|
||||
float f32;
|
||||
uint32_t u32;
|
||||
} val;
|
||||
|
||||
val.u32 = MEM_W(0x18, ctx->r29);
|
||||
return val.f32;
|
||||
}
|
||||
|
||||
template <int arg_index>
|
||||
ResourceId arg_resource_id(uint8_t* rdram, recomp_context* ctx) {
|
||||
uint32_t slot_id = _arg<arg_index, uint32_t>(rdram, ctx);
|
||||
|
|
@ -82,6 +132,23 @@ inline void return_string(uint8_t* rdram, recomp_context* ctx, const std::string
|
|||
|
||||
_return<PTR(char)>(ctx, addr);
|
||||
}
|
||||
|
||||
inline std::string decode_string(uint8_t* rdram, PTR(char) str) {
|
||||
// Get the length of the byteswapped string.
|
||||
size_t len = 0;
|
||||
while (MEM_B(str, len) != 0x00) {
|
||||
len++;
|
||||
}
|
||||
|
||||
std::string ret{};
|
||||
ret.reserve(len + 1);
|
||||
|
||||
for (size_t i = 0; i < len; i++) {
|
||||
ret += (char)MEM_B(str, i);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
@ -617,6 +617,11 @@ void draw_hook(RT64::RenderCommandList* command_list, RT64::RenderFramebuffer* s
|
|||
case SDL_EventType::SDL_KEYDOWN:
|
||||
non_mouse_interacted = true;
|
||||
kb_interacted = true;
|
||||
if (cur_event.key.keysym.scancode == SDL_Scancode::SDL_SCANCODE_F8) {
|
||||
if (zelda64::get_debug_mode_enabled()) {
|
||||
Rml::Debugger::SetVisible(!Rml::Debugger::IsVisible());
|
||||
}
|
||||
}
|
||||
break;
|
||||
case SDL_EventType::SDL_USEREVENT:
|
||||
if (cur_event.user.code == SDL_GameControllerAxis::SDL_CONTROLLER_AXIS_LEFTY) {
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue