mirror of
https://github.com/Mr-Wiseguy/Zelda64Recomp.git
synced 2025-04-07 05:56:53 +02:00
Created mod UI API functions for setting visibility, setting text, and destroying elements
This commit is contained in:
parent
2dffaf6148
commit
bb10d5d090
@ -33,7 +33,7 @@ namespace recompui {
|
||||
Rml::ElementDocument* document;
|
||||
Element root_element;
|
||||
std::vector<Element*> loose_elements;
|
||||
std::unordered_set<ResourceId> to_update;
|
||||
std::unordered_set<ResourceId> to_update;
|
||||
bool captures_input = true;
|
||||
bool captures_mouse = true;
|
||||
Context(Rml::ElementDocument* document) : document(document), root_element(document) {}
|
||||
@ -309,6 +309,15 @@ void recompui::ContextId::open() {
|
||||
opened_context_id = *this;
|
||||
}
|
||||
|
||||
bool recompui::ContextId::open_if_not_already() {
|
||||
if (opened_context_id == *this) {
|
||||
return false;
|
||||
}
|
||||
|
||||
open();
|
||||
return true;
|
||||
}
|
||||
|
||||
void recompui::ContextId::close() {
|
||||
// Ensure a context is currently opened by this thread.
|
||||
if (opened_context_id == ContextId::null()) {
|
||||
|
@ -42,6 +42,7 @@ namespace recompui {
|
||||
Element* get_root_element();
|
||||
|
||||
void open();
|
||||
bool open_if_not_already();
|
||||
void close();
|
||||
void process_updates();
|
||||
|
||||
|
@ -4,7 +4,7 @@
|
||||
|
||||
namespace recompui {
|
||||
|
||||
Button::Button(Element *parent, const std::string &text, ButtonStyle style) : Element(parent, Events(EventType::Click, EventType::Hover, EventType::Enable), "button") {
|
||||
Button::Button(Element *parent, const std::string &text, ButtonStyle style) : Element(parent, Events(EventType::Click, EventType::Hover, EventType::Enable), "button", true) {
|
||||
this->style = style;
|
||||
|
||||
set_text(text);
|
||||
|
@ -1,3 +1,5 @@
|
||||
#include "RmlUi/Core/StringUtilities.h"
|
||||
|
||||
#include "ui_element.h"
|
||||
#include "../core/ui_context.h"
|
||||
|
||||
@ -13,7 +15,7 @@ Element::Element(Rml::Element *base) {
|
||||
this->shim = true;
|
||||
}
|
||||
|
||||
Element::Element(Element* parent, uint32_t events_enabled, Rml::String base_class) {
|
||||
Element::Element(Element* parent, uint32_t events_enabled, Rml::String base_class, bool can_set_text) : can_set_text(can_set_text) {
|
||||
ContextId context = get_current_context();
|
||||
base_owning = context.get_document()->CreateElement(base_class);
|
||||
|
||||
@ -39,6 +41,10 @@ Element::~Element() {
|
||||
|
||||
void Element::add_child(Element *child) {
|
||||
assert(child != nullptr);
|
||||
if (can_set_text) {
|
||||
assert(false && "Elements with settable text cannot have children");
|
||||
return;
|
||||
}
|
||||
|
||||
children.emplace_back(child);
|
||||
|
||||
@ -134,9 +140,11 @@ void Element::ProcessEvent(Rml::Event &event) {
|
||||
context = get_context_from_document(doc);
|
||||
}
|
||||
|
||||
bool did_open = false;
|
||||
|
||||
// TODO disallow null contexts once the entire UI system has been migrated.
|
||||
if (context != ContextId::null()) {
|
||||
context.open();
|
||||
did_open = context.open_if_not_already();
|
||||
}
|
||||
|
||||
// Events that are processed during any phase.
|
||||
@ -187,7 +195,7 @@ void Element::ProcessEvent(Rml::Event &event) {
|
||||
}
|
||||
}
|
||||
|
||||
if (context != ContextId::null()) {
|
||||
if (context != ContextId::null() && did_open) {
|
||||
context.close();
|
||||
}
|
||||
}
|
||||
@ -215,6 +223,24 @@ void Element::clear_children() {
|
||||
children.clear();
|
||||
}
|
||||
|
||||
bool Element::remove_child(ResourceId child) {
|
||||
bool found = false;
|
||||
|
||||
ContextId context = get_current_context();
|
||||
|
||||
for (auto it = children.begin(); it != children.end(); ++it) {
|
||||
Element* cur_child = *it;
|
||||
if (cur_child->get_resource_id() == child) {
|
||||
children.erase(it);
|
||||
context.destroy_resource(cur_child);
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return found;
|
||||
}
|
||||
|
||||
void Element::add_style(Style *style, const std::string_view style_name) {
|
||||
add_style(style, { style_name });
|
||||
}
|
||||
@ -247,8 +273,13 @@ bool Element::is_enabled() const {
|
||||
}
|
||||
|
||||
void Element::set_text(std::string_view text) {
|
||||
// TODO escape this
|
||||
base->SetInnerRML(std::string(text));
|
||||
if (can_set_text) {
|
||||
// Escape the string into Rml to prevent element injection.
|
||||
base->SetInnerRML(Rml::StringUtilities::EncodeRml(std::string(text)));
|
||||
}
|
||||
else {
|
||||
assert(false && "Attempted to set text of an element that cannot have its text set.");
|
||||
}
|
||||
}
|
||||
|
||||
std::string Element::get_input_text() {
|
||||
|
@ -34,6 +34,7 @@ private:
|
||||
bool enabled = true;
|
||||
bool disabled_attribute = false;
|
||||
bool disabled_from_parent = false;
|
||||
bool can_set_text = false;
|
||||
|
||||
void add_child(Element *child);
|
||||
void register_event_listeners(uint32_t events_enabled);
|
||||
@ -56,9 +57,11 @@ public:
|
||||
Element(Rml::Element *base);
|
||||
|
||||
// Used to actually construct elements.
|
||||
Element(Element* parent, uint32_t events_enabled = 0, Rml::String base_class = "div");
|
||||
Element(Element* parent, uint32_t events_enabled = 0, Rml::String base_class = "div", bool can_set_text = false);
|
||||
virtual ~Element();
|
||||
void clear_children();
|
||||
bool remove_child(ResourceId child);
|
||||
bool remove_child(Element *child) { remove_child(child->get_resource_id()); }
|
||||
void add_style(Style *style, std::string_view style_name);
|
||||
void add_style(Style *style, const std::initializer_list<std::string_view> &style_names);
|
||||
void set_enabled(bool enabled);
|
||||
|
@ -4,7 +4,7 @@
|
||||
|
||||
namespace recompui {
|
||||
|
||||
Label::Label(Element *parent, LabelStyle label_style) : Element(parent) {
|
||||
Label::Label(Element *parent, LabelStyle label_style) : Element(parent, 0U, "div", true) {
|
||||
switch (label_style) {
|
||||
case LabelStyle::Annotation:
|
||||
set_color(Color{ 185, 125, 242, 255 });
|
||||
|
@ -4,7 +4,7 @@ namespace recompui {
|
||||
|
||||
// RadioOption
|
||||
|
||||
RadioOption::RadioOption(Element *parent, std::string_view name, uint32_t index) : Element(parent, Events(EventType::Click, EventType::Focus, EventType::Hover, EventType::Enable), "label") {
|
||||
RadioOption::RadioOption(Element *parent, std::string_view name, uint32_t index) : Element(parent, Events(EventType::Click, EventType::Focus, EventType::Hover, EventType::Enable), "label", true) {
|
||||
this->index = index;
|
||||
|
||||
set_text(name);
|
||||
|
@ -4,7 +4,7 @@
|
||||
|
||||
namespace recompui {
|
||||
|
||||
Span::Span(Element *parent) : Element(parent, 0, "span") {
|
||||
Span::Span(Element *parent) : Element(parent, 0, "span", true) {
|
||||
set_font_style(FontStyle::Normal);
|
||||
}
|
||||
|
||||
|
@ -181,6 +181,17 @@ namespace recompui {
|
||||
|
||||
}
|
||||
|
||||
void Style::set_visibility(Visibility visibility) {
|
||||
switch (visibility) {
|
||||
case Visibility::Visible:
|
||||
set_property(Rml::PropertyId::Visibility, Rml::Style::Visibility::Visible);
|
||||
break;
|
||||
case Visibility::Hidden:
|
||||
set_property(Rml::PropertyId::Visibility, Rml::Style::Visibility::Hidden);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void Style::set_position(Position position) {
|
||||
switch (position) {
|
||||
case Position::Absolute:
|
||||
|
@ -20,6 +20,7 @@ namespace recompui {
|
||||
public:
|
||||
Style();
|
||||
virtual ~Style();
|
||||
void set_visibility(Visibility visibility);
|
||||
void set_position(Position position);
|
||||
void set_left(float left, Unit unit = Unit::Dp);
|
||||
void set_top(float top, Unit unit = Unit::Dp);
|
||||
|
@ -152,6 +152,11 @@ namespace recompui {
|
||||
TableCell
|
||||
};
|
||||
|
||||
enum class Visibility {
|
||||
Visible,
|
||||
Hidden
|
||||
};
|
||||
|
||||
enum class Position {
|
||||
Absolute,
|
||||
Relative
|
||||
|
@ -168,6 +168,25 @@ void recompui_create_element(uint8_t* rdram, recomp_context* ctx) {
|
||||
return_resource(ctx, ret->get_resource_id());
|
||||
}
|
||||
|
||||
void recompui_destroy_element(uint8_t* rdram, recomp_context* ctx) {
|
||||
Style* parent_resource = arg_style<0>(rdram, ctx);
|
||||
|
||||
if (!parent_resource->is_element()) {
|
||||
recompui::message_box("Fatal error in mod - attempted to remove child from non-element");
|
||||
assert(false);
|
||||
ultramodern::error_handling::quick_exit(__FILE__, __LINE__, __FUNCTION__);
|
||||
}
|
||||
|
||||
Element* parent = static_cast<Element*>(parent_resource);
|
||||
ResourceId to_remove = arg_resource_id<1>(rdram, ctx);
|
||||
|
||||
if (!parent->remove_child(to_remove)) {
|
||||
recompui::message_box("Fatal error in mod - attempted to remove child from wrong parent");
|
||||
assert(false);
|
||||
ultramodern::error_handling::quick_exit(__FILE__, __LINE__, __FUNCTION__);
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
@ -206,6 +225,13 @@ void recompui_create_button(uint8_t* rdram, recomp_context* ctx) {
|
||||
}
|
||||
|
||||
// Position and Layout
|
||||
void recompui_set_visibility(uint8_t* rdram, recomp_context* ctx) {
|
||||
Style* resource = arg_style<0>(rdram, ctx);
|
||||
uint32_t visibility = _arg<1, uint32_t>(rdram, ctx);
|
||||
|
||||
resource->set_visibility(static_cast<Visibility>(visibility));
|
||||
}
|
||||
|
||||
void recompui_set_position(uint8_t* rdram, recomp_context* ctx) {
|
||||
Style* resource = arg_style<0>(rdram, ctx);
|
||||
uint32_t position = _arg<1, uint32_t>(rdram, ctx);
|
||||
@ -645,6 +671,19 @@ void recompui_set_overflow_y(uint8_t* rdram, recomp_context* ctx) {
|
||||
}
|
||||
|
||||
// Text and Fonts
|
||||
void recompui_set_text(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 set text of non-element");
|
||||
assert(false);
|
||||
ultramodern::error_handling::quick_exit(__FILE__, __LINE__, __FUNCTION__);
|
||||
}
|
||||
|
||||
Element* element = static_cast<Element*>(resource);
|
||||
element->set_text(_arg_string<1>(rdram, ctx));
|
||||
}
|
||||
|
||||
void recompui_set_font_size(uint8_t* rdram, recomp_context* ctx) {
|
||||
Style* resource = arg_style<0>(rdram, ctx);
|
||||
float size = _arg_float_a1(rdram, ctx);
|
||||
@ -731,12 +770,12 @@ void recompui_set_tab_index(uint8_t* rdram, recomp_context* ctx) {
|
||||
resource->set_tab_index(static_cast<TabIndex>(tab_index));
|
||||
}
|
||||
|
||||
// Getters
|
||||
// Text
|
||||
void recompui_get_input_text(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 text of non-element");
|
||||
recompui::message_box("Fatal error in mod - attempted to get input text of non-element");
|
||||
assert(false);
|
||||
ultramodern::error_handling::quick_exit(__FILE__, __LINE__, __FUNCTION__);
|
||||
}
|
||||
@ -746,12 +785,11 @@ void recompui_get_input_text(uint8_t* rdram, recomp_context* ctx) {
|
||||
return_string(rdram, ctx, ret);
|
||||
}
|
||||
|
||||
// Setters
|
||||
void recompui_set_input_text(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 set text of non-element");
|
||||
recompui::message_box("Fatal error in mod - attempted to set input text of non-element");
|
||||
assert(false);
|
||||
ultramodern::error_handling::quick_exit(__FILE__, __LINE__, __FUNCTION__);
|
||||
}
|
||||
@ -798,10 +836,12 @@ void recompui::register_ui_exports() {
|
||||
REGISTER_FUNC(recompui_set_context_captures_mouse);
|
||||
REGISTER_FUNC(recompui_create_style);
|
||||
REGISTER_FUNC(recompui_create_element);
|
||||
REGISTER_FUNC(recompui_destroy_element);
|
||||
REGISTER_FUNC(recompui_create_label);
|
||||
// REGISTER_FUNC(recompui_create_span);
|
||||
REGISTER_FUNC(recompui_create_textinput);
|
||||
REGISTER_FUNC(recompui_create_button);
|
||||
REGISTER_FUNC(recompui_set_visibility);
|
||||
REGISTER_FUNC(recompui_set_position);
|
||||
REGISTER_FUNC(recompui_set_left);
|
||||
REGISTER_FUNC(recompui_set_top);
|
||||
@ -860,6 +900,7 @@ void recompui::register_ui_exports() {
|
||||
REGISTER_FUNC(recompui_set_overflow);
|
||||
REGISTER_FUNC(recompui_set_overflow_x);
|
||||
REGISTER_FUNC(recompui_set_overflow_y);
|
||||
REGISTER_FUNC(recompui_set_text);
|
||||
REGISTER_FUNC(recompui_set_font_size);
|
||||
REGISTER_FUNC(recompui_set_letter_spacing);
|
||||
REGISTER_FUNC(recompui_set_line_height);
|
||||
|
Loading…
x
Reference in New Issue
Block a user