lots of work on ModPopup

This commit is contained in:
HJfod 2024-03-24 00:34:47 +02:00
parent 56679e739b
commit f40ced5bff
10 changed files with 249 additions and 9 deletions

BIN
loader/resources/close.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 24 KiB

After

Width:  |  Height:  |  Size: 9.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.4 KiB

View file

@ -48,10 +48,32 @@ GeodeSquareSprite* GeodeSquareSprite::createWithSpriteFrameName(const char* top,
return nullptr;
}
IconButtonSprite* createGeodeButton(CCNode* icon, std::string const& text, std::string const& bg) {
return IconButtonSprite::create(bg.c_str(), icon, text.c_str(), "bigFont.fnt");
}
CCNode* createGeodeButton(CCNode* icon, float width, std::string const& text, std::string const& bgSpr) {
auto bg = CCScale9Sprite::create(bgSpr.c_str());
bg->setContentSize({ width, 35 });
limitNodeSize(icon, { 20, 20 }, 1.f, .1f);
bg->addChildAtPosition(icon, Anchor::Left, { 35.f / 2, 0 }, { .5f, .5f });
auto label = CCLabelBMFont::create(text.c_str(), "bigFont.fnt");
limitNodeSize(label, { width - 42.5f, 20 }, .6f, .1f);
bg->addChildAtPosition(label, Anchor::Left, { 35, 0 }, { 0, .5f });
return bg;
}
ButtonSprite* createGeodeButton(std::string const& text, std::string const& bg) {
return ButtonSprite::create(text.c_str(), "bigFont.fnt", bg.c_str(), .8f);
}
CircleButtonSprite* createGeodeCircleButton(const char* topFrameName) {
return CircleButtonSprite::createWithSpriteFrameName(topFrameName, 1.f, CircleBaseColor::DarkPurple);
}
bool GeodeTabSprite::init(const char* iconFrame, const char* text, float width) {
if (!CCNode::init())
return false;

View file

@ -1,9 +1,32 @@
#pragma once
#include <Geode/DefaultInclude.hpp>
#include <Geode/ui/IconButtonSprite.hpp>
#include <Geode/ui/BasedButtonSprite.hpp>
using namespace geode::prelude;
template <class... Args>
class GeodePopup : public Popup<Args...> {
protected:
bool init(float width, float height, Args... args) {
if (!Popup<Args...>::initAnchored(width, height, std::forward<Args>(args)..., "GE_square01.png"_spr))
return false;
// Replace the close button with a Geode style one
auto origSize = Popup<Args...>::m_closeBtn->getContentSize();
auto orig = Ref(Popup<Args...>::m_closeBtn->getNormalImage());
auto spr = CircleButtonSprite::createWithSpriteFrameName("close.png"_spr, 1.f, CircleBaseColor::DarkPurple);
Popup<Args...>::m_closeBtn->setNormalImage(spr);
spr->setScale(orig->getScale());
spr->setPosition(orig->getPosition());
spr->setAnchorPoint(orig->getAnchorPoint());
Popup<Args...>::m_closeBtn->setContentSize(origSize);
return true;
}
};
class GeodeSquareSprite : public CCSprite {
protected:
bool* m_stateSrc = nullptr;
@ -18,8 +41,12 @@ public:
static GeodeSquareSprite* createWithSpriteFrameName(const char* top, bool* state = nullptr);
};
IconButtonSprite* createGeodeButton(CCNode* icon, std::string const& text, std::string const& bg = "GE_button_05.png"_spr);
CCNode* createGeodeButton(CCNode* icon, float width, std::string const& text, std::string const& bg = "GE_button_05.png"_spr);
ButtonSprite* createGeodeButton(std::string const& text, std::string const& bg = "GE_button_05.png"_spr);
CircleButtonSprite* createGeodeCircleButton(const char* topFrameName);
class GeodeTabSprite : public CCNode {
protected:
CCScale9Sprite* m_deselectedBG;

View file

@ -1,5 +1,7 @@
#include "ModPopup.hpp"
#include <Geode/ui/MDTextArea.hpp>
#include <Geode/utils/web.hpp>
#include <Geode/ui/GeodeUI.hpp>
bool ModPopup::setup(ModSource&& src) {
m_source = std::move(src);
@ -15,7 +17,7 @@ bool ModPopup::setup(ModSource&& src) {
);
auto leftColumn = CCNode::create();
leftColumn->setContentSize({ 145, mainContainer->getContentHeight() - 30 });
leftColumn->setContentSize({ 145, mainContainer->getContentHeight() });
auto titleContainer = CCNode::create();
titleContainer->setContentSize({ leftColumn->getContentWidth(), 25 });
@ -47,14 +49,25 @@ bool ModPopup::setup(ModSource&& src) {
leftColumn->addChild(titleContainer);
auto idStr = "(ID: " + m_source.getMetadata().getID() + ")";
auto idLabel = CCLabelBMFont::create(idStr.c_str(), "bigFont.fnt");
idLabel->limitLabelWidth(leftColumn->getContentWidth(), .25f, .05f);
idLabel->setColor({ 150, 150, 150 });
idLabel->setOpacity(140);
leftColumn->addChild(idLabel);
auto gap = CCNode::create();
gap->setContentHeight(6);
leftColumn->addChild(gap);
auto statsContainer = CCNode::create();
statsContainer->setContentSize({ leftColumn->getContentWidth(), 80 });
statsContainer->setAnchorPoint({ .5f, .5f });
auto statsBG = CCScale9Sprite::create("square02b_001.png");
statsBG->setColor({ 0, 0, 0 });
statsBG->setOpacity(90);
statsBG->setScale(.6f);
statsBG->setOpacity(75);
statsBG->setScale(.3f);
statsBG->setContentSize(statsContainer->getContentSize() / statsBG->getScale());
statsContainer->addChildAtPosition(statsBG, Anchor::Center);
@ -133,13 +146,171 @@ bool ModPopup::setup(ModSource&& src) {
leftColumn->addChild(statsContainer);
leftColumn->addChild(SpacerNode::create());
// Installing
auto installContainer = CCNode::create();
installContainer->setContentSize({ leftColumn->getContentWidth(), 25 });
installContainer->setAnchorPoint({ .5f, .5f });
auto installBG = CCScale9Sprite::create("square02b_001.png");
installBG->setColor({ 0, 0, 0 });
installBG->setOpacity(75);
installBG->setScale(.3f);
installBG->setContentSize(installContainer->getContentSize() / installBG->getScale());
installContainer->addChildAtPosition(installBG, Anchor::Center);
auto installMenu = CCMenu::create();
installMenu->ignoreAnchorPointForPosition(false);
installMenu->setContentSize(installContainer->getContentSize() - ccp(10, 10));
installMenu->setAnchorPoint({ .5f, .5f });
for (auto stat : std::initializer_list<std::tuple<
const char*, const char*, SEL_MenuHandler
>> {
{ "GJ_deleteIcon_001.png", "Disable", nullptr },
{ "edit_delBtn_001.png", "Uninstall", nullptr },
}) {
auto spr = createGeodeButton(
CCSprite::createWithSpriteFrameName(std::get<0>(stat)),
std::get<1>(stat)
);
spr->setScale(.5f);
auto btn = CCMenuItemSpriteExtra::create(
spr, this, std::get<2>(stat)
);
installMenu->addChild(btn);
}
installMenu->setLayout(
RowLayout::create()
->setDefaultScaleLimits(.1f, 1)
->setAxisAlignment(AxisAlignment::Center)
);
installContainer->addChildAtPosition(installMenu, Anchor::Center);
leftColumn->addChild(installContainer);
// Options
auto optionsContainer = CCNode::create();
optionsContainer->setContentSize({ leftColumn->getContentWidth(), 25 });
optionsContainer->setAnchorPoint({ .5f, .5f });
auto optionsBG = CCScale9Sprite::create("square02b_001.png");
optionsBG->setColor({ 0, 0, 0 });
optionsBG->setOpacity(75);
optionsBG->setScale(.3f);
optionsBG->setContentSize(optionsContainer->getContentSize() / optionsBG->getScale());
optionsContainer->addChildAtPosition(optionsBG, Anchor::Center);
auto optionsMenu = CCMenu::create();
optionsMenu->ignoreAnchorPointForPosition(false);
optionsMenu->setContentSize(optionsContainer->getContentSize() - ccp(10, 10));
optionsMenu->setAnchorPoint({ .5f, .5f });
for (auto stat : std::initializer_list<std::tuple<
const char*, const char*, SEL_MenuHandler
>> {
{ "folderIcon_001.png", "Config", nullptr },
{ "folderIcon_001.png", "Save Data", nullptr },
}) {
auto spr = createGeodeButton(
CCSprite::createWithSpriteFrameName(std::get<0>(stat)),
std::get<1>(stat)
);
spr->setScale(.5f);
auto btn = CCMenuItemSpriteExtra::create(
spr, this, std::get<2>(stat)
);
optionsMenu->addChild(btn);
}
optionsMenu->setLayout(
RowLayout::create()
->setDefaultScaleLimits(.1f, 1)
->setAxisAlignment(AxisAlignment::Center)
);
optionsContainer->addChildAtPosition(optionsMenu, Anchor::Center);
leftColumn->addChild(optionsContainer);
// Links
auto linksContainer = CCNode::create();
linksContainer->setContentSize({ leftColumn->getContentWidth() - 40, 30 });
linksContainer->setAnchorPoint({ .5f, .5f });
linksContainer->setLayoutOptions(
AxisLayoutOptions::create()
->setCrossAxisAlignment(AxisAlignment::End)
);
auto linksBG = CCScale9Sprite::create("square02b_001.png");
linksBG->setColor({ 0, 0, 0 });
linksBG->setOpacity(75);
linksBG->setScale(.3f);
linksBG->setContentSize(linksContainer->getContentSize() / linksBG->getScale());
linksContainer->addChildAtPosition(linksBG, Anchor::Center);
auto linksMenu = CCMenu::create();
linksMenu->ignoreAnchorPointForPosition(false);
linksMenu->setContentSize(linksContainer->getContentSize() - ccp(10, 10));
linksMenu->setAnchorPoint({ .5f, .5f });
// auto linksLabel = CCLabelBMFont::create("Links", "bigFont.fnt");
// linksLabel->setLayoutOptions(
// AxisLayoutOptions::create()
// ->setRelativeScale(.35f)
// );
// linksMenu->addChild(linksLabel);
for (auto stat : std::initializer_list<std::tuple<
const char*, std::optional<std::string>, SEL_MenuHandler
>> {
{ "homepage.png"_spr, m_source.getMetadata().getLinks().getHomepageURL(), nullptr },
{ "github.png"_spr, m_source.getMetadata().getLinks().getSourceURL(), nullptr },
{ "gj_discordIcon_001.png", m_source.getMetadata().getLinks().getCommunityURL(), nullptr },
{ "gift.png"_spr, m_source.getMetadata().getSupportInfo(), menu_selector(ModPopup::onSupport) },
}) {
auto spr = CCSprite::createWithSpriteFrameName(std::get<0>(stat));
spr->setScale(.75f);
if (!std::get<1>(stat).has_value()) {
spr->setColor({ 155, 155, 155 });
spr->setOpacity(155);
}
auto btn = CCMenuItemSpriteExtra::create(
spr, this, (
std::get<1>(stat).has_value() ?
(std::get<2>(stat) ? std::get<2>(stat) : menu_selector(ModPopup::onLink)) :
nullptr
)
);
if (!std::get<2>(stat) && std::get<1>(stat)) {
btn->setUserObject("url", CCString::create(*std::get<1>(stat)));
}
linksMenu->addChild(btn);
}
linksMenu->setLayout(
RowLayout::create()
->setDefaultScaleLimits(.1f, 1)
->setAxisAlignment(AxisAlignment::Center)
);
linksContainer->addChildAtPosition(linksMenu, Anchor::Center);
leftColumn->addChild(linksContainer);
// auto bottomPadding = CCNode::create();
// bottomPadding->setContentHeight(13);
// leftColumn->addChild(bottomPadding);
leftColumn->setLayout(
ColumnLayout::create()
->setAxisReverse(true)
->setCrossAxisOverflow(false)
->setDefaultScaleLimits(.1f, 1)
->setAutoScale(false)
->setAxisAlignment(AxisAlignment::Start)
->setCrossAxisLineAlignment(AxisAlignment::Start)
->setGap(5)
);
mainContainer->addChild(leftColumn);
@ -177,6 +348,13 @@ bool ModPopup::setup(ModSource&& src) {
mainContainer->updateLayout();
m_mainLayer->addChildAtPosition(mainContainer, Anchor::Center);
auto settingsSpr = createGeodeCircleButton("settings.png"_spr);
settingsSpr->setScale(.6f);
auto settingsBtn = CCMenuItemSpriteExtra::create(
settingsSpr, this, nullptr
);
m_buttonMenu->addChildAtPosition(settingsBtn, Anchor::BottomLeft, ccp(28, 25));
// Select details tab
this->loadTab(Tab::Details);
@ -329,9 +507,18 @@ void ModPopup::onTab(CCObject* sender) {
this->loadTab(static_cast<Tab>(sender->getTag()));
}
void ModPopup::onLink(CCObject* sender) {
auto url = static_cast<CCString*>(static_cast<CCNode*>(sender)->getUserObject("url"));
web::openLinkInBrowser(url->getCString());
}
void ModPopup::onSupport(CCObject*) {
openSupportPopup(m_source.getMetadata());
}
ModPopup* ModPopup::create(ModSource&& src) {
auto ret = new ModPopup();
if (ret && ret->initAnchored(440, 280, std::move(src), "GE_square01.png"_spr)) {
if (ret && ret->init(440, 280, std::move(src))) {
ret->autorelease();
return ret;
}

View file

@ -7,7 +7,7 @@
using namespace geode::prelude;
class ModPopup : public Popup<ModSource&&> {
class ModPopup : public GeodePopup<ModSource&&> {
protected:
enum class Tab {
Details,
@ -32,6 +32,9 @@ protected:
void loadTab(Tab tab);
void onTab(CCObject* sender);
void onLink(CCObject*);
void onSupport(CCObject*);
public:
static ModPopup* create(ModSource&& src);
};

View file

@ -19,7 +19,7 @@ void TagsPopup::onClose(CCObject* sender) {
TagsPopup* TagsPopup::create(ModListSource* src, MiniFunction<void()> onClose) {
auto ret = new TagsPopup();
if (ret && ret->initAnchored(260, 200, src, onClose, "GJ_square02.png")) {
if (ret && ret->init(260, 200, src, onClose)) {
ret->autorelease();
return ret;
}

View file

@ -2,10 +2,11 @@
#include <Geode/ui/Popup.hpp>
#include "../sources/ModListSource.hpp"
#include "../GeodeStyle.hpp"
using namespace geode::prelude;
class TagsPopup : public Popup<ModListSource*, MiniFunction<void()>> {
class TagsPopup : public GeodePopup<ModListSource*, MiniFunction<void()>> {
protected:
ModListSource* m_source;
MiniFunction<void()> m_onClose;