initial work on new ui

This commit is contained in:
HJfod 2024-02-22 02:04:38 +02:00
parent 6b59217ce1
commit 8985b32fc2
27 changed files with 515 additions and 89 deletions

View file

@ -66,6 +66,7 @@ file(GLOB SOURCES CONFIGURE_DEPENDS
src/utils/*.cpp
src/ui/*.cpp
src/ui/nodes/*.cpp
src/ui/mods/*.cpp
src/ui/internal/*.cpp
src/ui/internal/info/*.cpp
src/ui/internal/list/*.cpp

View file

@ -11,6 +11,31 @@ namespace geode {
*/
GEODE_DLL cocos2d::CCSprite* createLayerBG();
enum class SideArt {
BottomLeft = 0b0001,
BottomRight = 0b0010,
TopLeft = 0b0100,
TopRight = 0b1000,
Bottom = 0b0011,
Top = 0b1100,
All = 0b1111,
};
constexpr SideArt operator|(SideArt a, SideArt b) {
return static_cast<SideArt>(static_cast<int>(a) | static_cast<int>(b));
}
constexpr bool operator&(SideArt a, SideArt b) {
return static_cast<bool>(static_cast<int>(a) & static_cast<int>(b));
}
/**
* Add side art (corner pieces) for a layer
* @param to Layer to add corner pieces to
* @param sides Which corners to populate; by default, populates all
* @param useAnchorLayout If true, `to` is given an `AnchorLayout` and the
* corners' positions are dynamically updated
*/
GEODE_DLL void addSideArt(cocos2d::CCNode* to, SideArt sides = SideArt::All, bool useAnchorLayout = false);
/**
* Add the rounded comment borders to a node
*/

View file

@ -30,23 +30,14 @@ namespace geode {
GEODE_DLL void openSettingsPopup(Mod* mod);
/**
* Create a default logo sprite
* @param size Size of the sprite
*/
GEODE_DLL cocos2d::CCNode* createDefaultLogo(
cocos2d::CCSize const& size
);
GEODE_DLL cocos2d::CCNode* createDefaultLogo();
/**
* Create a logo sprite for a mod
* @param size Size of the sprite
*/
GEODE_DLL cocos2d::CCNode* createModLogo(
Mod* mod, cocos2d::CCSize const& size
);
GEODE_DLL cocos2d::CCNode* createModLogo(Mod* mod);
/**
* Create a logo sprite for an index item
* @param size Size of the sprite
*/
GEODE_DLL cocos2d::CCNode* createIndexItemLogo(
IndexItemHandle item, cocos2d::CCSize const& size
);
GEODE_DLL cocos2d::CCNode* createIndexItemLogo(IndexItemHandle item);
}

Binary file not shown.

After

(image error) Size: 9.7 KiB

View file

@ -50,6 +50,9 @@
],
"BlankSheet": [
"blanks/*.png"
],
"SwelveSheet": [
"swelve/*.png"
]
}
},

Binary file not shown.

After

(image error) Size: 5.3 KiB

Binary file not shown.

After

(image error) Size: 623 B

Binary file not shown.

After

(image error) Size: 6.3 KiB

BIN
loader/resources/search.png Normal file

Binary file not shown.

After

(image error) Size: 17 KiB

Binary file not shown.

After

(image error) Size: 2 KiB

Binary file not shown.

After

(image error) Size: 3 KiB

Binary file not shown.

After

(image error) Size: 2.1 KiB

Binary file not shown.

After

(image error) Size: 267 B

BIN
loader/resources/tab-bg.png Normal file

Binary file not shown.

After

(image error) Size: 3.2 KiB

View file

@ -1,5 +1,4 @@
#include "../ui/internal/list/ModListLayer.hpp"
#include "../ui/mods/ModsLayer.hpp"
#include <Geode/loader/Index.hpp>
#include <Geode/modify/MenuLayer.hpp>
#include <Geode/modify/Modify.hpp>
@ -334,6 +333,6 @@ struct CustomMenuLayer : Modify<CustomMenuLayer, MenuLayer> {
}
void onGeode(CCObject*) {
ModListLayer::scene();
ModsLayer::scene();
}
};

