mirror of
https://github.com/Mr-Wiseguy/Zelda64Recomp.git
synced 2025-02-10 00:48:49 +01:00
Begin implementing mod UI API
This commit is contained in:
parent
563e645c85
commit
2f37efa8a5
@ -163,6 +163,7 @@ set (SOURCES
|
||||
${CMAKE_SOURCE_DIR}/src/ui/ui_elements.cpp
|
||||
${CMAKE_SOURCE_DIR}/src/ui/ui_mod_details_panel.cpp
|
||||
${CMAKE_SOURCE_DIR}/src/ui/ui_mod_menu.cpp
|
||||
${CMAKE_SOURCE_DIR}/src/ui/ui_api.cpp
|
||||
${CMAKE_SOURCE_DIR}/src/ui/util/hsv.cpp
|
||||
${CMAKE_SOURCE_DIR}/src/ui/core/ui_context.cpp
|
||||
${CMAKE_SOURCE_DIR}/src/ui/elements/ui_button.cpp
|
||||
|
@ -108,6 +108,7 @@ namespace recompui {
|
||||
|
||||
Rml::ElementPtr create_custom_element(Rml::Element* parent, std::string tag);
|
||||
Rml::ElementDocument* load_document(const std::filesystem::path& path);
|
||||
Rml::ElementDocument* create_empty_document();
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@ -599,6 +599,8 @@ int main(int argc, char** argv) {
|
||||
recomp::register_game(game);
|
||||
}
|
||||
|
||||
recompui::register_ui_exports();
|
||||
|
||||
zelda64::register_overlays();
|
||||
zelda64::register_patches();
|
||||
zelda64::load_config();
|
||||
|
@ -178,6 +178,34 @@ recompui::ContextId recompui::create_context(Rml::ElementDocument* document) {
|
||||
return create_context_impl(document);
|
||||
}
|
||||
|
||||
recompui::ContextId recompui::create_context() {
|
||||
Rml::ElementDocument* doc = create_empty_document();
|
||||
ContextId ret = create_context_impl(doc);
|
||||
Element* root = ret.get_root_element();
|
||||
// Mark the root element as not being a shim, as that's only needed for elements that were parented to Rml ones manually.
|
||||
root->shim = false;
|
||||
|
||||
// TODO move these defaults elsewhere. Copied from the existing rcss.
|
||||
ret.open();
|
||||
root->set_width(100.0f, Unit::Percent);
|
||||
root->set_height(100.0f, Unit::Percent);
|
||||
root->set_display(Display::Flex);
|
||||
root->set_opacity(1.0f);
|
||||
root->set_font_family("chiaro");
|
||||
root->set_font_style(FontStyle::Normal);
|
||||
root->set_font_weight(400);
|
||||
|
||||
float sz = 16.0f;
|
||||
float spacing = 0.0f;
|
||||
float sz_add = sz + 4;
|
||||
root->set_font_size(sz_add, Unit::Dp);
|
||||
root->set_letter_spacing(sz_add * spacing, Unit::Dp);
|
||||
root->set_line_height(sz_add, Unit::Dp);
|
||||
ret.close();
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void recompui::destroy_context(ContextId id) {
|
||||
bool existed = false;
|
||||
|
||||
@ -209,6 +237,8 @@ void recompui::destroy_context(ContextId id) {
|
||||
}
|
||||
|
||||
void recompui::destroy_all_contexts() {
|
||||
recompui::hide_all_contexts();
|
||||
|
||||
std::lock_guard lock{ context_state.all_contexts_lock };
|
||||
|
||||
// TODO prevent deletion of a context while its mutex is in use. Second lock on the context's mutex before popping
|
||||
|
@ -51,8 +51,11 @@ namespace recompui {
|
||||
|
||||
ContextId create_context(const std::filesystem::path& path);
|
||||
ContextId create_context(Rml::ElementDocument* document);
|
||||
ContextId create_context();
|
||||
void destroy_context(ContextId id);
|
||||
ContextId get_current_context();
|
||||
ContextId get_context_from_document(Rml::ElementDocument* document);
|
||||
void destroy_all_contexts();
|
||||
|
||||
void register_ui_exports();
|
||||
} // namespace recompui
|
||||
|
@ -8,6 +8,8 @@ namespace recompui {
|
||||
struct ResourceId {
|
||||
uint32_t slot_id;
|
||||
|
||||
bool operator==(const ResourceId& rhs) const = default;
|
||||
|
||||
const Style* operator*() const;
|
||||
Style* operator*();
|
||||
|
||||
|
@ -4,7 +4,7 @@
|
||||
|
||||
namespace recompui {
|
||||
|
||||
Button::Button(const std::string &text, ButtonStyle style, Element *parent) : 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") {
|
||||
this->style = style;
|
||||
|
||||
set_text(text);
|
||||
|
@ -20,7 +20,7 @@ namespace recompui {
|
||||
// Element overrides.
|
||||
virtual void process_event(const Event &e) override;
|
||||
public:
|
||||
Button(const std::string &text, ButtonStyle style, Element *parent);
|
||||
Button(Element *parent, const std::string &text, ButtonStyle style);
|
||||
void add_pressed_callback(std::function<void()> callback);
|
||||
};
|
||||
|
||||
|
@ -4,7 +4,7 @@
|
||||
|
||||
namespace recompui {
|
||||
|
||||
Container::Container(FlexDirection direction, JustifyContent justify_content, Element *parent) : Element(parent) {
|
||||
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);
|
||||
|
@ -6,7 +6,7 @@ namespace recompui {
|
||||
|
||||
class Container : public Element {
|
||||
public:
|
||||
Container(FlexDirection direction, JustifyContent justify_content, Element *parent);
|
||||
Container(Element* parent, FlexDirection direction, JustifyContent justify_content);
|
||||
};
|
||||
|
||||
} // namespace recompui
|
||||
|
@ -203,6 +203,9 @@ void Element::process_event(const Event &) {
|
||||
}
|
||||
|
||||
void Element::clear_children() {
|
||||
if (children.empty()) {
|
||||
return;
|
||||
}
|
||||
ContextId context = get_current_context();
|
||||
|
||||
// Remove the children from the context.
|
||||
|
@ -8,6 +8,7 @@
|
||||
namespace recompui {
|
||||
class Element : public Style, public Rml::EventListener {
|
||||
friend ContextId create_context(const std::filesystem::path& path);
|
||||
friend ContextId create_context();
|
||||
private:
|
||||
Rml::Element *base = nullptr;
|
||||
Rml::ElementPtr base_owning = {};
|
||||
|
@ -4,7 +4,7 @@
|
||||
|
||||
namespace recompui {
|
||||
|
||||
Label::Label(LabelStyle label_style, Element *parent) : Element(parent) {
|
||||
Label::Label(Element *parent, LabelStyle label_style) : Element(parent) {
|
||||
switch (label_style) {
|
||||
case LabelStyle::Small:
|
||||
set_font_size(20.0f);
|
||||
@ -29,7 +29,7 @@ namespace recompui {
|
||||
set_font_style(FontStyle::Normal);
|
||||
}
|
||||
|
||||
Label::Label(const std::string &text, LabelStyle label_style, Element *parent) : Label(label_style, parent) {
|
||||
Label::Label(Element *parent, const std::string &text, LabelStyle label_style) : Label(parent, label_style) {
|
||||
set_text(text);
|
||||
}
|
||||
|
||||
|
@ -12,8 +12,8 @@ namespace recompui {
|
||||
|
||||
class Label : public Element {
|
||||
public:
|
||||
Label(LabelStyle label_style, Element *parent);
|
||||
Label(const std::string &text, LabelStyle label_style, Element *parent);
|
||||
Label(Element *parent, LabelStyle label_style);
|
||||
Label(Element *parent, const std::string &text, LabelStyle label_style);
|
||||
};
|
||||
|
||||
} // namespace recompui
|
@ -4,7 +4,7 @@ namespace recompui {
|
||||
|
||||
// RadioOption
|
||||
|
||||
RadioOption::RadioOption(std::string_view name, uint32_t index, Element *parent) : 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") {
|
||||
this->index = index;
|
||||
|
||||
set_text(name);
|
||||
@ -68,7 +68,7 @@ namespace recompui {
|
||||
set_index_internal(index, false, true);
|
||||
}
|
||||
|
||||
Radio::Radio(Element *parent) : Container(FlexDirection::Row, JustifyContent::FlexStart, parent) {
|
||||
Radio::Radio(Element *parent) : Container(parent, FlexDirection::Row, JustifyContent::FlexStart) {
|
||||
set_gap(12.0f);
|
||||
}
|
||||
|
||||
@ -77,7 +77,7 @@ namespace recompui {
|
||||
}
|
||||
|
||||
void Radio::add_option(std::string_view name) {
|
||||
RadioOption *option = get_current_context().create_element<RadioOption>(name, uint32_t(options.size()), this);
|
||||
RadioOption *option = get_current_context().create_element<RadioOption>(this, name, uint32_t(options.size()));
|
||||
option->set_pressed_callback(std::bind(&Radio::option_selected, this, std::placeholders::_1));
|
||||
options.emplace_back(option);
|
||||
|
||||
|
@ -13,7 +13,7 @@ namespace recompui {
|
||||
protected:
|
||||
virtual void process_event(const Event &e) override;
|
||||
public:
|
||||
RadioOption(std::string_view name, uint32_t index, Element *parent);
|
||||
RadioOption(Element *parent, std::string_view name, uint32_t index);
|
||||
void set_pressed_callback(std::function<void(uint32_t)> callback);
|
||||
void set_selected_state(bool enable);
|
||||
};
|
||||
|
@ -4,7 +4,7 @@
|
||||
|
||||
namespace recompui {
|
||||
|
||||
ScrollContainer::ScrollContainer(ScrollDirection direction, Element *parent) : Element(parent) {
|
||||
ScrollContainer::ScrollContainer(Element *parent, ScrollDirection direction) : Element(parent) {
|
||||
set_flex(1.0f, 1.0f, 100.0f);
|
||||
set_width(100.0f, Unit::Percent);
|
||||
set_height(100.0f, Unit::Percent);
|
||||
|
@ -11,7 +11,7 @@ namespace recompui {
|
||||
|
||||
class ScrollContainer : public Element {
|
||||
public:
|
||||
ScrollContainer(ScrollDirection direction, Element *parent);
|
||||
ScrollContainer(Element *parent, ScrollDirection direction);
|
||||
};
|
||||
|
||||
} // namespace recompui
|
||||
|
@ -60,7 +60,7 @@ namespace recompui {
|
||||
}
|
||||
}
|
||||
|
||||
Slider::Slider(SliderType type, Element *parent) : Element(parent) {
|
||||
Slider::Slider(Element *parent, SliderType type) : Element(parent) {
|
||||
this->type = type;
|
||||
|
||||
set_display(Display::Flex);
|
||||
@ -69,7 +69,7 @@ namespace recompui {
|
||||
|
||||
ContextId context = get_current_context();
|
||||
|
||||
value_label = context.create_element<Label>("0", LabelStyle::Small, this);
|
||||
value_label = context.create_element<Label>(this, "0", LabelStyle::Small);
|
||||
value_label->set_margin_right(20.0f);
|
||||
value_label->set_min_width(60.0f);
|
||||
value_label->set_max_width(60.0f);
|
||||
|
@ -34,7 +34,7 @@ namespace recompui {
|
||||
void update_label_text();
|
||||
|
||||
public:
|
||||
Slider(SliderType type, Element *parent);
|
||||
Slider(Element *parent, SliderType type);
|
||||
virtual ~Slider();
|
||||
void set_value(double v);
|
||||
double get_value() const;
|
||||
|
@ -475,4 +475,8 @@ namespace recompui {
|
||||
set_property(Rml::PropertyId::TabIndex, to_rml(tab_index), Animation());
|
||||
}
|
||||
|
||||
void Style::set_font_family(std::string_view family) {
|
||||
set_property(Rml::PropertyId::FontFamily, Rml::Property(Rml::String{ family }, Rml::Unit::UNKNOWN), Animation());
|
||||
}
|
||||
|
||||
} // namespace recompui
|
@ -1,5 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
#include <string_view>
|
||||
|
||||
#include "RmlUi/Core.h"
|
||||
|
||||
#include "../core/ui_resource.h"
|
||||
@ -84,6 +86,7 @@ namespace recompui {
|
||||
void set_column_gap(float size, Unit unit = Unit::Dp, Animation animation = Animation());
|
||||
void set_drag(Drag drag);
|
||||
void set_tab_index(TabIndex focus);
|
||||
void set_font_family(std::string_view family);
|
||||
virtual bool is_element() { return false; }
|
||||
ResourceId get_resource_id() { return resource_id; }
|
||||
};
|
||||
|
@ -171,7 +171,7 @@ namespace recompui {
|
||||
Percent
|
||||
};
|
||||
|
||||
enum class AnimationType {
|
||||
enum class AnimationType : uint32_t {
|
||||
None,
|
||||
Set,
|
||||
Tween
|
||||
|
254
src/ui/ui_api.cpp
Normal file
254
src/ui/ui_api.cpp
Normal file
@ -0,0 +1,254 @@
|
||||
#include "recomp_ui.h"
|
||||
|
||||
#include "core/ui_context.h"
|
||||
#include "core/ui_resource.h"
|
||||
|
||||
#include "elements/ui_element.h"
|
||||
#include "elements/ui_button.h"
|
||||
#include "elements/ui_clickable.h"
|
||||
#include "elements/ui_container.h"
|
||||
#include "elements/ui_image.h"
|
||||
#include "elements/ui_label.h"
|
||||
#include "elements/ui_radio.h"
|
||||
#include "elements/ui_scroll_container.h"
|
||||
#include "elements/ui_slider.h"
|
||||
#include "elements/ui_style.h"
|
||||
#include "elements/ui_text_input.h"
|
||||
#include "elements/ui_toggle.h"
|
||||
#include "elements/ui_types.h"
|
||||
|
||||
#include "librecomp/overlays.hpp"
|
||||
#include "librecomp/helpers.hpp"
|
||||
|
||||
using namespace recompui;
|
||||
|
||||
constexpr ResourceId root_element_id{ 0xFFFFFFFE };
|
||||
|
||||
// Helpers
|
||||
|
||||
ContextId get_context(uint8_t* rdram, recomp_context* ctx) {
|
||||
uint32_t context_id = _arg<0, uint32_t>(rdram, ctx);
|
||||
return ContextId{ .slot_id = context_id };
|
||||
}
|
||||
|
||||
template <int arg_index>
|
||||
std::string arg_string(uint8_t* rdram, recomp_context* ctx) {
|
||||
PTR(char) str = _arg<arg_index, PTR(char)>(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 <int arg_index>
|
||||
ResourceId arg_resource_id(uint8_t* rdram, recomp_context* ctx) {
|
||||
uint32_t slot_id = _arg<arg_index, uint32_t>(rdram, ctx);
|
||||
|
||||
return ResourceId{ .slot_id = slot_id };
|
||||
}
|
||||
|
||||
template <int arg_index>
|
||||
Element* arg_element(uint8_t* rdram, recomp_context* ctx, ContextId ui_context) {
|
||||
ResourceId resource = arg_resource_id<arg_index>(rdram, ctx);
|
||||
|
||||
if (resource == ResourceId::null()) {
|
||||
return nullptr;
|
||||
}
|
||||
else if (resource == root_element_id) {
|
||||
return ui_context.get_root_element();
|
||||
}
|
||||
|
||||
return resource.as_element();
|
||||
}
|
||||
|
||||
template <int arg_index>
|
||||
Style* arg_style(uint8_t* rdram, recomp_context* ctx) {
|
||||
ResourceId resource = arg_resource_id<arg_index>(rdram, ctx);
|
||||
|
||||
if (resource == ResourceId::null()) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return *resource;
|
||||
}
|
||||
|
||||
template <int arg_index>
|
||||
Animation arg_animation(uint8_t* rdram, recomp_context* ctx) {
|
||||
PTR(Animation) anim_ptr = _arg<arg_index, PTR(Animation)>(rdram, ctx);
|
||||
|
||||
if (anim_ptr == NULLPTR) {
|
||||
return Animation{};
|
||||
}
|
||||
else {
|
||||
return *TO_PTR(Animation, anim_ptr);
|
||||
}
|
||||
}
|
||||
|
||||
void return_resource(recomp_context* ctx, ResourceId resource) {
|
||||
_return<uint32_t>(ctx, resource.slot_id);
|
||||
}
|
||||
|
||||
// Context functions
|
||||
|
||||
extern "C" void recompui_create_context(uint8_t* rdram, recomp_context* ctx) {
|
||||
(void)rdram;
|
||||
ContextId ui_context = create_context();
|
||||
|
||||
_return<uint32_t>(ctx, ui_context.slot_id);
|
||||
}
|
||||
|
||||
extern "C" void recompui_open_context(uint8_t* rdram, recomp_context* ctx) {
|
||||
ContextId ui_context = get_context(rdram, ctx);
|
||||
|
||||
ui_context.open();
|
||||
}
|
||||
|
||||
extern "C" void recompui_close_context(uint8_t* rdram, recomp_context* ctx) {
|
||||
ContextId ui_context = get_context(rdram, ctx);
|
||||
|
||||
ui_context.close();
|
||||
}
|
||||
|
||||
extern "C" void recompui_context_root(uint8_t* rdram, recomp_context* ctx) {
|
||||
ContextId ui_context = get_context(rdram, ctx);
|
||||
(void)ui_context;
|
||||
|
||||
return_resource(ctx, root_element_id);
|
||||
}
|
||||
|
||||
extern "C" void recompui_show_context(uint8_t* rdram, recomp_context* ctx) {
|
||||
ContextId ui_context = get_context(rdram, ctx);
|
||||
|
||||
recompui::show_context(ui_context, "");
|
||||
}
|
||||
|
||||
extern "C" void recompui_hide_context(uint8_t* rdram, recomp_context* ctx) {
|
||||
ContextId ui_context = get_context(rdram, ctx);
|
||||
|
||||
recompui::hide_context(ui_context);
|
||||
}
|
||||
|
||||
// Resource creation functions
|
||||
|
||||
extern "C" void recompui_create_style(uint8_t* rdram, recomp_context* ctx) {
|
||||
ContextId ui_context = get_context(rdram, ctx);
|
||||
|
||||
Style* ret = ui_context.create_style();
|
||||
return_resource(ctx, ret->get_resource_id());
|
||||
}
|
||||
|
||||
extern "C" void recompui_create_element(uint8_t* rdram, recomp_context* ctx) {
|
||||
ContextId ui_context = get_context(rdram, ctx);
|
||||
Element* parent = arg_element<1>(rdram, ctx, ui_context);
|
||||
|
||||
Element* ret = ui_context.create_element<Element>(parent);
|
||||
return_resource(ctx, ret->get_resource_id());
|
||||
}
|
||||
|
||||
extern "C" 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());
|
||||
}
|
||||
|
||||
// Style functions
|
||||
|
||||
extern "C" void recompui_set_width(uint8_t* rdram, recomp_context* ctx) {
|
||||
Style* resource = arg_style<0>(rdram, ctx);
|
||||
float width = _arg_float_a1(rdram, ctx);
|
||||
uint32_t unit = _arg<2, uint32_t>(rdram, ctx);
|
||||
Animation animation = arg_animation<3>(rdram, ctx);
|
||||
|
||||
resource->set_width(width, static_cast<Unit>(unit), animation);
|
||||
}
|
||||
|
||||
extern "C" void recompui_set_height(uint8_t* rdram, recomp_context* ctx) {
|
||||
Style* resource = arg_style<0>(rdram, ctx);
|
||||
float height = _arg_float_a1(rdram, ctx);
|
||||
uint32_t unit = _arg<2, uint32_t>(rdram, ctx);
|
||||
Animation animation = arg_animation<3>(rdram, ctx);
|
||||
|
||||
resource->set_height(height, static_cast<Unit>(unit), animation);
|
||||
}
|
||||
|
||||
extern "C" void recompui_set_display(uint8_t* rdram, recomp_context* ctx) {
|
||||
Style* resource = arg_style<0>(rdram, ctx);
|
||||
uint32_t display = _arg<1, uint32_t>(rdram, ctx);
|
||||
|
||||
resource->set_display(static_cast<Display>(display));
|
||||
}
|
||||
|
||||
extern "C" void recompui_set_flex_direction(uint8_t* rdram, recomp_context* ctx) {
|
||||
Style* resource = arg_style<0>(rdram, ctx);
|
||||
uint32_t direction = _arg<1, uint32_t>(rdram, ctx);
|
||||
|
||||
resource->set_flex_direction(static_cast<FlexDirection>(direction));
|
||||
}
|
||||
|
||||
extern "C" void recompui_set_flex_grow(uint8_t* rdram, recomp_context* ctx) { // float grow, Animation animation = Animation()
|
||||
Style* resource = arg_style<0>(rdram, ctx);
|
||||
float grow = _arg_float_a1(rdram, ctx);
|
||||
Animation animation = arg_animation<2>(rdram, ctx);
|
||||
|
||||
resource->set_flex_grow(grow, animation);
|
||||
}
|
||||
|
||||
extern "C" void recompui_set_flex_shrink(uint8_t* rdram, recomp_context* ctx) { // float shrink, Animation animation = Animation()
|
||||
Style* resource = arg_style<0>(rdram, ctx);
|
||||
float shrink = _arg_float_a1(rdram, ctx);
|
||||
Animation animation = arg_animation<2>(rdram, ctx);
|
||||
|
||||
resource->set_flex_shrink(shrink, animation);
|
||||
}
|
||||
|
||||
extern "C" void recompui_set_flex_basis_auto(uint8_t* rdram, recomp_context* ctx) {
|
||||
Style* resource = arg_style<0>(rdram, ctx);
|
||||
|
||||
resource->set_flex_basis_auto();
|
||||
}
|
||||
|
||||
extern "C" void recompui_set_flex_basis(uint8_t* rdram, recomp_context* ctx) { // float basis, Unit unit = Unit::Percent, Animation animation = Animation()
|
||||
Style* resource = arg_style<0>(rdram, ctx);
|
||||
float basis = _arg_float_a1(rdram, ctx);
|
||||
uint32_t unit = _arg<2, uint32_t>(rdram, ctx);
|
||||
Animation animation = arg_animation<3>(rdram, ctx);
|
||||
|
||||
resource->set_flex_basis(basis, static_cast<Unit>(unit), animation);
|
||||
}
|
||||
|
||||
#define REGISTER_FUNC(name) recomp::overlays::register_base_export(#name, name)
|
||||
|
||||
void recompui::register_ui_exports() {
|
||||
REGISTER_FUNC(recompui_create_context);
|
||||
REGISTER_FUNC(recompui_open_context);
|
||||
REGISTER_FUNC(recompui_close_context);
|
||||
REGISTER_FUNC(recompui_context_root);
|
||||
REGISTER_FUNC(recompui_show_context);
|
||||
REGISTER_FUNC(recompui_hide_context);
|
||||
REGISTER_FUNC(recompui_create_style);
|
||||
REGISTER_FUNC(recompui_create_element);
|
||||
REGISTER_FUNC(recompui_create_button);
|
||||
REGISTER_FUNC(recompui_set_width);
|
||||
REGISTER_FUNC(recompui_set_height);
|
||||
REGISTER_FUNC(recompui_set_display);
|
||||
REGISTER_FUNC(recompui_set_flex_direction);
|
||||
REGISTER_FUNC(recompui_set_flex_grow);
|
||||
REGISTER_FUNC(recompui_set_flex_shrink);
|
||||
REGISTER_FUNC(recompui_set_flex_basis_auto);
|
||||
REGISTER_FUNC(recompui_set_flex_basis);
|
||||
}
|
@ -25,7 +25,7 @@ ConfigOptionElement::ConfigOptionElement(Element *parent) : Element(parent, Even
|
||||
set_gap(8.0f);
|
||||
set_min_height(100.0f);
|
||||
|
||||
name_label = get_current_context().create_element<Label>(LabelStyle::Normal, this);
|
||||
name_label = get_current_context().create_element<Label>(this, LabelStyle::Normal);
|
||||
}
|
||||
|
||||
ConfigOptionElement::~ConfigOptionElement() {
|
||||
@ -56,8 +56,8 @@ void ConfigOptionSlider::slider_value_changed(double v) {
|
||||
printf("%s changed to %f.\n", name.c_str(), v);
|
||||
}
|
||||
|
||||
ConfigOptionSlider::ConfigOptionSlider(double value, double min_value, double max_value, double step_value, bool percent, Element *parent) : ConfigOptionElement(parent) {
|
||||
slider = get_current_context().create_element<Slider>(percent ? SliderType::Percent : SliderType::Double, this);
|
||||
ConfigOptionSlider::ConfigOptionSlider(Element *parent, double value, double min_value, double max_value, double step_value, bool percent) : ConfigOptionElement(parent) {
|
||||
slider = get_current_context().create_element<Slider>(this, percent ? SliderType::Percent : SliderType::Double);
|
||||
slider->set_value(value);
|
||||
slider->set_min_value(min_value);
|
||||
slider->set_max_value(max_value);
|
||||
@ -83,7 +83,7 @@ void ConfigOptionRadio::index_changed(uint32_t index) {
|
||||
printf("%s changed to %d.\n", name.c_str(), index);
|
||||
}
|
||||
|
||||
ConfigOptionRadio::ConfigOptionRadio(const std::vector<std::string> &options, Element *parent) : ConfigOptionElement(parent) {
|
||||
ConfigOptionRadio::ConfigOptionRadio(Element *parent, const std::vector<std::string> &options) : ConfigOptionElement(parent) {
|
||||
radio = get_current_context().create_element<Radio>(this);
|
||||
radio->add_index_changed_callback(std::bind(&ConfigOptionRadio::index_changed, this, std::placeholders::_1));
|
||||
for (std::string_view option : options) {
|
||||
@ -127,25 +127,25 @@ ConfigSubMenu::ConfigSubMenu(Element *parent) : Element(parent) {
|
||||
set_height(100.0f, Unit::Percent);
|
||||
|
||||
recompui::ContextId context = get_current_context();
|
||||
header_container = context.create_element<Container>(FlexDirection::Row, JustifyContent::FlexStart, this);
|
||||
header_container = context.create_element<Container>(this, FlexDirection::Row, JustifyContent::FlexStart);
|
||||
|
||||
{
|
||||
back_button = context.create_element<Button>("Back", ButtonStyle::Secondary, header_container);
|
||||
back_button = context.create_element<Button>(header_container, "Back", ButtonStyle::Secondary);
|
||||
back_button->add_pressed_callback(std::bind(&ConfigSubMenu::back_button_pressed, this));
|
||||
title_label = context.create_element<Label>("Title", LabelStyle::Large, header_container);
|
||||
title_label = context.create_element<Label>(header_container, "Title", LabelStyle::Large);
|
||||
}
|
||||
|
||||
body_container = context.create_element<Container>(FlexDirection::Row, JustifyContent::SpaceEvenly, this);
|
||||
body_container = context.create_element<Container>(this, FlexDirection::Row, JustifyContent::SpaceEvenly);
|
||||
{
|
||||
config_container = context.create_element<Container>(FlexDirection::Column, JustifyContent::Center, body_container);
|
||||
config_container = context.create_element<Container>(body_container, FlexDirection::Column, JustifyContent::Center);
|
||||
config_container->set_display(Display::Block);
|
||||
config_container->set_flex_basis(100.0f);
|
||||
config_container->set_align_items(AlignItems::Center);
|
||||
{
|
||||
config_scroll_container = context.create_element<ScrollContainer>(ScrollDirection::Vertical, config_container);
|
||||
config_scroll_container = context.create_element<ScrollContainer>(config_container, ScrollDirection::Vertical);
|
||||
}
|
||||
|
||||
description_label = context.create_element<Label>("Description", LabelStyle::Small, body_container);
|
||||
description_label = context.create_element<Label>(body_container, "Description", LabelStyle::Small);
|
||||
description_label->set_min_width(800.0f);
|
||||
}
|
||||
}
|
||||
@ -172,7 +172,7 @@ void ConfigSubMenu::add_option(ConfigOptionElement *option, std::string_view nam
|
||||
}
|
||||
|
||||
void ConfigSubMenu::add_slider_option(std::string_view name, std::string_view description, double min, double max, double step, bool percent) {
|
||||
ConfigOptionSlider *option_slider = get_current_context().create_element<ConfigOptionSlider>((min + max) / 2.0, min, max, step, percent, config_scroll_container);
|
||||
ConfigOptionSlider *option_slider = get_current_context().create_element<ConfigOptionSlider>(config_scroll_container, (min + max) / 2.0, min, max, step, percent);
|
||||
add_option(option_slider, name, description);
|
||||
}
|
||||
|
||||
@ -182,7 +182,7 @@ void ConfigSubMenu::add_text_option(std::string_view name, std::string_view desc
|
||||
}
|
||||
|
||||
void ConfigSubMenu::add_radio_option(std::string_view name, std::string_view description, const std::vector<std::string> &options) {
|
||||
ConfigOptionRadio *option_radio = get_current_context().create_element<ConfigOptionRadio>(options, config_scroll_container);
|
||||
ConfigOptionRadio *option_radio = get_current_context().create_element<ConfigOptionRadio>(config_scroll_container, options);
|
||||
add_option(option_radio, name, description);
|
||||
}
|
||||
|
||||
|
@ -36,7 +36,7 @@ protected:
|
||||
|
||||
void slider_value_changed(double v);
|
||||
public:
|
||||
ConfigOptionSlider(double value, double min_value, double max_value, double step_value, bool percent, Element *parent);
|
||||
ConfigOptionSlider(Element *parent, double value, double min_value, double max_value, double step_value, bool percent);
|
||||
};
|
||||
|
||||
class ConfigOptionTextInput : public ConfigOptionElement {
|
||||
@ -54,7 +54,7 @@ protected:
|
||||
|
||||
void index_changed(uint32_t index);
|
||||
public:
|
||||
ConfigOptionRadio(const std::vector<std::string> &options, Element *parent);
|
||||
ConfigOptionRadio(Element *parent, const std::vector<std::string> &options);
|
||||
};
|
||||
|
||||
class ConfigSubMenu : public Element {
|
||||
|
@ -14,13 +14,13 @@ ModDetailsPanel::ModDetailsPanel(Element *parent) : Element(parent) {
|
||||
|
||||
ContextId context = get_current_context();
|
||||
|
||||
header_container = context.create_element<Container>(FlexDirection::Row, JustifyContent::FlexStart, this);
|
||||
header_container = context.create_element<Container>(this, FlexDirection::Row, JustifyContent::FlexStart);
|
||||
header_container->set_flex(0.0f, 0.0f);
|
||||
header_container->set_padding(16.0f);
|
||||
header_container->set_gap(16.0f);
|
||||
header_container->set_background_color(Color{ 0, 0, 0, 89 });
|
||||
{
|
||||
thumbnail_container = context.create_element<Container>(FlexDirection::Column, JustifyContent::SpaceEvenly, header_container);
|
||||
thumbnail_container = context.create_element<Container>(header_container, FlexDirection::Column, JustifyContent::SpaceEvenly);
|
||||
thumbnail_container->set_flex(0.0f, 0.0f);
|
||||
{
|
||||
thumbnail_image = context.create_element<Image>(thumbnail_container);
|
||||
@ -29,38 +29,38 @@ ModDetailsPanel::ModDetailsPanel(Element *parent) : Element(parent) {
|
||||
thumbnail_image->set_background_color(Color{ 190, 184, 219, 25 });
|
||||
}
|
||||
|
||||
header_details_container = context.create_element<Container>(FlexDirection::Column, JustifyContent::SpaceEvenly, header_container);
|
||||
header_details_container = context.create_element<Container>(header_container, FlexDirection::Column, JustifyContent::SpaceEvenly);
|
||||
header_details_container->set_flex(1.0f, 1.0f);
|
||||
header_details_container->set_flex_basis(100.0f, Unit::Percent);
|
||||
header_details_container->set_text_align(TextAlign::Left);
|
||||
{
|
||||
title_label = context.create_element<Label>(LabelStyle::Large, header_details_container);
|
||||
version_label = context.create_element<Label>(LabelStyle::Normal, header_details_container);
|
||||
title_label = context.create_element<Label>(header_details_container, LabelStyle::Large);
|
||||
version_label = context.create_element<Label>(header_details_container, LabelStyle::Normal);
|
||||
}
|
||||
}
|
||||
|
||||
body_container = context.create_element<Container>(FlexDirection::Column, JustifyContent::FlexStart, this);
|
||||
body_container = context.create_element<Container>(this, FlexDirection::Column, JustifyContent::FlexStart);
|
||||
body_container->set_flex(0.0f, 0.0f);
|
||||
body_container->set_text_align(TextAlign::Left);
|
||||
body_container->set_padding(16.0f);
|
||||
body_container->set_gap(16.0f);
|
||||
{
|
||||
description_label = context.create_element<Label>(LabelStyle::Normal, body_container);
|
||||
authors_label = context.create_element<Label>(LabelStyle::Normal, body_container);
|
||||
description_label = context.create_element<Label>(body_container, LabelStyle::Normal);
|
||||
authors_label = context.create_element<Label>(body_container, LabelStyle::Normal);
|
||||
}
|
||||
|
||||
spacer_element = context.create_element<Element>(this);
|
||||
spacer_element->set_flex(1.0f, 0.0f);
|
||||
|
||||
buttons_container = context.create_element<Container>(FlexDirection::Row, JustifyContent::SpaceAround, this);
|
||||
buttons_container = context.create_element<Container>(this, FlexDirection::Row, JustifyContent::SpaceAround);
|
||||
buttons_container->set_flex(0.0f, 0.0f);
|
||||
buttons_container->set_padding(16.0f);
|
||||
{
|
||||
enable_toggle = context.create_element<Toggle>(buttons_container);
|
||||
enable_toggle->add_checked_callback(std::bind(&ModDetailsPanel::enable_toggle_checked, this, std::placeholders::_1));
|
||||
configure_button = context.create_element<Button>("Configure", recompui::ButtonStyle::Secondary, buttons_container);
|
||||
configure_button = context.create_element<Button>(buttons_container, "Configure", recompui::ButtonStyle::Secondary);
|
||||
configure_button->add_pressed_callback(std::bind(&ModDetailsPanel::configure_button_pressed, this));
|
||||
erase_button = context.create_element<Button>("Erase", recompui::ButtonStyle::Secondary, buttons_container);
|
||||
erase_button = context.create_element<Button>(buttons_container, "Erase", recompui::ButtonStyle::Secondary);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -40,15 +40,15 @@ ModEntry::ModEntry(Element *parent, const recomp::mods::ModDetails &details, uin
|
||||
thumbnail_image->set_min_height(100.0f);
|
||||
thumbnail_image->set_background_color(Color{ 190, 184, 219, 25 });
|
||||
|
||||
body_container = context.create_element<Container>(FlexDirection::Column, JustifyContent::FlexStart, this);
|
||||
body_container = context.create_element<Container>(this, FlexDirection::Column, JustifyContent::FlexStart);
|
||||
body_container->set_width_auto();
|
||||
body_container->set_height(100.0f);
|
||||
body_container->set_margin_left(16.0f);
|
||||
body_container->set_overflow(Overflow::Hidden);
|
||||
|
||||
{
|
||||
name_label = context.create_element<Label>(details.mod_id, LabelStyle::Normal, body_container);
|
||||
description_label = context.create_element<Label>("Short description of mod here.", LabelStyle::Small, body_container);
|
||||
name_label = context.create_element<Label>(body_container, details.mod_id, LabelStyle::Normal);
|
||||
description_label = context.create_element<Label>(body_container, "Short description of mod here.", LabelStyle::Small);
|
||||
} // body_container
|
||||
} // this
|
||||
}
|
||||
@ -174,12 +174,12 @@ ModMenu::ModMenu(Element *parent) : Element(parent) {
|
||||
set_height(100.0f, Unit::Percent);
|
||||
|
||||
{
|
||||
body_container = context.create_element<Container>(FlexDirection::Row, JustifyContent::FlexStart, this);
|
||||
body_container = context.create_element<Container>(this, FlexDirection::Row, JustifyContent::FlexStart);
|
||||
body_container->set_flex(1.0f, 1.0f, 100.0f);
|
||||
body_container->set_width(100.0f, Unit::Percent);
|
||||
body_container->set_height(100.0f, Unit::Percent);
|
||||
{
|
||||
list_container = context.create_element<Container>(FlexDirection::Column, JustifyContent::Center, body_container);
|
||||
list_container = context.create_element<Container>(body_container, FlexDirection::Column, JustifyContent::Center);
|
||||
list_container->set_display(Display::Block);
|
||||
list_container->set_flex_basis(100.0f);
|
||||
list_container->set_align_items(AlignItems::Center);
|
||||
@ -187,7 +187,7 @@ ModMenu::ModMenu(Element *parent) : Element(parent) {
|
||||
list_container->set_background_color(Color{ 0, 0, 0, 89 });
|
||||
list_container->set_border_bottom_left_radius(16.0f);
|
||||
{
|
||||
list_scroll_container = context.create_element<ScrollContainer>(ScrollDirection::Vertical, list_container);
|
||||
list_scroll_container = context.create_element<ScrollContainer>(list_container, ScrollDirection::Vertical);
|
||||
} // list_container
|
||||
|
||||
mod_details_panel = context.create_element<ModDetailsPanel>(body_container);
|
||||
@ -196,7 +196,7 @@ ModMenu::ModMenu(Element *parent) : Element(parent) {
|
||||
} // body_container
|
||||
|
||||
|
||||
footer_container = context.create_element<Container>(FlexDirection::Row, JustifyContent::SpaceBetween, this);
|
||||
footer_container = context.create_element<Container>(this, FlexDirection::Row, JustifyContent::SpaceBetween);
|
||||
footer_container->set_width(100.0f, recompui::Unit::Percent);
|
||||
footer_container->set_align_items(recompui::AlignItems::Center);
|
||||
footer_container->set_background_color(Color{ 0, 0, 0, 89 });
|
||||
@ -206,7 +206,7 @@ ModMenu::ModMenu(Element *parent) : Element(parent) {
|
||||
footer_container->set_border_bottom_left_radius(16.0f);
|
||||
footer_container->set_border_bottom_right_radius(16.0f);
|
||||
{
|
||||
refresh_button = context.create_element<Button>("Refresh", recompui::ButtonStyle::Primary, footer_container);
|
||||
refresh_button = context.create_element<Button>(footer_container, "Refresh", recompui::ButtonStyle::Primary);
|
||||
refresh_button->add_pressed_callback(std::bind(&ModMenu::refresh_mods, this));
|
||||
} // footer_container
|
||||
} // this
|
||||
|
@ -4,10 +4,10 @@
|
||||
#include <memory>
|
||||
|
||||
namespace RT64 {
|
||||
class RenderInterface;
|
||||
class RenderDevice;
|
||||
class RenderCommandList;
|
||||
class RenderFramebuffer;
|
||||
struct RenderInterface;
|
||||
struct RenderDevice;
|
||||
struct RenderCommandList;
|
||||
struct RenderFramebuffer;
|
||||
};
|
||||
|
||||
namespace Rml {
|
||||
|
@ -650,7 +650,6 @@ void draw_hook(RT64::RenderCommandList* command_list, RT64::RenderFramebuffer* s
|
||||
break;
|
||||
}
|
||||
|
||||
recompui::hide_all_contexts();
|
||||
if (open_config) {
|
||||
recompui::show_context(recompui::get_config_context_id(), "");
|
||||
}
|
||||
@ -770,3 +769,9 @@ Rml::ElementDocument* recompui::load_document(const std::filesystem::path& path)
|
||||
return ui_state->context->LoadDocument(path.string());
|
||||
}
|
||||
|
||||
Rml::ElementDocument* recompui::create_empty_document() {
|
||||
std::lock_guard lock{ui_state_mutex};
|
||||
|
||||
return ui_state->context->CreateDocument();
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user