initial mod popup work! :)

This commit is contained in:
HJfod 2024-03-01 17:05:20 +02:00
parent 65f6158774
commit 6414737b0c
6 changed files with 183 additions and 40 deletions

Binary file not shown.

After

(image error) Size: 4.2 KiB

View file

@ -48,6 +48,63 @@ GeodeSquareSprite* GeodeSquareSprite::createWithSpriteFrameName(const char* top,
return nullptr;
}
ButtonSprite* createGeodeButton(std::string const& text) {
return ButtonSprite::create(text.c_str(), "bigFont.fnt", "GE_button_05.png"_spr, .8f);
ButtonSprite* createGeodeButton(std::string const& text, std::string const& bg) {
return ButtonSprite::create(text.c_str(), "bigFont.fnt", bg.c_str(), .8f);
}
bool GeodeTabSprite::init(const char* iconFrame, const char* text, float width) {
if (!CCNode::init())
return false;
const CCSize itemSize { width, 35 };
const CCSize iconSize { 18, 18 };
this->setContentSize(itemSize);
this->setAnchorPoint({ .5f, .5f });
m_deselectedBG = CCScale9Sprite::createWithSpriteFrameName("tab-bg.png"_spr);
m_deselectedBG->setScale(.8f);
m_deselectedBG->setContentSize(itemSize / .8f);
m_deselectedBG->setColor({ 26, 24, 29 });
this->addChildAtPosition(m_deselectedBG, Anchor::Center);
m_selectedBG = CCScale9Sprite::createWithSpriteFrameName("tab-bg.png"_spr);
m_selectedBG->setScale(.8f);
m_selectedBG->setContentSize(itemSize / .8f);
m_selectedBG->setColor({ 168, 147, 185 });
this->addChildAtPosition(m_selectedBG, Anchor::Center);
m_icon = CCSprite::createWithSpriteFrameName(iconFrame);
limitNodeSize(m_icon, iconSize, 3.f, .1f);
this->addChildAtPosition(m_icon, Anchor::Left, ccp(16, 0), false);
m_label = CCLabelBMFont::create(text, "bigFont.fnt");
m_label->limitLabelWidth(this->getContentWidth() - 34, .55f, .1f);
m_label->setAnchorPoint({ .0f, .5f });
this->addChildAtPosition(m_label, Anchor::Left, ccp(28, 0), false);
return true;
}
GeodeTabSprite* GeodeTabSprite::create(const char* iconFrame, const char* text, float width) {
auto ret = new GeodeTabSprite();
if (ret && ret->init(iconFrame, text, width)) {
ret->autorelease();
return ret;
}
CC_SAFE_DELETE(ret);
return nullptr;
}
void GeodeTabSprite::select(bool selected) {
m_deselectedBG->setVisible(!selected);
m_selectedBG->setVisible(selected);
}
void GeodeTabSprite::disable(bool disabled) {
auto color = disabled ? ccc3(95, 95, 95) : ccc3(255, 255, 255);
m_deselectedBG->setColor(color);
m_selectedBG->setColor(color);
m_icon->setColor(color);
m_label->setColor(color);
}

View file

@ -18,12 +18,20 @@ public:
static GeodeSquareSprite* createWithSpriteFrameName(const char* top, bool* state = nullptr);
};
ButtonSprite* createGeodeButton(std::string const& text);
ButtonSprite* createGeodeButton(std::string const& text, std::string const& bg = "GE_button_05.png"_spr);
class GeodeButtonSprite : public ButtonSprite {
class GeodeTabSprite : public CCNode {
protected:
bool init(std::string const& text);
CCScale9Sprite* m_deselectedBG;
CCScale9Sprite* m_selectedBG;
CCSprite* m_icon;
CCLabelBMFont* m_label;
bool init(const char* iconFrame, const char* text, float width);
public:
static GeodeButtonSprite* create(std::string const& text);
static GeodeTabSprite* create(const char* iconFrame, const char* text, float width);
void select(bool selected);
void disable(bool disabled);
};

View file

@ -1,15 +1,109 @@
#include "ModPopup.hpp"
#include <Geode/ui/MDTextArea.hpp>
#include "GeodeStyle.hpp"
std::optional<std::string> getModMarkdownData(ModSource const& src, ModMarkdownData data) {
switch (data) {
default: return std::nullopt;
case ModMarkdownData::Details: return src.getMetadata().getDetails().value_or("No description provided");
case ModMarkdownData::Changelog: return src.getMetadata().getChangelog();
}
}
bool ModPopup::setup(ModSource&& src) {
m_source = std::move(src);
m_noElasticity = true;
const CCSize titleSize { 230, 50 };
const float titlePad = 10;
auto titleContainer = CCNode::create();
titleContainer->setContentSize(titleSize);
titleContainer->setAnchorPoint({ 0, 1 });
titleContainer->setScale(.6f);
auto logo = m_source.createModLogo();
limitNodeSize(logo, { titleSize.height, titleSize.height }, 5.f, .1f);
titleContainer->addChildAtPosition(logo, Anchor::Left, ccp(titleSize.height / 2, 0));
auto title = CCLabelBMFont::create(m_source.getMetadata().getName().c_str(), "bigFont.fnt");
title->limitLabelWidth(titleSize.width - titleSize.height - titlePad, 1.f, .1f);
title->setAnchorPoint({ .0f, .5f });
titleContainer->addChildAtPosition(title, Anchor::TopLeft, ccp(titleSize.height + titlePad, -titleSize.height * .25f));
auto by = "By " + ModMetadata::formatDeveloperDisplayString(m_source.getMetadata().getDevelopers());
auto dev = CCLabelBMFont::create(by.c_str(), "goldFont.fnt");
dev->limitLabelWidth(titleSize.width - titleSize.height - titlePad, .75f, .1f);
dev->setAnchorPoint({ .0f, .5f });
titleContainer->addChildAtPosition(dev, Anchor::BottomLeft, ccp(titleSize.height + titlePad, titleSize.height * .25f));
m_mainLayer->addChildAtPosition(titleContainer, Anchor::TopLeft, ccp(20, -35));
auto statsBG = CCScale9Sprite::create("square02b_001.png");
statsBG->setColor({ 0, 0, 0 });
statsBG->setOpacity(90);
statsBG->setAnchorPoint({ 0, 0 });
statsBG->setContentSize({ 120, 130 });
m_mainLayer->addChildAtPosition(statsBG, Anchor::BottomLeft, ccp(30, 30));
auto tabsSize = CCSize { 250, 250 };
auto tabsContainer = CCNode::create();
tabsContainer->setContentSize(tabsSize);
tabsContainer->setAnchorPoint({ 1.f, .5f });
m_mdArea = MDTextArea::create("", (tabsSize - ccp(0, 30)));
m_mdArea->setAnchorPoint({ .5f, .0f });
tabsContainer->addChildAtPosition(m_mdArea, Anchor::Bottom);
m_tabsMenu = CCMenu::create();
m_tabsMenu->ignoreAnchorPointForPosition(false);
m_tabsMenu->setScale(.65f);
m_tabsMenu->setContentWidth(m_mdArea->getScaledContentSize().width / m_tabsMenu->getScale());
m_tabsMenu->setAnchorPoint({ .5f, 1.f });
for (auto mdTab : std::initializer_list<std::tuple<const char*, const char*, ModMarkdownData>> {
{ "GJ_chatBtn_02_001.png", "Description", ModMarkdownData::Details },
{ "changelog.png"_spr, "Changelog", ModMarkdownData::Changelog },
}) {
auto btn = CCMenuItemSpriteExtra::create(
GeodeTabSprite::create(std::get<0>(mdTab), std::get<1>(mdTab), 140),
this, menu_selector(ModPopup::onMDTab)
);
if (auto data = getModMarkdownData(m_source, std::get<2>(mdTab))) {
btn->setTag(static_cast<int>(std::get<2>(mdTab)));
}
else {
btn->setEnabled(false);
static_cast<GeodeTabSprite*>(btn->getNormalImage())->disable(true);
}
m_tabsMenu->addChild(btn);
}
m_tabsMenu->setLayout(RowLayout::create());
tabsContainer->addChildAtPosition(m_tabsMenu, Anchor::Top);
m_mainLayer->addChildAtPosition(tabsContainer, Anchor::Right, ccp(-20, 0));
// Select details tab
this->onMDTab(m_tabsMenu->getChildren()->firstObject());
return true;
}
void ModPopup::onMDTab(CCObject* sender) {
if (auto data = getModMarkdownData(m_source, static_cast<ModMarkdownData>(sender->getTag()))) {
m_mdArea->setString(data.value().c_str());
}
// Highlight selected tab
for (auto tab : CCArrayExt<CCMenuItemSpriteExtra*>(m_tabsMenu->getChildren())) {
static_cast<GeodeTabSprite*>(tab->getNormalImage())->select(tab->getTag() == sender->getTag());
}
}
ModPopup* ModPopup::create(ModSource&& src) {
auto ret = new ModPopup();
if (ret && ret->init(358.f, 250.f, std::move(src))) {
if (ret && ret->initAnchored(440, 280, std::move(src), "GE_square01.png"_spr)) {
ret->autorelease();
return ret;
}

View file

@ -1,16 +1,28 @@
#pragma once
#include <Geode/ui/Popup.hpp>
#include <Geode/ui/MDTextArea.hpp>
#include "ModSource.hpp"
using namespace geode::prelude;
enum class ModMarkdownData {
Details,
Changelog,
};
std::optional<std::string> getModMarkdownData(ModSource const& src, ModMarkdownData data);
class ModPopup : public Popup<ModSource&&> {
protected:
ModSource m_source;
MDTextArea* m_mdArea;
CCMenu* m_tabsMenu;
bool setup(ModSource&& src) override;
void onMDTab(CCObject* sender);
public:
static ModPopup* create(ModSource&& src);
};

View file

@ -92,37 +92,10 @@ bool ModsLayer::init() {
{ "GJ_sTrendingIcon_001.png", "Trending", ModListSourceType::Trending },
{ "gj_folderBtn_001.png", "Mod Packs", ModListSourceType::ModPacks },
}) {
const CCSize itemSize { 100, 35 };
const CCSize iconSize { 18, 18 };
auto spr = CCNode::create();
spr->setContentSize(itemSize);
spr->setAnchorPoint({ .5f, .5f });
auto disabledBG = CCScale9Sprite::createWithSpriteFrameName("tab-bg.png"_spr);
disabledBG->setScale(.8f);
disabledBG->setContentSize(itemSize / .8f);
disabledBG->setID("disabled-bg");
disabledBG->setColor({ 26, 24, 29 });
spr->addChildAtPosition(disabledBG, Anchor::Center);
auto enabledBG = CCScale9Sprite::createWithSpriteFrameName("tab-bg.png"_spr);
enabledBG->setScale(.8f);
enabledBG->setContentSize(itemSize / .8f);
enabledBG->setID("enabled-bg");
enabledBG->setColor({ 168, 147, 185 });
spr->addChildAtPosition(enabledBG, Anchor::Center);
auto icon = CCSprite::createWithSpriteFrameName(std::get<0>(item));
limitNodeSize(icon, iconSize, 3.f, .1f);
spr->addChildAtPosition(icon, Anchor::Left, ccp(16, 0), false);
auto title = CCLabelBMFont::create(std::get<1>(item), "bigFont.fnt");
title->limitLabelWidth(spr->getContentWidth() - 34, .55f, .1f);
title->setAnchorPoint({ .0f, .5f });
spr->addChildAtPosition(title, Anchor::Left, ccp(28, 0), false);
auto btn = CCMenuItemSpriteExtra::create(spr, this, menu_selector(ModsLayer::onTab));
auto btn = CCMenuItemSpriteExtra::create(
GeodeTabSprite::create(std::get<0>(item), std::get<1>(item), 100),
this, menu_selector(ModsLayer::onTab)
);
btn->setTag(static_cast<int>(std::get<2>(item)));
mainTabs->addChild(btn);
m_tabs.push_back(btn);
@ -203,8 +176,7 @@ void ModsLayer::gotoTab(ModListSourceType type) {
// Update selected tab
for (auto tab : m_tabs) {
auto selected = tab->getTag() == static_cast<int>(type);
tab->getNormalImage()->getChildByID("disabled-bg")->setVisible(!selected);
tab->getNormalImage()->getChildByID("enabled-bg")->setVisible(selected);
static_cast<GeodeTabSprite*>(tab->getNormalImage())->select(selected);
tab->setEnabled(!selected);
}