View file

@ -66,66 +66,40 @@ void geode::openSettingsPopup(Mod* mod) {
}
}
CCNode* geode::createDefaultLogo(CCSize const& size) {
CCNode* geode::createDefaultLogo() {
CCNode* spr = CCSprite::createWithSpriteFrameName("no-logo.png"_spr);
if (!spr) {
spr = CCLabelBMFont::create("OwO", "goldFont.fnt");
}
limitNodeSize(spr, size, 1.f, .01f);
return spr;
}
CCNode* geode::createModLogo(Mod* mod, CCSize const& size) {
CCNode* spr = mod == Mod::get() ?
CCSprite::createWithSpriteFrameName("geode-logo.png"_spr) :
CCSprite::create(fmt::format("{}/logo.png", mod->getID()).c_str());
if (!spr) spr = CCSprite::createWithSpriteFrameName("no-logo.png"_spr);
if (!spr) spr = CCLabelBMFont::create("N/A", "goldFont.fnt");
limitNodeSize(spr, size, 1.f, .01f);
spr->setPosition(size/2);
spr->setAnchorPoint({.5f, .5f});
auto node = CCNode::create();
node->addChild(spr);
node->setContentSize(size);
return node;
CCNode* geode::createModLogo(Mod* mod) {
CCNode* ret = nullptr;
if (mod == Mod::get()) {
ret = CCSprite::createWithSpriteFrameName("geode-logo.png"_spr);
}
else {
ret = CCSprite::create(fmt::format("{}/logo.png", mod->getID()).c_str());
}
if (!ret) {
ret = createDefaultLogo();
}
return ret;
}
CCNode* geode::createIndexItemLogo(IndexItemHandle item, CCSize const& size) {
CCNode* geode::createIndexItemLogo(IndexItemHandle item) {
auto logoPath = ghc::filesystem::absolute(item->getRootPath() / "logo.png");
CCNode* spr = CCSprite::create(logoPath.string().c_str());
if (!spr) {
spr = CCSprite::createWithSpriteFrameName("no-logo.png"_spr);
}
if (!spr) {
spr = CCLabelBMFont::create("N/A", "goldFont.fnt");
spr = createDefaultLogo();
}
if (item->isFeatured()) {
auto glowSize = size + CCSize(4.f, 4.f);
auto logoGlow = CCSprite::createWithSpriteFrameName("logo-glow.png"_spr);
logoGlow->setScaleX(glowSize.width / logoGlow->getContentSize().width);
logoGlow->setScaleY(glowSize.height / logoGlow->getContentSize().height);
// i dont know why + 1 is needed and its too late for me to figure out why
spr->setPosition(
logoGlow->getContentSize().width / 2 + 1,
logoGlow->getContentSize().height / 2 - 1
);
// scary mathematics
spr->setScaleX(size.width / spr->getContentSize().width / logoGlow->getScaleX());
spr->setScaleY(size.height / spr->getContentSize().height / logoGlow->getScaleY());
logoGlow->addChild(spr);
spr->setScaleX(logoGlow->getContentWidth() / spr->getContentWidth());
spr->setScaleY(logoGlow->getContentHeight() / spr->getContentHeight());
logoGlow->addChildAtPosition(spr, Anchor::Center);
spr = logoGlow;
}
else {
limitNodeSize(spr, size, 1.f, .01f);
}
spr->setPosition(size/2);
spr->setAnchorPoint({.5f, .5f});
auto node = CCNode::create();
node->addChild(spr);
node->setContentSize(size);
return node;
return spr;
}

View file

@ -444,7 +444,7 @@ bool LocalModInfoPopup::init(Mod* mod, ModListLayer* list) {
}
CCNode* LocalModInfoPopup::createLogo(CCSize const& size) {
return geode::createModLogo(m_mod, size);
return geode::createModLogo(m_mod);
}
ModMetadata LocalModInfoPopup::getMetadata() const {
@ -677,7 +677,7 @@ void IndexItemInfoPopup::onInstall(CCObject*) {
}
CCNode* IndexItemInfoPopup::createLogo(CCSize const& size) {
return geode::createIndexItemLogo(m_item, size);
return geode::createIndexItemLogo(m_item);
}
ModMetadata IndexItemInfoPopup::getMetadata() const {

View file

@ -168,7 +168,7 @@ ModInstallListCell* ModInstallListCell::create(Mod* mod, InstallListPopup* list,
}
CCNode* ModInstallListCell::createLogo(CCSize const& size) {
return geode::createModLogo(m_mod, size);
return geode::createModLogo(m_mod);
}
std::string ModInstallListCell::getID() const {
return m_mod->getID();
@ -292,7 +292,7 @@ IndexItemInstallListCell* IndexItemInstallListCell::create(
}
CCNode* IndexItemInstallListCell::createLogo(CCSize const& size) {
return geode::createIndexItemLogo(m_item, size);
return geode::createIndexItemLogo(m_item);
}
std::string IndexItemInstallListCell::getID() const {
return m_item->getMetadata().getID();
@ -354,7 +354,7 @@ UnknownInstallListCell* UnknownInstallListCell::create(
}
CCNode* UnknownInstallListCell::createLogo(CCSize const& size) {
return geode::createDefaultLogo(size);
return geode::createDefaultLogo();
}
std::string UnknownInstallListCell::getID() const {
return m_dependency.id;
@ -401,7 +401,7 @@ SelectVersionCell* SelectVersionCell::create(IndexItemHandle item, SelectVersion
}
CCNode* SelectVersionCell::createLogo(CCSize const& size) {
return geode::createIndexItemLogo(m_item, size);
return geode::createIndexItemLogo(m_item);
}
std::string SelectVersionCell::getID() const {
return m_item->getMetadata().getID();

View file

@ -344,7 +344,7 @@ std::optional<ModMetadata> ModCell::getModMetadata() const {
}
CCNode* ModCell::createLogo(CCSize const& size) {
return geode::createModLogo(m_mod, size);
return geode::createModLogo(m_mod);
}
// IndexItemCell
@ -434,7 +434,7 @@ std::optional<ModMetadata> IndexItemCell::getModMetadata() const {
}
CCNode* IndexItemCell::createLogo(CCSize const& size) {
return geode::createIndexItemLogo(m_item, size);
return geode::createIndexItemLogo(m_item);
}
// InvalidGeodeFileCell

View file

@ -0,0 +1,83 @@
#include "ModItem.hpp"
#include <Geode/ui/GeodeUI.hpp>
bool BaseModItem::init() {
if (!CCNode::init())
return false;
return true;
}
void BaseModItem::setupCommonInfo() {
auto meta = this->getMetadata();
m_logo = this->createModLogo();
this->addChild(m_logo);
m_title = CCLabelBMFont::create(meta.getName().c_str(), "bigFont.fnt");
m_title->setAnchorPoint({ .0f, .5f });
this->addChild(m_title);
auto by = "By " + ModMetadata::formatDeveloperDisplayString(meta.getDevelopers());
auto developersBtn = CCMenuItemSpriteExtra::create(
CCLabelBMFont::create(by.c_str(), "goldFont.fnt"),
this, nullptr
);
m_developers = CCMenu::create();
m_developers->ignoreAnchorPointForPosition(false);
m_developers->setContentSize(developersBtn->getScaledContentSize());
m_developers->addChildAtPosition(developersBtn, Anchor::Center);
m_developers->setAnchorPoint({ .0f, .5f });
this->addChild(m_developers);
}
void BaseModItem::updateSize(float width, bool big) {
this->setContentSize({ width, big ? 40.f : 25.f });
if (m_logo) {
auto logoSize = m_obContentSize.height - 5;
limitNodeSize(m_logo, { logoSize, logoSize }, 999, .1f);
m_logo->setPosition(m_obContentSize.height / 2 + 5, m_obContentSize.height / 2);
}
CCSize titleSpace {
m_obContentSize.width / 2 - m_obContentSize.height,
m_obContentSize.height / 2
};
if (m_title) {
m_title->setPosition(m_obContentSize.height + 10, m_obContentSize.height * .7f);
limitNodeSize(m_title, titleSpace, 1.f, .1f);
}
if (m_developers) {
m_developers->setPosition(m_obContentSize.height + 10, m_obContentSize.height * .3f);
limitNodeSize(m_developers, titleSpace, .6f, .1f);
}
}
bool InstalledModItem::init(Mod* mod) {
if (!BaseModItem::init())
return false;
m_mod = mod;
this->setupCommonInfo();
return true;
}
InstalledModItem* InstalledModItem::create(Mod* mod) {
auto ret = new InstalledModItem();
if (ret && ret->init(mod)) {
ret->autorelease();
return ret;
}
CC_SAFE_DELETE(ret);
return nullptr;
}
ModMetadata InstalledModItem::getMetadata() const {
return m_mod->getMetadata();
}
CCNode* InstalledModItem::createModLogo() const {
return geode::createModLogo(m_mod);
}

View file

@ -0,0 +1,35 @@
#pragma once
#include <Geode/ui/General.hpp>
using namespace geode::prelude;
class BaseModItem : public CCNode {
protected:
CCNode* m_logo = nullptr;
CCNode* m_title = nullptr;
CCNode* m_developers = nullptr;
bool init();
void setupCommonInfo();
public:
virtual ModMetadata getMetadata() const = 0;
virtual CCNode* createModLogo() const = 0;
virtual void updateSize(float width, bool big);
};
class InstalledModItem : public BaseModItem {
protected:
Mod* m_mod;
bool init(Mod* mod);
public:
static InstalledModItem* create(Mod* mod);
ModMetadata getMetadata() const override;
CCNode* createModLogo() const override;
};

View file

@ -0,0 +1,193 @@
#include "ModsLayer.hpp"
#include "SwelvyBG.hpp"
static bool BIG_VIEW = false;
bool ModsLayer::init() {
if (!CCLayer::init())
return false;
auto winSize = CCDirector::get()->getWinSize();
this->addChild(SwelvyBG::create());
auto backMenu = CCMenu::create();
backMenu->setContentWidth(100.f);
backMenu->setAnchorPoint({ .0f, .5f });
auto backSpr = CCSprite::createWithSpriteFrameName("GJ_arrow_03_001.png");
auto backBtn = CCMenuItemSpriteExtra::create(
backSpr, this, menu_selector(ModsLayer::onBack)
);
backMenu->addChild(backBtn);
backMenu->setLayout(
RowLayout::create()
->setAxisAlignment(AxisAlignment::Start)
);
this->addChildAtPosition(backMenu, Anchor::TopLeft, ccp(12, -25), false);
auto frame = CCNode::create();
frame->setAnchorPoint({ .5f, .5f });
frame->setContentSize({ 380, 205 });
auto frameBG = CCLayerColor::create({ 25, 17, 37, 255 });
frameBG->setContentSize(frame->getContentSize());
frameBG->ignoreAnchorPointForPosition(false);
frame->addChildAtPosition(frameBG, Anchor::Center);
auto tabsTop = CCSprite::createWithSpriteFrameName("mods-list-top.png"_spr);
tabsTop->setAnchorPoint({ .5f, .0f });
frame->addChildAtPosition(tabsTop, Anchor::Top, ccp(0, -2));
auto tabsLeft = CCSprite::createWithSpriteFrameName("mods-list-side.png"_spr);
tabsLeft->setScaleY(frame->getContentHeight() / tabsLeft->getContentHeight());
frame->addChildAtPosition(tabsLeft, Anchor::Left, ccp(6, 0));
auto tabsRight = CCSprite::createWithSpriteFrameName("mods-list-side.png"_spr);
tabsRight->setFlipX(true);
tabsRight->setScaleY(frame->getContentHeight() / tabsRight->getContentHeight());
frame->addChildAtPosition(tabsRight, Anchor::Right, ccp(-6, 0));
auto tabsBottom = CCSprite::createWithSpriteFrameName("mods-list-bottom.png"_spr);
tabsBottom->setAnchorPoint({ .5f, 1.f });
frame->addChildAtPosition(tabsBottom, Anchor::Bottom, ccp(0, 2));
this->addChildAtPosition(frame, Anchor::Center, ccp(0, -10), false);
m_list = ScrollLayer::create(frame->getContentSize() - ccp(24, 0));
m_list->m_contentLayer->setLayout(
ColumnLayout::create()
->setAxisReverse(true)
->setAxisAlignment(AxisAlignment::End)
->setAutoGrowAxis(frame->getContentHeight())
);
this->addChildAtPosition(m_list, Anchor::Center, -m_list->getScaledContentSize() / 2 - ccp(0, 10), false);
auto mainTabs = CCMenu::create();
mainTabs->setContentWidth(tabsTop->getContentWidth() - 45);
mainTabs->setAnchorPoint({ .5f, .0f });
mainTabs->setPosition(frame->convertToWorldSpace(tabsTop->getPosition() + ccp(0, 10)));
for (auto item : std::initializer_list<std::tuple<const char*, const char*, const char*>> {
{ "download.png"_spr, "Installed", "installed" },
{ "GJ_bigStar_noShadow_001.png", "Featured", "featured" },
{ "GJ_sTrendingIcon_001.png", "Trending", "trending" },
{ "gj_folderBtn_001.png", "Mod Packs", "mod-packs" },
{ "search.png"_spr, "Search", "search" },
}) {
const CCSize itemSize { 100, 40 };
const CCSize iconSize { 20, 20 };
auto spr = CCNode::create();
spr->setContentSize(itemSize);
spr->setAnchorPoint({ .5f, .5f });
auto disabledBG = CCScale9Sprite::createWithSpriteFrameName("tab-bg.png"_spr);
disabledBG->setContentSize(itemSize);
disabledBG->setID("disabled-bg");
disabledBG->setColor({ 26, 24, 29 });
spr->addChildAtPosition(disabledBG, Anchor::Center);
auto enabledBG = CCScale9Sprite::createWithSpriteFrameName("tab-bg.png"_spr);
enabledBG->setContentSize(itemSize);
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(iconSize.width / 2 + 5, 0), false);
auto title = CCLabelBMFont::create(std::get<1>(item), "bigFont.fnt");
title->limitLabelWidth(spr->getContentWidth() - iconSize.width - 15, .55f, .1f);
title->setAnchorPoint({ .0f, .5f });
spr->addChildAtPosition(title, Anchor::Left, ccp((iconSize.width + 10), 0), false);
auto btn = CCMenuItemSpriteExtra::create(spr, this, menu_selector(ModsLayer::onTab));
btn->setID(std::get<2>(item));
mainTabs->addChild(btn);
m_tabs.push_back(btn);
}
mainTabs->setLayout(RowLayout::create());
this->addChild(mainTabs);
this->gotoTab("installed");
this->setKeypadEnabled(true);
cocos::handleTouchPriority(this, true);
return true;
}
void ModsLayer::loadList(std::string const& id, bool update) {
if (m_currentList) {
m_currentList->scrollPosition = m_list->m_contentLayer->getPositionY();
}
m_list->m_contentLayer->removeAllChildren();
if (!m_listItemsCache.contains(id) || update) {
ListCache cache;
switch (hash(id.c_str())) {
case hash("installed"): {
for (auto mod : Loader::get()->getAllMods()) {
cache.items.push_back(InstalledModItem::create(mod));
}
} break;
}
cache.scrollPosition = std::numeric_limits<float>::max();
m_listItemsCache[id] = std::move(cache);
}
auto& cache = m_listItemsCache.at(id);
for (auto item : cache.items) {
m_list->m_contentLayer->addChild(item);
item->updateSize(m_list->getContentWidth(), BIG_VIEW);
}
m_list->m_contentLayer->updateLayout();
auto listTopScrollPos = -m_list->m_contentLayer->getContentHeight() + m_list->getContentHeight();
if (cache.scrollPosition > 0.f || cache.scrollPosition < listTopScrollPos) {
cache.scrollPosition = listTopScrollPos;
}
m_list->m_contentLayer->setPositionY(cache.scrollPosition);
m_currentList = &cache;
}
void ModsLayer::gotoTab(std::string const& id) {
for (auto tab : m_tabs) {
auto selected = tab->getID() == id;
tab->getNormalImage()->getChildByID("disabled-bg")->setVisible(!selected);
tab->getNormalImage()->getChildByID("enabled-bg")->setVisible(selected);
tab->setEnabled(!selected);
}
this->loadList(id);
}
void ModsLayer::onTab(CCObject* sender) {
this->gotoTab(static_cast<CCNode*>(sender)->getID());
}
void ModsLayer::keyBackClicked() {
this->onBack(nullptr);
}
void ModsLayer::onBack(CCObject*) {
CCDirector::get()->replaceScene(CCTransitionFade::create(.5f, MenuLayer::scene(false)));
}
ModsLayer* ModsLayer::create() {
auto ret = new ModsLayer();
if (ret && ret->init()) {
ret->autorelease();
return ret;
}
CC_SAFE_DELETE(ret);
return nullptr;
}
ModsLayer* ModsLayer::scene() {
auto scene = CCScene::create();
auto layer = ModsLayer::create();
scene->addChild(layer);
CCDirector::sharedDirector()->replaceScene(CCTransitionFade::create(.5f, scene));
return layer;
}

View file

@ -0,0 +1,33 @@
#pragma once
#include <Geode/ui/General.hpp>
#include <Geode/ui/ScrollLayer.hpp>
#include "ModItem.hpp"
using namespace geode::prelude;
struct ListCache {
std::vector<Ref<BaseModItem>> items;
float scrollPosition;
};
class ModsLayer : public CCLayer {
protected:
std::vector<CCMenuItemSpriteExtra*> m_tabs;
ScrollLayer* m_list;
ListCache* m_currentList = nullptr;
std::unordered_map<std::string, ListCache> m_listItemsCache;
bool init();
void keyBackClicked() override;
void onTab(CCObject* sender);
void gotoTab(std::string const& id);
void loadList(std::string const& id, bool update = false);
public:
static ModsLayer* create();
static ModsLayer* scene();
void onBack(CCObject*);
};

View file

@ -0,0 +1,67 @@
#include "SwelvyBG.hpp"
#include <random>
bool SwelvyBG::init() {
if (!CCSpriteBatchNode::initWithTexture(CCTextureCache::get()->textureForKey("SwelveSheet.png"_spr), 20))
return false;
auto winSize = CCDirector::get()->getWinSize();
this->setContentSize(winSize);
this->setAnchorPoint({ 0.f, 0.f });
std::random_device rd;
std::mt19937 gen(rd());
std::uniform_int_distribution<> sign(0, 1);
std::uniform_real_distribution<float> dis(.05f, .15f);
float y = m_obContentSize.height + 5;
for (auto layer : std::initializer_list<std::pair<ccColor3B, const char*>> {
{ ccc3(244, 212, 142), "layer3.png"_spr },
{ ccc3(245, 174, 125), "layer0.png"_spr },
{ ccc3(236, 137, 124), "layer1.png"_spr },
{ ccc3(213, 105, 133), "layer2.png"_spr },
{ ccc3(173, 84, 146), "layer1.png"_spr },
{ ccc3(113, 74, 154), "layer0.png"_spr },
}) {
float speed = dis(gen);
if (sign(gen) == 0) {
speed = -speed;
}
auto frame = CCSpriteFrameCache::get()->spriteFrameByName(layer.second);
auto repeatCount = static_cast<int>(floor(winSize.width / frame->getRect().size.width)) + 2;
for (int i = 0; i < repeatCount; i += 1) {
auto sprite = CCSprite::createWithSpriteFrame(frame);
sprite->setColor(layer.first);
sprite->setAnchorPoint({ (speed < 0 ? 0.f : 1.f), 1 });
sprite->setPosition({ (i + 1) * (sprite->getContentWidth() - 1), y });
sprite->schedule(schedule_selector(SwelvyBG::updateSpritePosition));
sprite->setUserData(std::bit_cast<void*>(speed));
sprite->setTag(repeatCount);
this->addChild(sprite);
}
y -= m_obContentSize.height / 6;
}
return true;
}
void SwelvyBG::updateSpritePosition(float dt) {
auto speed = std::bit_cast<float>(this->getUserData());
this->setPositionX(this->getPositionX() - speed);
if (speed > 0 && this->getPositionX() < 0.f) {
this->setPositionX(this->getPositionX() + (this->getContentWidth() - 1) * this->getTag());
}
else if (speed < 0 && this->getPositionX() > this->getParent()->getContentWidth()) {
this->setPositionX(this->getPositionX() - (this->getContentWidth() - 1) * this->getTag());
}
}
SwelvyBG* SwelvyBG::create() {
auto ret = new SwelvyBG();
if (ret && ret->init()) {
ret->autorelease();
return ret;
}
CC_SAFE_DELETE(ret);
return nullptr;
}

View file

@ -0,0 +1,15 @@
#pragma once
#include <Geode/ui/General.hpp>
using namespace geode::prelude;
class SwelvyBG : public CCSpriteBatchNode {
protected:
bool init();
void updateSpritePosition(float dt);
public:
static SwelvyBG* create();
};

View file

@ -18,6 +18,29 @@ CCSprite* geode::createLayerBG() {
return bg;
}
void geode::addSideArt(CCNode* to, SideArt sides, bool useAnchorLayout) {
if (sides & SideArt::BottomLeft) {
auto spr = CCSprite::createWithSpriteFrameName("GJ_sideArt_001.png");
to->addChildAtPosition(spr, Anchor::BottomLeft, ccp(35, 35), useAnchorLayout);
}
if (sides & SideArt::BottomRight) {
auto spr = CCSprite::createWithSpriteFrameName("GJ_sideArt_001.png");
spr->setFlipX(true);
to->addChildAtPosition(spr, Anchor::BottomRight, ccp(-35, 35), useAnchorLayout);
}
if (sides & SideArt::TopLeft) {
auto spr = CCSprite::createWithSpriteFrameName("GJ_sideArt_001.png");
spr->setFlipY(true);
to->addChildAtPosition(spr, Anchor::TopLeft, ccp(35, -35), useAnchorLayout);
}
if (sides & SideArt::TopRight) {
auto spr = CCSprite::createWithSpriteFrameName("GJ_sideArt_001.png");
spr->setFlipX(true);
spr->setFlipY(true);
to->addChildAtPosition(spr, Anchor::TopRight, ccp(-35, -35), useAnchorLayout);
}
}
void geode::addListBorders(CCNode* to, CCPoint const& center, CCSize const& size) {
// if the size is 346.f, the top aligns perfectly by default :3
if (size.width == 346.f) {

View file

@ -418,32 +418,16 @@ CCRect geode::cocos::calculateChildCoverage(CCNode* parent) {
return calculateNodeCoverage(parent->getChildren());
}
void geode::cocos::limitNodeSize(cocos2d::CCNode* spr, cocos2d::CCSize const& size, float def, float min) {
spr->setScale(1.f);
auto [cwidth, cheight] = spr->getContentSize();
float scale = def;
if (size.height && size.height < cheight) {
scale = size.height / cheight;
}
if (size.width && size.width < cwidth) {
if (size.width / cwidth < scale) scale = size.width / cwidth;
}
if (def && def < scale) {
scale = def;
}
if (min && scale < min) {
scale = min;
}
spr->setScale(scale);
void geode::cocos::limitNodeSize(CCNode* spr, CCSize const& size, float def, float min) {
spr->setScale(clamp(std::min(size.height / spr->getContentHeight(), size.width / spr->getContentWidth()), min, def));
}
bool geode::cocos::nodeIsVisible(cocos2d::CCNode* node) {
bool geode::cocos::nodeIsVisible(CCNode* node) {
if (!node->isVisible()) {
return false;
}
if (node->getParent()) {
return nodeIsVisible(node->getParent());
if (auto parent = node->getParent()) {
return nodeIsVisible(parent);
}
return true;
}