Refactored mods menu entirely.

This commit is contained in:
Dario 2025-01-12 01:02:21 -03:00 committed by Mr-Wiseguy
parent 425dfeec24
commit 4e582443fb
14 changed files with 402 additions and 187 deletions

View File

@ -159,6 +159,8 @@ set (SOURCES
${CMAKE_SOURCE_DIR}/src/ui/ui_color_hack.cpp
${CMAKE_SOURCE_DIR}/src/ui/ui_rml_hacks.cpp
${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/util/hsv.cpp
${CMAKE_SOURCE_DIR}/src/ui/elements/ElementConfigGroup.cpp
${CMAKE_SOURCE_DIR}/src/ui/elements/ElementConfigOption.cpp
@ -171,14 +173,13 @@ set (SOURCES
${CMAKE_SOURCE_DIR}/src/ui/elements/ElementOptionTypeRadioTabs.cpp
${CMAKE_SOURCE_DIR}/src/ui/elements/ElementOptionTypeRange.cpp
${CMAKE_SOURCE_DIR}/src/ui/elements/ElementOptionTypeTextField.cpp
${CMAKE_SOURCE_DIR}/src/ui/elements/ElementModMenu.cpp
${CMAKE_SOURCE_DIR}/src/ui/elements/presets.cpp
${CMAKE_SOURCE_DIR}/src/ui/elements/ui_button.cpp
${CMAKE_SOURCE_DIR}/src/ui/elements/ui_container.cpp
${CMAKE_SOURCE_DIR}/src/ui/elements/ui_element.cpp
${CMAKE_SOURCE_DIR}/src/ui/elements/ui_image.cpp
${CMAKE_SOURCE_DIR}/src/ui/elements/ui_label.cpp
${CMAKE_SOURCE_DIR}/src/ui/elements/ui_mod_details_panel.cpp
${CMAKE_SOURCE_DIR}/src/ui/elements/ui_scroll_container.cpp
${CMAKE_SOURCE_DIR}/src/ui/elements/ui_toggle.cpp
${CMAKE_SOURCE_DIR}/rsp/aspMain.cpp

View File

@ -1,144 +0,0 @@
#include "ElementModMenu.h"
#include "presets.h"
#include "librecomp/mods.hpp"
#include <string>
#define MOD_MENU_BEM "mod-menu"
namespace recompui {
static const std::string cls_base = BLOCK(MOD_MENU_BEM);
static const std::string cls_list = EL(MOD_MENU_BEM, "list");
static const std::string cls_list_scroll = EL(MOD_MENU_BEM, "list-scroll");
static const std::string cls_list_entry = EL(MOD_MENU_BEM, "list-entry");
static const std::string cls_list_entry_thumbnail = EL(MOD_MENU_BEM, "list-entry-thumbnail");
static const std::string cls_list_entry_body = EL(MOD_MENU_BEM, "list-entry-body");
static const std::string cls_list_entry_name = EL(MOD_MENU_BEM, "list-entry-name");
static const std::string cls_list_entry_description = EL(MOD_MENU_BEM, "list-entry-description");
void ElementModMenu::ProcessEvent(Rml::Event& event) {
Rml::Element* event_element = event.GetCurrentElement();
Rml::EventId event_id = event.GetId();
switch (event_id) {
// Click event handlers.
case Rml::EventId::Click:
// Refresh
if (event_element == refresh_button) {
RefreshMods();
}
break;
case Rml::EventId::Focus:
{
size_t mod_index;
Rml::Variant *val = event_element->GetAttribute("mod_index");
if (val->GetInto(mod_index) && mod_index < mod_details.size()) {
mod_details_panel->set_mod_details(mod_details[mod_index]);
}
if (active_list_entry_el != nullptr) {
active_list_entry_el->RemoveAttribute("is_selected");
}
event_element->SetAttribute("is_selected", true);
active_list_entry_el = event_element;
}
default:
break;
}
}
Rml::ElementPtr ElementModMenu::CreateModListEntry(const recomp::mods::ModDetails& details, size_t index) {
Rml::ElementDocument *doc = GetOwnerDocument();
Rml::ElementPtr mod_el = doc->CreateElement("div");
mod_el->SetClass(cls_list_entry, true);
mod_el->SetAttribute("mod_index", index);
{
Rml::Element* thumbnail_el = add_div_with_class(doc, mod_el.get(), cls_list_entry_thumbnail);
Rml::Element *body_el = add_div_with_class(doc, mod_el.get(), cls_list_entry_body);
{
Rml::Element *name_el = add_div_with_class(doc, body_el, cls_list_entry_name);
name_el->SetInnerRML(details.mod_id);
Rml::Element *description_el = add_div_with_class(doc, body_el, cls_list_entry_description);
description_el->SetInnerRML("Short description of mod here.");
} // body_el
} // mod_el
return mod_el;
}
void ElementModMenu::CreateModList() {
Rml::ElementDocument *doc = GetOwnerDocument();
// Clear the contents of the list scroll.
list_el_scroll->SetInnerRML("");
Rml::Element* prev_el = refresh_button;
active_list_entry_el = nullptr;
bool first = true;
// Create the child elements for the list scroll.
for (size_t mod_index = 0; mod_index < mod_details.size(); mod_index++) {
const recomp::mods::ModDetails& details = mod_details[mod_index];
Rml::Element *mod_el = list_el_scroll->AppendChild(CreateModListEntry(details, mod_index));
mod_el->SetAttribute("mod_index", mod_index);
mod_el->AddEventListener(Rml::EventId::Focus, this, false);
mod_el->SetId("mod-list-entry-" + std::to_string(mod_index));
mod_el->SetProperty("nav-up", "#" + prev_el->GetId());
prev_el->SetProperty("nav-down", "#" + mod_el->GetId());
if (first) {
active_list_entry_el = mod_el;
}
first = false;
prev_el = mod_el;
}
active_list_entry_el->SetAttribute("is_selected", true);
DirtyLayout();
}
void ElementModMenu::RefreshMods() {
recomp::mods::scan_mods();
mod_details = recomp::mods::get_mod_details(game_mod_id);
mod_details_panel->set_mod_details(mod_details[0]);
CreateModList();
}
ElementModMenu::ElementModMenu(const Rml::String& tag) : Rml::Element(tag) {
game_mod_id = "mm";
SetAttribute("recomp-store-element", true);
Rml::ElementDocument *doc = GetOwnerDocument();
SetClass(cls_base, true);
Rml::Element *body_el = add_div_with_class(doc, this, "config__hz-wrapper");
{
list_el = add_div_with_class(doc, body_el, cls_list);
{
list_el_scroll = add_div_with_class(doc, list_el, cls_list_scroll);
} // list_el
recompui::Element body_el_compat(body_el);
mod_details_panel = std::make_unique<ModDetailsPanel>(&body_el_compat);
} // body_el
Rml::Element *footer_el = add_div_with_class(doc, this, "config__footer");
{
refresh_button = add_button(doc, footer_el, "Refresh", ButtonVariant::Primary);
refresh_button->AddEventListener(Rml::EventId::Click, this, false);
refresh_button->SetId("refresh-button");
} // footer_el
RefreshMods();
}
ElementModMenu::~ElementModMenu() {
}
} // namespace Rml

View File

@ -1,29 +0,0 @@
#ifndef RECOMPUI_ELEMENT_MOD_MENU_H
#define RECOMPUI_ELEMENT_MOD_MENU_H
#include "common.h"
#include "librecomp/mods.hpp"
#include "ui_mod_details_panel.h"
namespace recompui {
class ElementModMenu : public Rml::Element, public Rml::EventListener {
public:
ElementModMenu(const Rml::String& tag);
virtual ~ElementModMenu();
void ProcessEvent(Rml::Event& event) final;
private:
void RefreshMods();
void CreateModList();
Rml::ElementPtr CreateModListEntry(const recomp::mods::ModDetails& details, size_t index);
Rml::Element *refresh_button;
Rml::Element *list_el; // The root mod list element.
Rml::Element *list_el_scroll; // The scroll within the root mod list element.
std::unique_ptr<ModDetailsPanel> mod_details_panel;
Rml::Element *active_list_entry_el = nullptr;
std::vector<recomp::mods::ModDetails> mod_details{};
std::string game_mod_id;
};
} // namespace recompui
#endif

View File

@ -17,6 +17,24 @@ static Rml::Unit to_rml(Unit unit) {
}
}
static Rml::Style::AlignItems to_rml(AlignItems align_items) {
switch (align_items) {
case AlignItems::FlexStart:
return Rml::Style::AlignItems::FlexStart;
case AlignItems::FlexEnd:
return Rml::Style::AlignItems::FlexEnd;
case AlignItems::Center:
return Rml::Style::AlignItems::Center;
case AlignItems::Baseline:
return Rml::Style::AlignItems::Baseline;
case AlignItems::Stretch:
return Rml::Style::AlignItems::Stretch;
default:
assert(false && "Unknown align items.");
return Rml::Style::AlignItems::FlexStart;
}
}
static Rml::Style::Overflow to_rml(Overflow overflow) {
switch (overflow) {
case Overflow::Visible:
@ -33,18 +51,32 @@ static Rml::Style::Overflow to_rml(Overflow overflow) {
}
}
static Rml::Style::TextAlign to_rml(TextAlign text_align) {
switch (text_align) {
case TextAlign::Left:
return Rml::Style::TextAlign::Left;
case TextAlign::Right:
return Rml::Style::TextAlign::Right;
case TextAlign::Center:
return Rml::Style::TextAlign::Center;
case TextAlign::Justify:
return Rml::Style::TextAlign::Justify;
default:
assert(false && "Unknown text align.");
return Rml::Style::TextAlign::Left;
}
}
Element::Element(Rml::Element *base) {
assert(base != nullptr);
this->base = base;
this->parent = nullptr;
this->owner = false;
}
Element::Element(Element *parent, uint32_t events_enabled, Rml::String base_class) {
assert(parent != nullptr);
this->parent = parent;
this->owner = true;
base = parent->base->AppendChild(parent->base->GetOwnerDocument()->CreateElement(base_class));
@ -169,6 +201,22 @@ void Element::set_height_auto() {
set_property(Rml::PropertyId::Height, Rml::Property(Rml::Style::FlexBasis::Type::Auto, Rml::Unit::KEYWORD));
}
void Element::set_min_width(float width, Unit unit, Animation animation) {
set_property(Rml::PropertyId::MinWidth, Rml::Property(width, to_rml(unit)), animation);
}
void Element::set_min_height(float height, Unit unit, Animation animation) {
set_property(Rml::PropertyId::MinHeight, Rml::Property(height, to_rml(unit)), animation);
}
void Element::set_max_width(float width, Unit unit, Animation animation) {
set_property(Rml::PropertyId::MaxWidth, Rml::Property(width, to_rml(unit)), animation);
}
void Element::set_max_height(float height, Unit unit, Animation animation) {
set_property(Rml::PropertyId::MaxHeight, Rml::Property(height, to_rml(unit)), animation);
}
void Element::set_padding(float padding, Unit unit, Animation animation) {
set_property(Rml::PropertyId::PaddingLeft, Rml::Property(padding, to_rml(unit)), animation);
set_property(Rml::PropertyId::PaddingTop, Rml::Property(padding, to_rml(unit)), animation);
@ -223,6 +271,22 @@ void Element::set_border_width(float width, Unit unit, Animation animation) {
set_property(Rml::PropertyId::BorderRightWidth, property, animation);
}
void Element::set_border_left_width(float width, Unit unit, Animation animation) {
set_property(Rml::PropertyId::BorderLeftWidth, Rml::Property(width, to_rml(unit)), animation);
}
void Element::set_border_top_width(float width, Unit unit, Animation animation) {
set_property(Rml::PropertyId::BorderTopWidth, Rml::Property(width, to_rml(unit)), animation);
}
void Element::set_border_right_width(float width, Unit unit, Animation animation) {
set_property(Rml::PropertyId::BorderRightWidth, Rml::Property(width, to_rml(unit)), animation);
}
void Element::set_border_bottom_width(float width, Unit unit, Animation animation) {
set_property(Rml::PropertyId::BorderBottomWidth, Rml::Property(width, to_rml(unit)), animation);
}
void Element::set_border_radius(float radius, Unit unit, Animation animation) {
Rml::Property property(radius, to_rml(unit));
set_property(Rml::PropertyId::BorderTopLeftRadius, property, animation);
@ -260,6 +324,26 @@ void Element::set_border_color(const Color &color, Animation animation) {
set_property(Rml::PropertyId::BorderRightColor, property, animation);
}
void Element::set_border_left_color(const Color &color, Animation animation) {
Rml::Property property(Rml::Colourb(color.r, color.g, color.b, color.a), Rml::Unit::COLOUR);
set_property(Rml::PropertyId::BorderLeftColor, property, animation);
}
void Element::set_border_top_color(const Color &color, Animation animation) {
Rml::Property property(Rml::Colourb(color.r, color.g, color.b, color.a), Rml::Unit::COLOUR);
set_property(Rml::PropertyId::BorderTopColor, property, animation);
}
void Element::set_border_right_color(const Color &color, Animation animation) {
Rml::Property property(Rml::Colourb(color.r, color.g, color.b, color.a), Rml::Unit::COLOUR);
set_property(Rml::PropertyId::BorderRightColor, property, animation);
}
void Element::set_border_bottom_color(const Color &color, Animation animation) {
Rml::Property property(Rml::Colourb(color.r, color.g, color.b, color.a), Rml::Unit::COLOUR);
set_property(Rml::PropertyId::BorderBottomColor, property, animation);
}
void Element::set_color(const Color &color, Animation animation) {
Rml::Property property(Rml::Colourb(color.r, color.g, color.b, color.a), Rml::Unit::COLOUR);
set_property(Rml::PropertyId::Color, property, animation);
@ -365,6 +449,10 @@ void Element::set_flex_direction(FlexDirection flex_direction) {
}
}
void Element::set_align_items(AlignItems align_items) {
set_property(Rml::PropertyId::AlignItems, to_rml(align_items));
}
void Element::set_overflow(Overflow overflow) {
set_property(Rml::PropertyId::OverflowX, to_rml(overflow));
set_property(Rml::PropertyId::OverflowY, to_rml(overflow));
@ -412,4 +500,8 @@ void Element::set_text(const std::string &text) {
base->SetInnerRML(text);
}
void Element::set_text_align(TextAlign text_align) {
set_property(Rml::PropertyId::TextAlign, to_rml(text_align));
}
};

View File

@ -103,6 +103,14 @@ enum class FlexDirection {
Column
};
enum class AlignItems {
FlexStart,
FlexEnd,
Center,
Baseline,
Stretch
};
enum class Overflow {
Visible,
Hidden,
@ -126,6 +134,13 @@ enum class FontStyle {
Italic
};
enum class TextAlign {
Left,
Right,
Center,
Justify
};
struct Animation {
AnimationType type = AnimationType::None;
float duration = 0.0f;
@ -146,7 +161,6 @@ private:
// Rml::EventListener overrides.
virtual void ProcessEvent(Rml::Event &event) override;
protected:
Element *parent;
Rml::Element *base;
bool owner;
@ -167,6 +181,10 @@ public:
void set_width_auto();
void set_height(float height, Unit unit = Unit::Dp, Animation animation = Animation());
void set_height_auto();
void set_min_width(float width, Unit unit = Unit::Dp, Animation animation = Animation());
void set_min_height(float height, Unit unit = Unit::Dp, Animation animation = Animation());
void set_max_width(float width, Unit unit = Unit::Dp, Animation animation = Animation());
void set_max_height(float height, Unit unit = Unit::Dp, Animation animation = Animation());
void set_padding(float padding, Unit unit = Unit::Dp, Animation animation = Animation());
void set_padding_left(float padding, Unit unit = Unit::Dp, Animation animation = Animation());
void set_padding_top(float padding, Unit unit = Unit::Dp, Animation animation = Animation());
@ -178,6 +196,10 @@ public:
void set_margin_right(float margin, Unit unit = Unit::Dp, Animation animation = Animation());
void set_margin_bottom(float margin, Unit unit = Unit::Dp, Animation animation = Animation());
void set_border_width(float width, Unit unit = Unit::Dp, Animation animation = Animation());
void set_border_left_width(float width, Unit unit = Unit::Dp, Animation animation = Animation());
void set_border_top_width(float width, Unit unit = Unit::Dp, Animation animation = Animation());
void set_border_right_width(float width, Unit unit = Unit::Dp, Animation animation = Animation());
void set_border_bottom_width(float width, Unit unit = Unit::Dp, Animation animation = Animation());
void set_border_radius(float radius, Unit unit = Unit::Dp, Animation animation = Animation());
void set_border_top_left_radius(float radius, Unit unit = Unit::Dp, Animation animation = Animation());
void set_border_top_right_radius(float radius, Unit unit = Unit::Dp, Animation animation = Animation());
@ -185,6 +207,10 @@ public:
void set_border_bottom_right_radius(float radius, Unit unit = Unit::Dp, Animation animation = Animation());
void set_background_color(const Color &color, Animation animation = Animation());
void set_border_color(const Color &color, Animation animation = Animation());
void set_border_left_color(const Color &color, Animation animation = Animation());
void set_border_top_color(const Color &color, Animation animation = Animation());
void set_border_right_color(const Color &color, Animation animation = Animation());
void set_border_bottom_color(const Color &color, Animation animation = Animation());
void set_color(const Color &color, Animation animation = Animation());
void set_cursor(Cursor cursor);
void set_opacity(float opacity, Animation animation = Animation());
@ -197,6 +223,7 @@ public:
void set_flex(float grow, float shrink, Animation animation = Animation());
void set_flex(float grow, float shrink, float basis_percentage, Animation animation = Animation());
void set_flex_direction(FlexDirection flex_direction);
void set_align_items(AlignItems align_items);
void set_overflow(Overflow overflow);
void set_overflow_x(Overflow overflow);
void set_overflow_y(Overflow overflow);
@ -206,6 +233,7 @@ public:
void set_font_style(FontStyle style);
void set_font_weight(uint32_t weight, Animation animation = Animation());
void set_text(const std::string &text);
void set_text_align(TextAlign text_align);
};
} // namespace recompui

View File

@ -6,20 +6,27 @@ namespace recompui {
Label::Label(LabelStyle label_style, Element *parent) : Element(parent) {
switch (label_style) {
case LabelStyle::Small:
set_font_size(20.0f);
set_letter_spacing(0.0f);
set_line_height(20.0f);
set_font_weight(400);
break;
case LabelStyle::Normal:
set_font_size(28.0f);
set_letter_spacing(3.08f);
set_line_height(28.0f);
set_font_weight(700);
break;
case LabelStyle::Large:
set_font_size(36.0f);
set_letter_spacing(2.52f);
set_line_height(36.0f);
set_font_weight(700);
break;
}
set_font_style(FontStyle::Normal);
set_font_weight(700);
}
Label::Label(const std::string &text, LabelStyle label_style, Element *parent) : Label(label_style, parent) {

View File

@ -5,6 +5,7 @@
namespace recompui {
enum class LabelStyle {
Small,
Normal,
Large
};

View File

@ -0,0 +1,27 @@
#include "ui_scroll_container.h"
#include <cassert>
namespace recompui {
ScrollContainer::ScrollContainer(ScrollDirection direction, Element *parent) : Element(parent) {
set_flex(1.0f, 1.0f, 100.0f);
set_width(100.0f, Unit::Percent);
set_height(100.0f, Unit::Percent);
switch (direction) {
case ScrollDirection::Horizontal:
set_max_width(100.0f, Unit::Percent);
set_overflow_x(Overflow::Auto);
break;
case ScrollDirection::Vertical:
set_max_height(100.0f, Unit::Percent);
set_overflow_y(Overflow::Auto);
break;
default:
assert(false && "Unknown scroll direction.");
break;
}
}
};

View File

@ -0,0 +1,17 @@
#pragma once
#include "ui_element.h"
namespace recompui {
enum class ScrollDirection {
Horizontal,
Vertical
};
class ScrollContainer : public Element {
public:
ScrollContainer(ScrollDirection direction, Element *parent);
};
} // namespace recompui

View File

@ -14,7 +14,7 @@
#include "elements/ElementOptionTypeRange.h"
#include "elements/ElementOptionTypeTextField.h"
#include "elements/ElementDescription.h"
#include "elements/ElementModMenu.h"
#include "ui_mod_menu.h"
namespace recompui {
void register_custom_elements();

View File

@ -1,6 +1,5 @@
#include "ui_mod_details_panel.h"
#include "presets.h"
#include "librecomp/mods.hpp"
namespace recompui {

View File

@ -1,13 +1,12 @@
#ifndef RECOMPUI_ELEMENT_MOD_DETAILS_PANEL_H
#define RECOMPUI_ELEMENT_MOD_DETAILS_PANEL_H
#include "common.h"
#include "librecomp/mods.hpp"
#include "ui_button.h"
#include "ui_container.h"
#include "ui_image.h"
#include "ui_label.h"
#include "ui_toggle.h"
#include "elements/ui_button.h"
#include "elements/ui_container.h"
#include "elements/ui_image.h"
#include "elements/ui_label.h"
#include "elements/ui_toggle.h"
namespace recompui {

161
src/ui/ui_mod_menu.cpp Normal file
View File

@ -0,0 +1,161 @@
#include "ui_mod_menu.h"
#include "elements/presets.h"
#include "librecomp/mods.hpp"
#include <string>
// TODO:
// - Set up navigation.
// - Add hover and active state for mod entries.
namespace recompui {
ModEntry::ModEntry(Element *parent, const recomp::mods::ModDetails &details, uint32_t mod_index, ModMenu *mod_menu) : Element(parent, Events(EventType::Click, EventType::Hover, EventType::Focus)) {
assert(mod_menu != nullptr);
this->mod_index = mod_index;
this->mod_menu = mod_menu;
set_display(Display::Flex);
set_flex_direction(FlexDirection::Row);
set_width(100.0f, Unit::Percent);
set_height_auto();
set_padding_top(4.0f);
set_padding_right(8.0f);
set_padding_bottom(4.0f);
set_padding_left(8.0f);
set_border_width(1.1f);
set_border_color(Color{ 242, 242, 242, 204 });
set_background_color(Color{ 242, 242, 242, 12 });
set_cursor(Cursor::Pointer);
{
thumbnail_image = std::make_unique<Image>(this);
thumbnail_image->set_width(100.0f);
thumbnail_image->set_height(100.0f);
thumbnail_image->set_min_width(100.0f);
thumbnail_image->set_min_height(100.0f);
thumbnail_image->set_background_color(Color{ 190, 184, 219, 25 });
body_container = std::make_unique<Container>(FlexDirection::Column, JustifyContent::FlexStart, this);
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 = std::make_unique<Label>(details.mod_id, LabelStyle::Normal, body_container.get());
description_label = std::make_unique<Label>("Short description of mod here.", LabelStyle::Small, body_container.get());
} // body_container
} // this
}
ModEntry::~ModEntry() {
}
void ModEntry::process_event(const Event& e) {
switch (e.type) {
case EventType::Click:
mod_menu->set_active_mod(mod_index);
break;
case EventType::Hover:
break;
case EventType::Focus:
break;
default:
break;
}
}
void ModMenu::set_active_mod(uint32_t mod_index) {
mod_details_panel->set_mod_details(mod_details[mod_index]);
}
void ModMenu::refresh_mods() {
recomp::mods::scan_mods();
mod_details = recomp::mods::get_mod_details(game_mod_id);
create_mod_list();
}
void ModMenu::create_mod_list() {
// Clear the contents of the list scroll.
mod_entries.clear();
// Create the child elements for the list scroll.
for (size_t mod_index = 0; mod_index < mod_details.size(); mod_index++) {
mod_entries.emplace_back(std::make_unique<ModEntry>(list_scroll_container.get(), mod_details[mod_index], mod_index, this));
}
set_active_mod(0);
}
ModMenu::ModMenu(Element *parent) : Element(parent) {
game_mod_id = "mm";
set_display(Display::Flex);
set_flex(1.0f, 1.0f, 100.0f);
set_flex_direction(FlexDirection::Column);
set_align_items(AlignItems::Center);
set_justify_content(JustifyContent::FlexStart);
set_width(100.0f, Unit::Percent);
set_height(100.0f, Unit::Percent);
{
body_container = std::make_unique<Container>(FlexDirection::Row, JustifyContent::FlexStart, this);
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 = std::make_unique<Container>(FlexDirection::Column, JustifyContent::Center, body_container.get());
list_container->set_display(Display::Block);
list_container->set_flex_basis_percentage(100.0f);
list_container->set_align_items(AlignItems::Center);
list_container->set_height(100.0f, Unit::Percent);
list_container->set_background_color(Color{ 0, 0, 0, 89 });
list_container->set_border_bottom_left_radius(16.0f);
{
list_scroll_container = std::make_unique<ScrollContainer>(ScrollDirection::Vertical, list_container.get());
} // list_container
mod_details_panel = std::make_unique<ModDetailsPanel>(body_container.get());
} // body_container
footer_container = std::make_unique<recompui::Container>(FlexDirection::Row, JustifyContent::SpaceBetween, this);
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 });
footer_container->set_border_top_width(1.1f);
footer_container->set_border_top_color(Color{ 255, 255, 255, 25 });
footer_container->set_padding(20.0f);
footer_container->set_border_bottom_left_radius(16.0f);
footer_container->set_border_bottom_right_radius(16.0f);
{
refresh_button = std::make_unique<recompui::Button>("Refresh", recompui::ButtonStyle::Primary, footer_container.get());
refresh_button->add_pressed_callback(std::bind(&ModMenu::refresh_mods, this));
} // footer_container
} // this
refresh_mods();
}
ModMenu::~ModMenu() {
}
// Placeholder class until the rest of the UI refactor is finished.
ElementModMenu::ElementModMenu(const Rml::String &tag) : Rml::Element(tag) {
SetProperty("width", "100%");
SetProperty("height", "100%");
recompui::Element this_compat(this);
mod_menu = std::make_unique<ModMenu>(&this_compat);
}
ElementModMenu::~ElementModMenu() {
}
} // namespace recompui

56
src/ui/ui_mod_menu.h Normal file
View File

@ -0,0 +1,56 @@
#ifndef RECOMPUI_ELEMENT_MOD_MENU_H
#define RECOMPUI_ELEMENT_MOD_MENU_H
#include "librecomp/mods.hpp"
#include "elements/ui_scroll_container.h"
#include "ui_mod_details_panel.h"
namespace recompui {
class ModMenu;
class ModEntry : public Element {
public:
ModEntry(Element *parent, const recomp::mods::ModDetails &details, uint32_t mod_index, ModMenu *mod_menu);
virtual ~ModEntry();
protected:
virtual void process_event(const Event &e);
private:
uint32_t mod_index;
ModMenu *mod_menu;
std::unique_ptr<Image> thumbnail_image;
std::unique_ptr<Container> body_container;
std::unique_ptr<Label> name_label;
std::unique_ptr<Label> description_label;
};
class ModMenu : public Element {
public:
ModMenu(Element *parent);
virtual ~ModMenu();
void set_active_mod(uint32_t mod_index);
private:
void refresh_mods();
void create_mod_list();
std::unique_ptr<Container> body_container;
std::unique_ptr<Container> list_container;
std::unique_ptr<ScrollContainer> list_scroll_container;
std::unique_ptr<ModDetailsPanel> mod_details_panel;
std::unique_ptr<Container> footer_container;
std::unique_ptr<Button> refresh_button;
std::vector<std::unique_ptr<ModEntry>> mod_entries;
std::vector<recomp::mods::ModDetails> mod_details{};
std::string game_mod_id;
};
class ElementModMenu : public Rml::Element {
public:
ElementModMenu(const Rml::String& tag);
virtual ~ElementModMenu();
private:
std::unique_ptr<ModMenu> mod_menu;
};
} // namespace recompui
#endif