mirror of
https://github.com/Zelda64Recomp/Zelda64Recomp.git
synced 2025-10-30 08:03:03 +00:00
Manual navigation in UI framework and WIP mod menu navigation
This commit is contained in:
parent
6166fffc99
commit
afc880521c
23 changed files with 128 additions and 12 deletions
|
|
@ -466,6 +466,8 @@ recompui::Style* recompui::ContextId::add_resource_impl(std::unique_ptr<Style>&&
|
||||||
auto key = opened_context->resources.emplace(std::move(resource));
|
auto key = opened_context->resources.emplace(std::move(resource));
|
||||||
|
|
||||||
if (is_element) {
|
if (is_element) {
|
||||||
|
Element* element_ptr = static_cast<Element*>(resource_ptr);
|
||||||
|
element_ptr->set_id(std::string{element_ptr->get_type_name()} + "-" + std::to_string(key.raw));
|
||||||
key.set_tag(static_cast<uint8_t>(SlotTag::Element));
|
key.set_tag(static_cast<uint8_t>(SlotTag::Element));
|
||||||
// Send one update to the element.
|
// Send one update to the element.
|
||||||
opened_context->to_update.emplace(ResourceId{ key.raw });
|
opened_context->to_update.emplace(ResourceId{ key.raw });
|
||||||
|
|
|
||||||
|
|
@ -20,6 +20,7 @@ namespace recompui {
|
||||||
|
|
||||||
// Element overrides.
|
// Element overrides.
|
||||||
virtual void process_event(const Event &e) override;
|
virtual void process_event(const Event &e) override;
|
||||||
|
std::string_view get_type_name() override { return "Button"; }
|
||||||
public:
|
public:
|
||||||
Button(Element *parent, const std::string &text, ButtonStyle style);
|
Button(Element *parent, const std::string &text, ButtonStyle style);
|
||||||
void add_pressed_callback(std::function<void()> callback);
|
void add_pressed_callback(std::function<void()> callback);
|
||||||
|
|
|
||||||
|
|
@ -11,6 +11,7 @@ namespace recompui {
|
||||||
|
|
||||||
// Element overrides.
|
// Element overrides.
|
||||||
virtual void process_event(const Event &e) override;
|
virtual void process_event(const Event &e) override;
|
||||||
|
std::string_view get_type_name() override { return "Clickable"; }
|
||||||
public:
|
public:
|
||||||
Clickable(Element *parent, bool draggable = false);
|
Clickable(Element *parent, bool draggable = false);
|
||||||
void add_pressed_callback(std::function<void(float, float)> callback);
|
void add_pressed_callback(std::function<void(float, float)> callback);
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,8 @@
|
||||||
namespace recompui {
|
namespace recompui {
|
||||||
|
|
||||||
class Container : public Element {
|
class Container : public Element {
|
||||||
|
protected:
|
||||||
|
std::string_view get_type_name() override { return "Container"; }
|
||||||
public:
|
public:
|
||||||
Container(Element* parent, FlexDirection direction, JustifyContent justify_content);
|
Container(Element* parent, FlexDirection direction, JustifyContent justify_content);
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -147,6 +147,11 @@ void Element::handle_event(const Event& event) {
|
||||||
process_event(event);
|
process_event(event);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Element::set_id(const std::string& new_id) {
|
||||||
|
id = new_id;
|
||||||
|
base->SetId(new_id);
|
||||||
|
}
|
||||||
|
|
||||||
void Element::ProcessEvent(Rml::Event &event) {
|
void Element::ProcessEvent(Rml::Event &event) {
|
||||||
ContextId prev_context = recompui::try_close_current_context();
|
ContextId prev_context = recompui::try_close_current_context();
|
||||||
ContextId context = ContextId::null();
|
ContextId context = ContextId::null();
|
||||||
|
|
|
||||||
|
|
@ -33,6 +33,7 @@ private:
|
||||||
std::unordered_multimap<std::string_view, uint32_t> style_name_index_map;
|
std::unordered_multimap<std::string_view, uint32_t> style_name_index_map;
|
||||||
std::vector<UICallback> callbacks;
|
std::vector<UICallback> callbacks;
|
||||||
std::vector<Element *> children;
|
std::vector<Element *> children;
|
||||||
|
std::string id;
|
||||||
bool shim = false;
|
bool shim = false;
|
||||||
bool enabled = true;
|
bool enabled = true;
|
||||||
bool disabled_attribute = false;
|
bool disabled_attribute = false;
|
||||||
|
|
@ -44,6 +45,7 @@ private:
|
||||||
void apply_style(Style *style);
|
void apply_style(Style *style);
|
||||||
void propagate_disabled(bool disabled);
|
void propagate_disabled(bool disabled);
|
||||||
void handle_event(const Event &e);
|
void handle_event(const Event &e);
|
||||||
|
void set_id(const std::string& new_id);
|
||||||
|
|
||||||
// Style overrides.
|
// Style overrides.
|
||||||
virtual void set_property(Rml::PropertyId property_id, const Rml::Property &property) override;
|
virtual void set_property(Rml::PropertyId property_id, const Rml::Property &property) override;
|
||||||
|
|
@ -56,6 +58,7 @@ protected:
|
||||||
virtual void process_event(const Event &e);
|
virtual void process_event(const Event &e);
|
||||||
virtual ElementValue get_element_value() { return std::monostate{}; }
|
virtual ElementValue get_element_value() { return std::monostate{}; }
|
||||||
virtual void set_input_value(const ElementValue&) {}
|
virtual void set_input_value(const ElementValue&) {}
|
||||||
|
virtual std::string_view get_type_name() { return "Element"; }
|
||||||
public:
|
public:
|
||||||
// Used for backwards compatibility with legacy UI elements.
|
// Used for backwards compatibility with legacy UI elements.
|
||||||
Element(Rml::Element *base);
|
Element(Rml::Element *base);
|
||||||
|
|
@ -94,6 +97,7 @@ public:
|
||||||
void set_input_value_u32(uint32_t val) { set_input_value(val); }
|
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_float(float val) { set_input_value(val); }
|
||||||
void set_input_value_double(double val) { set_input_value(val); }
|
void set_input_value_double(double val) { set_input_value(val); }
|
||||||
|
const std::string& get_id() { return id; }
|
||||||
};
|
};
|
||||||
|
|
||||||
void queue_ui_callback(recompui::ResourceId resource, const Event& e, const UICallback& callback);
|
void queue_ui_callback(recompui::ResourceId resource, const Event& e, const UICallback& callback);
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,8 @@
|
||||||
namespace recompui {
|
namespace recompui {
|
||||||
|
|
||||||
class Image : public Element {
|
class Image : public Element {
|
||||||
|
protected:
|
||||||
|
std::string_view get_type_name() override { return "ImageView"; }
|
||||||
public:
|
public:
|
||||||
Image(Element *parent, std::string_view src);
|
Image(Element *parent, std::string_view src);
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -12,6 +12,8 @@ namespace recompui {
|
||||||
};
|
};
|
||||||
|
|
||||||
class Label : public Element {
|
class Label : public Element {
|
||||||
|
protected:
|
||||||
|
std::string_view get_type_name() override { return "Label"; }
|
||||||
public:
|
public:
|
||||||
Label(Element *parent, LabelStyle label_style);
|
Label(Element *parent, LabelStyle label_style);
|
||||||
Label(Element *parent, const std::string &text, LabelStyle label_style);
|
Label(Element *parent, const std::string &text, LabelStyle label_style);
|
||||||
|
|
|
||||||
|
|
@ -13,6 +13,7 @@ namespace recompui {
|
||||||
uint32_t index = 0;
|
uint32_t index = 0;
|
||||||
protected:
|
protected:
|
||||||
virtual void process_event(const Event &e) override;
|
virtual void process_event(const Event &e) override;
|
||||||
|
std::string_view get_type_name() override { return "LabelRadioOption"; }
|
||||||
public:
|
public:
|
||||||
RadioOption(Element *parent, std::string_view name, uint32_t index);
|
RadioOption(Element *parent, std::string_view name, uint32_t index);
|
||||||
void set_pressed_callback(std::function<void(uint32_t)> callback);
|
void set_pressed_callback(std::function<void(uint32_t)> callback);
|
||||||
|
|
@ -29,6 +30,8 @@ namespace recompui {
|
||||||
void option_selected(uint32_t index);
|
void option_selected(uint32_t index);
|
||||||
void set_input_value(const ElementValue& val) override;
|
void set_input_value(const ElementValue& val) override;
|
||||||
ElementValue get_element_value() override { return get_index(); }
|
ElementValue get_element_value() override { return get_index(); }
|
||||||
|
protected:
|
||||||
|
std::string_view get_type_name() override { return "LabelRadio"; }
|
||||||
public:
|
public:
|
||||||
Radio(Element *parent);
|
Radio(Element *parent);
|
||||||
virtual ~Radio();
|
virtual ~Radio();
|
||||||
|
|
|
||||||
|
|
@ -10,6 +10,8 @@ namespace recompui {
|
||||||
};
|
};
|
||||||
|
|
||||||
class ScrollContainer : public Element {
|
class ScrollContainer : public Element {
|
||||||
|
protected:
|
||||||
|
std::string_view get_type_name() override { return "ScrollContainer"; }
|
||||||
public:
|
public:
|
||||||
ScrollContainer(Element *parent, ScrollDirection direction);
|
ScrollContainer(Element *parent, ScrollDirection direction);
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -36,6 +36,7 @@ namespace recompui {
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual void process_event(const Event &e) override;
|
virtual void process_event(const Event &e) override;
|
||||||
|
std::string_view get_type_name() override { return "Slider"; }
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Slider(Element *parent, SliderType type);
|
Slider(Element *parent, SliderType type);
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,8 @@
|
||||||
namespace recompui {
|
namespace recompui {
|
||||||
|
|
||||||
class Span : public Element {
|
class Span : public Element {
|
||||||
|
protected:
|
||||||
|
std::string_view get_type_name() override { return "Span"; }
|
||||||
public:
|
public:
|
||||||
Span(Element *parent);
|
Span(Element *parent);
|
||||||
Span(Element *parent, const std::string &text);
|
Span(Element *parent, const std::string &text);
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,5 @@
|
||||||
#include "ui_style.h"
|
#include "ui_style.h"
|
||||||
|
#include "ui_element.h"
|
||||||
|
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
|
|
||||||
|
|
@ -587,6 +588,14 @@ namespace recompui {
|
||||||
set_property(nav_to_property(dir), Rml::Style::Nav::None);
|
set_property(nav_to_property(dir), Rml::Style::Nav::None);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Style::set_nav(NavDirection dir, Element* element) {
|
||||||
|
set_property(nav_to_property(dir), Rml::Property(Rml::String{ "#" + element->get_id() }, Rml::Unit::STRING));
|
||||||
|
}
|
||||||
|
|
||||||
|
void Style::set_nav_manual(NavDirection dir, const std::string& target) {
|
||||||
|
set_property(nav_to_property(dir), Rml::Property(target, Rml::Unit::STRING));
|
||||||
|
}
|
||||||
|
|
||||||
void Style::set_tab_index_auto() {
|
void Style::set_tab_index_auto() {
|
||||||
set_property(Rml::PropertyId::TabIndex, Rml::Style::Nav::Auto);
|
set_property(Rml::PropertyId::TabIndex, Rml::Style::Nav::Auto);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -94,9 +94,10 @@ namespace recompui {
|
||||||
void set_drag(Drag drag);
|
void set_drag(Drag drag);
|
||||||
void set_tab_index(TabIndex focus);
|
void set_tab_index(TabIndex focus);
|
||||||
void set_font_family(std::string_view family);
|
void set_font_family(std::string_view family);
|
||||||
// TODO set_nav with Element*
|
|
||||||
void set_nav_auto(NavDirection dir);
|
void set_nav_auto(NavDirection dir);
|
||||||
void set_nav_none(NavDirection dir);
|
void set_nav_none(NavDirection dir);
|
||||||
|
void set_nav(NavDirection dir, Element* element);
|
||||||
|
void set_nav_manual(NavDirection dir, const std::string& target);
|
||||||
void set_tab_index_auto();
|
void set_tab_index_auto();
|
||||||
void set_tab_index_none();
|
void set_tab_index_none();
|
||||||
virtual bool is_element() { return false; }
|
virtual bool is_element() { return false; }
|
||||||
|
|
|
||||||
|
|
@ -10,6 +10,7 @@ namespace recompui {
|
||||||
std::vector<std::function<void(const std::string &)>> text_changed_callbacks;
|
std::vector<std::function<void(const std::string &)>> text_changed_callbacks;
|
||||||
protected:
|
protected:
|
||||||
virtual void process_event(const Event &e) override;
|
virtual void process_event(const Event &e) override;
|
||||||
|
std::string_view get_type_name() override { return "TextInput"; }
|
||||||
public:
|
public:
|
||||||
TextInput(Element *parent, bool text_visible = true);
|
TextInput(Element *parent, bool text_visible = true);
|
||||||
void set_text(std::string_view text);
|
void set_text(std::string_view text);
|
||||||
|
|
|
||||||
|
|
@ -6,9 +6,9 @@
|
||||||
|
|
||||||
namespace recompui {
|
namespace recompui {
|
||||||
|
|
||||||
Toggle::Toggle(Element *parent) : Element(parent, Events(EventType::Click, EventType::Hover, EventType::Enable), "button") {
|
Toggle::Toggle(Element *parent) : Element(parent, Events(EventType::Click, EventType::Focus, EventType::Hover, EventType::Enable), "button") {
|
||||||
enable_focus();
|
enable_focus();
|
||||||
|
|
||||||
set_width(162.0f);
|
set_width(162.0f);
|
||||||
set_height(72.0f);
|
set_height(72.0f);
|
||||||
set_border_radius(36.0f);
|
set_border_radius(36.0f);
|
||||||
|
|
@ -20,13 +20,19 @@ namespace recompui {
|
||||||
checked_style.set_border_color(Color{ 34, 177, 76, 255 });
|
checked_style.set_border_color(Color{ 34, 177, 76, 255 });
|
||||||
hover_style.set_border_color(Color{ 177, 76, 34, 255 });
|
hover_style.set_border_color(Color{ 177, 76, 34, 255 });
|
||||||
hover_style.set_background_color(Color{ 206, 120, 68, 76 });
|
hover_style.set_background_color(Color{ 206, 120, 68, 76 });
|
||||||
|
focus_style.set_border_color(Color{ 177, 76, 34, 255 });
|
||||||
|
focus_style.set_background_color(Color{ 206, 120, 68, 76 });
|
||||||
checked_hover_style.set_border_color(Color{ 34, 177, 76, 255 });
|
checked_hover_style.set_border_color(Color{ 34, 177, 76, 255 });
|
||||||
checked_hover_style.set_background_color(Color{ 68, 206, 120, 76 });
|
checked_hover_style.set_background_color(Color{ 68, 206, 120, 76 });
|
||||||
|
checked_focus_style.set_border_color(Color{ 34, 177, 76, 255 });
|
||||||
|
checked_focus_style.set_background_color(Color{ 68, 206, 120, 76 });
|
||||||
disabled_style.set_border_color(Color{ 177, 76, 34, 128 });
|
disabled_style.set_border_color(Color{ 177, 76, 34, 128 });
|
||||||
checked_disabled_style.set_border_color(Color{ 34, 177, 76, 128 });
|
checked_disabled_style.set_border_color(Color{ 34, 177, 76, 128 });
|
||||||
add_style(&checked_style, checked_state);
|
add_style(&checked_style, checked_state);
|
||||||
add_style(&hover_style, hover_state);
|
add_style(&hover_style, hover_state);
|
||||||
|
add_style(&focus_style, focus_state);
|
||||||
add_style(&checked_hover_style, { checked_state, hover_state });
|
add_style(&checked_hover_style, { checked_state, hover_state });
|
||||||
|
add_style(&checked_focus_style, { checked_state, focus_state });
|
||||||
add_style(&disabled_style, disabled_state);
|
add_style(&disabled_style, disabled_state);
|
||||||
add_style(&checked_disabled_style, { checked_state, disabled_state });
|
add_style(&checked_disabled_style, { checked_state, disabled_state });
|
||||||
|
|
||||||
|
|
@ -92,6 +98,11 @@ namespace recompui {
|
||||||
floater->set_style_enabled(hover_state, hover_active);
|
floater->set_style_enabled(hover_state, hover_active);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case EventType::Focus: {
|
||||||
|
bool focus_active = std::get<EventFocus>(e.variant).active;
|
||||||
|
set_style_enabled(focus_state, focus_active);
|
||||||
|
break;
|
||||||
|
}
|
||||||
case EventType::Enable: {
|
case EventType::Enable: {
|
||||||
bool enable_active = std::get<EventEnable>(e.variant).active;
|
bool enable_active = std::get<EventEnable>(e.variant).active;
|
||||||
set_style_enabled(disabled_state, !enable_active);
|
set_style_enabled(disabled_state, !enable_active);
|
||||||
|
|
|
||||||
|
|
@ -12,7 +12,9 @@ namespace recompui {
|
||||||
std::list<std::function<void(bool)>> checked_callbacks;
|
std::list<std::function<void(bool)>> checked_callbacks;
|
||||||
Style checked_style;
|
Style checked_style;
|
||||||
Style hover_style;
|
Style hover_style;
|
||||||
|
Style focus_style;
|
||||||
Style checked_hover_style;
|
Style checked_hover_style;
|
||||||
|
Style checked_focus_style;
|
||||||
Style disabled_style;
|
Style disabled_style;
|
||||||
Style checked_disabled_style;
|
Style checked_disabled_style;
|
||||||
Style floater_checked_style;
|
Style floater_checked_style;
|
||||||
|
|
@ -25,6 +27,7 @@ namespace recompui {
|
||||||
|
|
||||||
// Element overrides.
|
// Element overrides.
|
||||||
virtual void process_event(const Event &e) override;
|
virtual void process_event(const Event &e) override;
|
||||||
|
std::string_view get_type_name() override { return "Toggle"; }
|
||||||
public:
|
public:
|
||||||
Toggle(Element *parent);
|
Toggle(Element *parent);
|
||||||
void set_checked(bool checked);
|
void set_checked(bool checked);
|
||||||
|
|
|
||||||
|
|
@ -36,8 +36,8 @@ ConfigOptionElement::~ConfigOptionElement() {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ConfigOptionElement::set_id(std::string_view id) {
|
void ConfigOptionElement::set_option_id(std::string_view id) {
|
||||||
this->id = id;
|
this->option_id = id;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ConfigOptionElement::set_name(std::string_view name) {
|
void ConfigOptionElement::set_name(std::string_view name) {
|
||||||
|
|
@ -60,7 +60,7 @@ const std::string &ConfigOptionElement::get_description() const {
|
||||||
// ConfigOptionSlider
|
// ConfigOptionSlider
|
||||||
|
|
||||||
void ConfigOptionSlider::slider_value_changed(double v) {
|
void ConfigOptionSlider::slider_value_changed(double v) {
|
||||||
callback(id, v);
|
callback(option_id, v);
|
||||||
}
|
}
|
||||||
|
|
||||||
ConfigOptionSlider::ConfigOptionSlider(Element *parent, double value, double min_value, double max_value, double step_value, bool percent, std::function<void(const std::string &, double)> callback) : ConfigOptionElement(parent) {
|
ConfigOptionSlider::ConfigOptionSlider(Element *parent, double value, double min_value, double max_value, double step_value, bool percent, std::function<void(const std::string &, double)> callback) : ConfigOptionElement(parent) {
|
||||||
|
|
@ -78,7 +78,7 @@ ConfigOptionSlider::ConfigOptionSlider(Element *parent, double value, double min
|
||||||
// ConfigOptionTextInput
|
// ConfigOptionTextInput
|
||||||
|
|
||||||
void ConfigOptionTextInput::text_changed(const std::string &text) {
|
void ConfigOptionTextInput::text_changed(const std::string &text) {
|
||||||
callback(id, text);
|
callback(option_id, text);
|
||||||
}
|
}
|
||||||
|
|
||||||
ConfigOptionTextInput::ConfigOptionTextInput(Element *parent, std::string_view value, std::function<void(const std::string &, const std::string &)> callback) : ConfigOptionElement(parent) {
|
ConfigOptionTextInput::ConfigOptionTextInput(Element *parent, std::string_view value, std::function<void(const std::string &, const std::string &)> callback) : ConfigOptionElement(parent) {
|
||||||
|
|
@ -93,7 +93,7 @@ ConfigOptionTextInput::ConfigOptionTextInput(Element *parent, std::string_view v
|
||||||
// ConfigOptionRadio
|
// ConfigOptionRadio
|
||||||
|
|
||||||
void ConfigOptionRadio::index_changed(uint32_t index) {
|
void ConfigOptionRadio::index_changed(uint32_t index) {
|
||||||
callback(id, index);
|
callback(option_id, index);
|
||||||
}
|
}
|
||||||
|
|
||||||
ConfigOptionRadio::ConfigOptionRadio(Element *parent, uint32_t value, const std::vector<std::string> &options, std::function<void(const std::string &, uint32_t)> callback) : ConfigOptionElement(parent) {
|
ConfigOptionRadio::ConfigOptionRadio(Element *parent, uint32_t value, const std::vector<std::string> &options, std::function<void(const std::string &, uint32_t)> callback) : ConfigOptionElement(parent) {
|
||||||
|
|
@ -189,7 +189,7 @@ void ConfigSubMenu::clear_options() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void ConfigSubMenu::add_option(ConfigOptionElement *option, std::string_view id, std::string_view name, std::string_view description) {
|
void ConfigSubMenu::add_option(ConfigOptionElement *option, std::string_view id, std::string_view name, std::string_view description) {
|
||||||
option->set_id(id);
|
option->set_option_id(id);
|
||||||
option->set_name(name);
|
option->set_name(name);
|
||||||
option->set_description(description);
|
option->set_description(description);
|
||||||
option->set_hover_callback([this](ConfigOptionElement *option, bool active){ option_hovered(option, active); });
|
option->set_hover_callback([this](ConfigOptionElement *option, bool active){ option_hovered(option, active); });
|
||||||
|
|
|
||||||
|
|
@ -16,16 +16,17 @@ namespace recompui {
|
||||||
class ConfigOptionElement : public Element {
|
class ConfigOptionElement : public Element {
|
||||||
protected:
|
protected:
|
||||||
Label *name_label = nullptr;
|
Label *name_label = nullptr;
|
||||||
std::string id;
|
std::string option_id;
|
||||||
std::string name;
|
std::string name;
|
||||||
std::string description;
|
std::string description;
|
||||||
std::function<void(ConfigOptionElement *, bool)> hover_callback = nullptr;
|
std::function<void(ConfigOptionElement *, bool)> hover_callback = nullptr;
|
||||||
|
|
||||||
virtual void process_event(const Event &e) override;
|
virtual void process_event(const Event &e) override;
|
||||||
|
std::string_view get_type_name() override { return "ConfigOptionElement"; }
|
||||||
public:
|
public:
|
||||||
ConfigOptionElement(Element *parent);
|
ConfigOptionElement(Element *parent);
|
||||||
virtual ~ConfigOptionElement();
|
virtual ~ConfigOptionElement();
|
||||||
void set_id(std::string_view id);
|
void set_option_id(std::string_view id);
|
||||||
void set_name(std::string_view name);
|
void set_name(std::string_view name);
|
||||||
void set_description(std::string_view description);
|
void set_description(std::string_view description);
|
||||||
void set_hover_callback(std::function<void(ConfigOptionElement *, bool)> callback);
|
void set_hover_callback(std::function<void(ConfigOptionElement *, bool)> callback);
|
||||||
|
|
@ -38,6 +39,7 @@ protected:
|
||||||
std::function<void(const std::string &, double)> callback;
|
std::function<void(const std::string &, double)> callback;
|
||||||
|
|
||||||
void slider_value_changed(double v);
|
void slider_value_changed(double v);
|
||||||
|
std::string_view get_type_name() override { return "ConfigOptionSlider"; }
|
||||||
public:
|
public:
|
||||||
ConfigOptionSlider(Element *parent, double value, double min_value, double max_value, double step_value, bool percent, std::function<void(const std::string &, double)> callback);
|
ConfigOptionSlider(Element *parent, double value, double min_value, double max_value, double step_value, bool percent, std::function<void(const std::string &, double)> callback);
|
||||||
};
|
};
|
||||||
|
|
@ -48,6 +50,7 @@ protected:
|
||||||
std::function<void(const std::string &, const std::string &)> callback;
|
std::function<void(const std::string &, const std::string &)> callback;
|
||||||
|
|
||||||
void text_changed(const std::string &text);
|
void text_changed(const std::string &text);
|
||||||
|
std::string_view get_type_name() override { return "ConfigOptionTextInput"; }
|
||||||
public:
|
public:
|
||||||
ConfigOptionTextInput(Element *parent, std::string_view value, std::function<void(const std::string &, const std::string &)> callback);
|
ConfigOptionTextInput(Element *parent, std::string_view value, std::function<void(const std::string &, const std::string &)> callback);
|
||||||
};
|
};
|
||||||
|
|
@ -58,6 +61,7 @@ protected:
|
||||||
std::function<void(const std::string &, uint32_t)> callback;
|
std::function<void(const std::string &, uint32_t)> callback;
|
||||||
|
|
||||||
void index_changed(uint32_t index);
|
void index_changed(uint32_t index);
|
||||||
|
std::string_view get_type_name() override { return "ConfigOptionRadio"; }
|
||||||
public:
|
public:
|
||||||
ConfigOptionRadio(Element *parent, uint32_t value, const std::vector<std::string> &options, std::function<void(const std::string &, uint32_t)> callback);
|
ConfigOptionRadio(Element *parent, uint32_t value, const std::vector<std::string> &options, std::function<void(const std::string &, uint32_t)> callback);
|
||||||
};
|
};
|
||||||
|
|
@ -77,7 +81,8 @@ private:
|
||||||
void back_button_pressed();
|
void back_button_pressed();
|
||||||
void option_hovered(ConfigOptionElement *option, bool active);
|
void option_hovered(ConfigOptionElement *option, bool active);
|
||||||
void add_option(ConfigOptionElement *option, std::string_view id, std::string_view name, std::string_view description);
|
void add_option(ConfigOptionElement *option, std::string_view id, std::string_view name, std::string_view description);
|
||||||
|
protected:
|
||||||
|
std::string_view get_type_name() override { return "ConfigSubMenu"; }
|
||||||
public:
|
public:
|
||||||
ConfigSubMenu(Element *parent);
|
ConfigSubMenu(Element *parent);
|
||||||
virtual ~ConfigSubMenu();
|
virtual ~ConfigSubMenu();
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,8 @@
|
||||||
|
|
||||||
namespace recompui {
|
namespace recompui {
|
||||||
|
|
||||||
|
extern const std::string mod_tab_id;
|
||||||
|
|
||||||
ModDetailsPanel::ModDetailsPanel(Element *parent) : Element(parent) {
|
ModDetailsPanel::ModDetailsPanel(Element *parent) : Element(parent) {
|
||||||
set_flex(1.0f, 1.0f, 200.0f);
|
set_flex(1.0f, 1.0f, 200.0f);
|
||||||
set_height(100.0f, Unit::Percent);
|
set_height(100.0f, Unit::Percent);
|
||||||
|
|
@ -63,13 +65,16 @@ ModDetailsPanel::ModDetailsPanel(Element *parent) : Element(parent) {
|
||||||
{
|
{
|
||||||
enable_toggle = context.create_element<Toggle>(enable_container);
|
enable_toggle = context.create_element<Toggle>(enable_container);
|
||||||
enable_toggle->add_checked_callback([this](bool checked){ enable_toggle_checked(checked); });
|
enable_toggle->add_checked_callback([this](bool checked){ enable_toggle_checked(checked); });
|
||||||
|
enable_toggle->set_nav_manual(NavDirection::Up, mod_tab_id);
|
||||||
|
|
||||||
enable_label = context.create_element<Label>(enable_container, "A currently enabled mod requires this mod", LabelStyle::Annotation);
|
enable_label = context.create_element<Label>(enable_container, "A currently enabled mod requires this mod", LabelStyle::Annotation);
|
||||||
}
|
}
|
||||||
|
|
||||||
configure_button = context.create_element<Button>(buttons_container, "Configure", recompui::ButtonStyle::Secondary);
|
configure_button = context.create_element<Button>(buttons_container, "Configure", recompui::ButtonStyle::Secondary);
|
||||||
configure_button->add_pressed_callback([this](){ configure_button_pressed(); });
|
configure_button->add_pressed_callback([this](){ configure_button_pressed(); });
|
||||||
|
configure_button->set_nav_manual(NavDirection::Up, mod_tab_id);
|
||||||
}
|
}
|
||||||
|
clear_mod_navigation();
|
||||||
}
|
}
|
||||||
|
|
||||||
ModDetailsPanel::~ModDetailsPanel() {
|
ModDetailsPanel::~ModDetailsPanel() {
|
||||||
|
|
@ -110,6 +115,14 @@ void ModDetailsPanel::set_mod_configure_pressed_callback(std::function<void()> c
|
||||||
mod_configure_pressed_callback = callback;
|
mod_configure_pressed_callback = callback;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ModDetailsPanel::setup_mod_navigation(Element* nav_target) {
|
||||||
|
enable_toggle->set_nav(NavDirection::Left, nav_target);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ModDetailsPanel::clear_mod_navigation() {
|
||||||
|
enable_toggle->set_nav_none(NavDirection::Left);
|
||||||
|
}
|
||||||
|
|
||||||
void ModDetailsPanel::enable_toggle_checked(bool checked) {
|
void ModDetailsPanel::enable_toggle_checked(bool checked) {
|
||||||
if (mod_toggled_callback != nullptr) {
|
if (mod_toggled_callback != nullptr) {
|
||||||
mod_toggled_callback(checked);
|
mod_toggled_callback(checked);
|
||||||
|
|
|
||||||
|
|
@ -18,7 +18,13 @@ public:
|
||||||
void set_mod_details(const recomp::mods::ModDetails& details, const std::string &thumbnail, bool toggle_checked, bool toggle_enabled, bool toggle_label_visible, bool configure_enabled);
|
void set_mod_details(const recomp::mods::ModDetails& details, const std::string &thumbnail, bool toggle_checked, bool toggle_enabled, bool toggle_label_visible, bool configure_enabled);
|
||||||
void set_mod_toggled_callback(std::function<void(bool)> callback);
|
void set_mod_toggled_callback(std::function<void(bool)> callback);
|
||||||
void set_mod_configure_pressed_callback(std::function<void()> callback);
|
void set_mod_configure_pressed_callback(std::function<void()> callback);
|
||||||
|
void setup_mod_navigation(Element* nav_target);
|
||||||
|
void clear_mod_navigation();
|
||||||
|
Toggle* get_enable_toggle() { return enable_toggle; }
|
||||||
|
Button* get_configure_button() { return configure_button; }
|
||||||
void disable_toggle();
|
void disable_toggle();
|
||||||
|
protected:
|
||||||
|
std::string_view get_type_name() override { return "ModDetailsPanel"; }
|
||||||
private:
|
private:
|
||||||
recomp::mods::ModDetails cur_details;
|
recomp::mods::ModDetails cur_details;
|
||||||
Container *thumbnail_container = nullptr;
|
Container *thumbnail_container = nullptr;
|
||||||
|
|
|
||||||
|
|
@ -32,6 +32,9 @@ static bool is_mod_enabled_or_auto(const std::string &mod_id) {
|
||||||
constexpr float modEntryHeight = 120.0f;
|
constexpr float modEntryHeight = 120.0f;
|
||||||
constexpr float modEntryPadding = 4.0f;
|
constexpr float modEntryPadding = 4.0f;
|
||||||
|
|
||||||
|
extern const std::string mod_tab_id;
|
||||||
|
const std::string mod_tab_id = "#tab_mods";
|
||||||
|
|
||||||
ModEntryView::ModEntryView(Element *parent) : Element(parent) {
|
ModEntryView::ModEntryView(Element *parent) : Element(parent) {
|
||||||
ContextId context = get_current_context();
|
ContextId context = get_current_context();
|
||||||
|
|
||||||
|
|
@ -283,6 +286,22 @@ void ModMenu::mod_selected(uint32_t mod_index) {
|
||||||
bool configure_enabled = !config_schema.options.empty();
|
bool configure_enabled = !config_schema.options.empty();
|
||||||
mod_details_panel->set_mod_details(mod_details[mod_index], thumbnail_src, toggle_checked, toggle_enabled, auto_enabled, configure_enabled);
|
mod_details_panel->set_mod_details(mod_details[mod_index], thumbnail_src, toggle_checked, toggle_enabled, auto_enabled, configure_enabled);
|
||||||
mod_entry_buttons[active_mod_index]->set_selected(true);
|
mod_entry_buttons[active_mod_index]->set_selected(true);
|
||||||
|
|
||||||
|
mod_details_panel->setup_mod_navigation(mod_entry_buttons[mod_index]);
|
||||||
|
if (configure_enabled) {
|
||||||
|
Button* configure_button = mod_details_panel->get_configure_button();
|
||||||
|
refresh_button->set_nav(NavDirection::Up, configure_button);
|
||||||
|
mods_folder_button->set_nav(NavDirection::Up, configure_button);
|
||||||
|
}
|
||||||
|
else if (toggle_enabled) {
|
||||||
|
Toggle* enable_toggle = mod_details_panel->get_enable_toggle();
|
||||||
|
refresh_button->set_nav(NavDirection::Up, enable_toggle);
|
||||||
|
mods_folder_button->set_nav(NavDirection::Up, enable_toggle);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
refresh_button->set_nav_manual(NavDirection::Up, mod_tab_id);
|
||||||
|
mods_folder_button->set_nav_manual(NavDirection::Up, mod_tab_id);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -495,6 +514,8 @@ void ModMenu::create_mod_list() {
|
||||||
mod_entry_buttons.clear();
|
mod_entry_buttons.clear();
|
||||||
mod_entry_spacers.clear();
|
mod_entry_spacers.clear();
|
||||||
|
|
||||||
|
Toggle* enable_toggle = mod_details_panel->get_enable_toggle();
|
||||||
|
|
||||||
// Create the child elements for the list scroll.
|
// Create the child elements for the list scroll.
|
||||||
for (size_t mod_index = 0; mod_index < mod_details.size(); mod_index++) {
|
for (size_t mod_index = 0; mod_index < mod_details.size(); mod_index++) {
|
||||||
const std::vector<char> &thumbnail = recomp::mods::get_mod_thumbnail(mod_details[mod_index].mod_id);
|
const std::vector<char> &thumbnail = recomp::mods::get_mod_thumbnail(mod_details[mod_index].mod_id);
|
||||||
|
|
@ -513,6 +534,13 @@ void ModMenu::create_mod_list() {
|
||||||
mod_entry->set_mod_details(mod_details[mod_index]);
|
mod_entry->set_mod_details(mod_details[mod_index]);
|
||||||
mod_entry->set_mod_thumbnail(thumbnail_name);
|
mod_entry->set_mod_thumbnail(thumbnail_name);
|
||||||
mod_entry->set_mod_enabled(is_mod_enabled_or_auto(mod_details[mod_index].mod_id));
|
mod_entry->set_mod_enabled(is_mod_enabled_or_auto(mod_details[mod_index].mod_id));
|
||||||
|
mod_entry->set_nav(NavDirection::Right, enable_toggle);
|
||||||
|
if (mod_index == 0) {
|
||||||
|
mod_entry->set_nav_manual(NavDirection::Up, mod_tab_id);
|
||||||
|
}
|
||||||
|
if (mod_index == mod_details.size() - 1) {
|
||||||
|
mod_entry->set_nav(NavDirection::Down, install_mods_button);
|
||||||
|
}
|
||||||
mod_entry_buttons.emplace_back(mod_entry);
|
mod_entry_buttons.emplace_back(mod_entry);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -605,17 +633,23 @@ ModMenu::ModMenu(Element *parent) : Element(parent) {
|
||||||
footer_container->set_border_bottom_left_radius(16.0f);
|
footer_container->set_border_bottom_left_radius(16.0f);
|
||||||
footer_container->set_border_bottom_right_radius(16.0f);
|
footer_container->set_border_bottom_right_radius(16.0f);
|
||||||
{
|
{
|
||||||
|
Toggle* enable_toggle = mod_details_panel->get_enable_toggle();
|
||||||
|
Button* configure_button = mod_details_panel->get_configure_button();
|
||||||
install_mods_button = context.create_element<Button>(footer_container, "Install Mods", recompui::ButtonStyle::Primary);
|
install_mods_button = context.create_element<Button>(footer_container, "Install Mods", recompui::ButtonStyle::Primary);
|
||||||
install_mods_button->add_pressed_callback([this](){ open_install_dialog(); });
|
install_mods_button->add_pressed_callback([this](){ open_install_dialog(); });
|
||||||
|
install_mods_button->set_nav_manual(NavDirection::Up, mod_tab_id);
|
||||||
|
|
||||||
Element* footer_spacer = context.create_element<Element>(footer_container);
|
Element* footer_spacer = context.create_element<Element>(footer_container);
|
||||||
footer_spacer->set_flex(1.0f, 0.0f);
|
footer_spacer->set_flex(1.0f, 0.0f);
|
||||||
|
|
||||||
refresh_button = context.create_element<Button>(footer_container, "Refresh", recompui::ButtonStyle::Primary);
|
refresh_button = context.create_element<Button>(footer_container, "Refresh", recompui::ButtonStyle::Primary);
|
||||||
refresh_button->add_pressed_callback([this](){ recomp::mods::scan_mods(); refresh_mods(); });
|
refresh_button->add_pressed_callback([this](){ recomp::mods::scan_mods(); refresh_mods(); });
|
||||||
|
refresh_button->set_nav_manual(NavDirection::Up, mod_tab_id);
|
||||||
|
|
||||||
mods_folder_button = context.create_element<Button>(footer_container, "Open Mods Folder", recompui::ButtonStyle::Primary);
|
mods_folder_button = context.create_element<Button>(footer_container, "Open Mods Folder", recompui::ButtonStyle::Primary);
|
||||||
mods_folder_button->add_pressed_callback([this](){ open_mods_folder(); });
|
mods_folder_button->add_pressed_callback([this](){ open_mods_folder(); });
|
||||||
|
mods_folder_button->set_nav(NavDirection::Up, configure_button);
|
||||||
|
mods_folder_button->set_nav_manual(NavDirection::Up, mod_tab_id);
|
||||||
} // footer_container
|
} // footer_container
|
||||||
} // this
|
} // this
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -18,6 +18,8 @@ public:
|
||||||
void set_mod_thumbnail(const std::string &thumbnail);
|
void set_mod_thumbnail(const std::string &thumbnail);
|
||||||
void set_mod_enabled(bool enabled);
|
void set_mod_enabled(bool enabled);
|
||||||
void set_selected(bool selected);
|
void set_selected(bool selected);
|
||||||
|
protected:
|
||||||
|
std::string_view get_type_name() override { return "ModEntryView"; }
|
||||||
private:
|
private:
|
||||||
Image *thumbnail_image = nullptr;
|
Image *thumbnail_image = nullptr;
|
||||||
Element *body_container = nullptr;
|
Element *body_container = nullptr;
|
||||||
|
|
@ -40,6 +42,7 @@ public:
|
||||||
void set_selected(bool selected);
|
void set_selected(bool selected);
|
||||||
protected:
|
protected:
|
||||||
virtual void process_event(const Event &e) override;
|
virtual void process_event(const Event &e) override;
|
||||||
|
std::string_view get_type_name() override { return "ModEntryButton"; }
|
||||||
private:
|
private:
|
||||||
uint32_t mod_index = 0;
|
uint32_t mod_index = 0;
|
||||||
ModEntryView *view = nullptr;
|
ModEntryView *view = nullptr;
|
||||||
|
|
@ -56,6 +59,7 @@ private:
|
||||||
void check_height_distance();
|
void check_height_distance();
|
||||||
protected:
|
protected:
|
||||||
virtual void process_event(const Event &e) override;
|
virtual void process_event(const Event &e) override;
|
||||||
|
std::string_view get_type_name() override { return "ModEntrySpacer"; }
|
||||||
public:
|
public:
|
||||||
ModEntrySpacer(Element *parent);
|
ModEntrySpacer(Element *parent);
|
||||||
void set_target_height(float target_height, bool animate_to_target);
|
void set_target_height(float target_height, bool animate_to_target);
|
||||||
|
|
@ -66,6 +70,8 @@ public:
|
||||||
ModMenu(Element *parent);
|
ModMenu(Element *parent);
|
||||||
virtual ~ModMenu();
|
virtual ~ModMenu();
|
||||||
void set_mods_dirty() { mods_dirty = true; }
|
void set_mods_dirty() { mods_dirty = true; }
|
||||||
|
protected:
|
||||||
|
std::string_view get_type_name() override { return "ModMenu"; }
|
||||||
private:
|
private:
|
||||||
void refresh_mods();
|
void refresh_mods();
|
||||||
void open_mods_folder();
|
void open_mods_folder();
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue