diff --git a/CMakeLists.txt b/CMakeLists.txt index 637e8b1..e84ed83 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -179,6 +179,7 @@ set (SOURCES ${CMAKE_SOURCE_DIR}/src/ui/elements/ui_radio.cpp ${CMAKE_SOURCE_DIR}/src/ui/elements/ui_scroll_container.cpp ${CMAKE_SOURCE_DIR}/src/ui/elements/ui_slider.cpp + ${CMAKE_SOURCE_DIR}/src/ui/elements/ui_span.cpp ${CMAKE_SOURCE_DIR}/src/ui/elements/ui_style.cpp ${CMAKE_SOURCE_DIR}/src/ui/elements/ui_text_input.cpp ${CMAKE_SOURCE_DIR}/src/ui/elements/ui_toggle.cpp diff --git a/patches/play_patches.c b/patches/play_patches.c index 04f7b88..1b6307a 100644 --- a/patches/play_patches.c +++ b/patches/play_patches.c @@ -179,7 +179,7 @@ RECOMP_PATCH void Play_Init(GameState* thisx) { if (CHECK_EVENTINF(EVENTINF_TRIGGER_DAYTELOP)) { CLEAR_EVENTINF(EVENTINF_TRIGGER_DAYTELOP); STOP_GAMESTATE(&this->state); - // Use non-relocatable reference to DayTelop_Init instead. + // @recomp Use non-relocatable reference to DayTelop_Init instead. SET_NEXT_GAMESTATE(&this->state, DayTelop_Init_NORELOCATE, sizeof(DayTelopState)); return; } @@ -195,7 +195,7 @@ RECOMP_PATCH void Play_Init(GameState* thisx) { if (gSaveContext.save.entrance == -1) { gSaveContext.save.entrance = 0; STOP_GAMESTATE(&this->state); - // Use non-relocatable reference to TitleSetup_Init instead. + // @recomp Use non-relocatable reference to TitleSetup_Init instead. SET_NEXT_GAMESTATE(&this->state, TitleSetup_Init_NORELOCATE, sizeof(TitleSetupState)); return; } diff --git a/src/ui/elements/ui_element.cpp b/src/ui/elements/ui_element.cpp index efb35d7..e53cd4b 100644 --- a/src/ui/elements/ui_element.cpp +++ b/src/ui/elements/ui_element.cpp @@ -247,9 +247,18 @@ bool Element::is_enabled() const { } void Element::set_text(std::string_view text) { + // TODO escape this base->SetInnerRML(std::string(text)); } +std::string Element::get_input_text() { + return base->GetAttribute("value", std::string{}); +} + +void Element::set_input_text(std::string_view val) { + base->SetAttribute("value", std::string{ val }); +} + void Element::set_src(std::string_view src) { base->SetAttribute("src", std::string(src)); } @@ -317,8 +326,8 @@ void Element::queue_update() { cur_context.queue_element_update(resource_id); } -void Element::register_callback(PTR(void) callback, PTR(void) userdata) { - callbacks.emplace_back(UICallback{.callback = callback, .userdata = userdata}); +void Element::register_callback(ContextId context, PTR(void) callback, PTR(void) userdata) { + callbacks.emplace_back(UICallback{.context = context, .callback = callback, .userdata = userdata}); } } \ No newline at end of file diff --git a/src/ui/elements/ui_element.h b/src/ui/elements/ui_element.h index 319615f..0897e72 100644 --- a/src/ui/elements/ui_element.h +++ b/src/ui/elements/ui_element.h @@ -10,6 +10,7 @@ namespace recompui { struct UICallback { + ContextId context; PTR(void) callback; PTR(void) userdata; }; @@ -63,6 +64,8 @@ public: void set_enabled(bool enabled); bool is_enabled() const; void set_text(std::string_view text); + std::string get_input_text(); + void set_input_text(std::string_view text); void set_src(std::string_view src); void set_style_enabled(std::string_view style_name, bool enabled); bool is_element() override { return true; } @@ -73,7 +76,7 @@ public: float get_client_width(); float get_client_height(); void queue_update(); - void register_callback(PTR(void) callback, PTR(void) userdata); + void register_callback(ContextId context, PTR(void) callback, PTR(void) userdata); }; void queue_ui_callback(recompui::ResourceId resource, const Event& e, const UICallback& callback); diff --git a/src/ui/elements/ui_span.cpp b/src/ui/elements/ui_span.cpp new file mode 100644 index 0000000..0cd8ef1 --- /dev/null +++ b/src/ui/elements/ui_span.cpp @@ -0,0 +1,15 @@ +#include "ui_span.h" + +#include + +namespace recompui { + + Span::Span(Element *parent) : Element(parent, 0, "span") { + set_font_style(FontStyle::Normal); + } + + Span::Span(Element *parent, const std::string &text) : Span(parent) { + set_text(text); + } + +}; diff --git a/src/ui/elements/ui_span.h b/src/ui/elements/ui_span.h new file mode 100644 index 0000000..d74c53d --- /dev/null +++ b/src/ui/elements/ui_span.h @@ -0,0 +1,14 @@ +#pragma once + +#include "ui_element.h" +#include "ui_label.h" + +namespace recompui { + + class Span : public Element { + public: + Span(Element *parent); + Span(Element *parent, const std::string &text); + }; + +} // namespace recompui \ No newline at end of file diff --git a/src/ui/ui_api.cpp b/src/ui/ui_api.cpp index 8bab53b..ff2ba2f 100644 --- a/src/ui/ui_api.cpp +++ b/src/ui/ui_api.cpp @@ -12,6 +12,7 @@ #include "elements/ui_radio.h" #include "elements/ui_scroll_container.h" #include "elements/ui_slider.h" +#include "elements/ui_span.h" #include "elements/ui_style.h" #include "elements/ui_text_input.h" #include "elements/ui_toggle.h" @@ -19,6 +20,7 @@ #include "librecomp/overlays.hpp" #include "librecomp/helpers.hpp" +#include "librecomp/addresses.hpp" #include "ultramodern/error_handling.hpp" using namespace recompui; @@ -32,26 +34,6 @@ ContextId get_context(uint8_t* rdram, recomp_context* ctx) { return ContextId{ .slot_id = context_id }; } -template -std::string arg_string(uint8_t* rdram, recomp_context* ctx) { - PTR(char) str = _arg(rdram, ctx); - - // 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; -} - template ResourceId arg_resource_id(uint8_t* rdram, recomp_context* ctx) { uint32_t slot_id = _arg(rdram, ctx); @@ -106,6 +88,17 @@ void return_resource(recomp_context* ctx, ResourceId resource) { _return(ctx, resource.slot_id); } +void return_string(uint8_t* rdram, recomp_context* ctx, const std::string& ret) { + gpr addr = (reinterpret_cast(recomp::alloc(rdram, ret.size() + 1)) - rdram) + 0xFFFFFFFF80000000ULL; + + for (size_t i = 0; i < ret.size(); i++) { + MEM_B(i, addr) = ret[i]; + } + MEM_B(ret.size(), addr) = '\x00'; + + _return(ctx, addr); +} + // Contexts void recompui_create_context(uint8_t* rdram, recomp_context* ctx) { (void)rdram; @@ -161,10 +154,37 @@ void recompui_create_element(uint8_t* rdram, recomp_context* ctx) { 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); + std::string text = _arg_string<2>(rdram, ctx); + uint32_t style = _arg<3, uint32_t>(rdram, ctx); + + Element* ret = ui_context.create_element