View buttons!

This commit is contained in:
HJfod 2024-02-22 17:28:09 +02:00
parent 1f6335ce17
commit e452f482a8
19 changed files with 168 additions and 29 deletions

View file

@ -1013,6 +1013,48 @@ public:
* @note Geode addition
*/
GEODE_DLL void addChildAtPosition(CCNode* child, Anchor anchor, CCPoint const& offset = CCPointZero, bool useAnchorLayout = true);
/**
* Adds a child at an anchored position with an offset. The node is placed
* in its parent where the anchor specifies, and then the offset is used to
* relatively adjust the node's position
* @param child The child to add
* @param anchor Where the place the child relative to this node
* @param offset Where to place the child relative to the anchor
* @param nodeAnchor The child's anchor position
* @param useAnchorLayout If true, sets this node's layout to `AnchorLayout`
* if no other layout is already specified
* @note Geode addition
*/
GEODE_DLL void addChildAtPosition(
CCNode* child,
Anchor anchor,
CCPoint const& nodeAnchor,
CCPoint const& offset,
bool useAnchorLayout = true
);
/**
* Updates the anchored position of a child. Requires the child to already
* have a parent; if the child already has AnchorLayoutOptions set, those
* are updated, otherwise nothing is done
* @param anchor Where the place the child relative to its parent
* @param offset Where to place the child relative to the anchor
* @note Geode addition
*/
GEODE_DLL void updateAnchoredPosition(Anchor anchor, CCPoint const& offset = CCPointZero);
/**
* Updates the anchored position of a child. Requires the child to already
* have a parent; if the child already has AnchorLayoutOptions set, those
* are updated, otherwise nothing is done
* @param anchor Where the place the child relative to its parent
* @param offset Where to place the child relative to the anchor
* @param nodeAnchor The child's anchor position
* @note Geode addition
*/
GEODE_DLL void updateAnchoredPosition(
Anchor anchor,
CCPoint const& offset,
CCPoint const& nodeAnchor = { .5f, .5f }
);
/**
* Swap two children

View file

@ -28,7 +28,7 @@ namespace geode {
Gray = 2,
Blue = 3,
Cyan = 4,
Geode = 5,
DarkPurple = 5, // Geode-added color, used in Geode UIs
};
GEODE_DLL const char* baseEnumToString(CircleBaseColor);

Binary file not shown.

After

(image error) Size: 19 KiB

Binary file not shown.

After

(image error) Size: 16 KiB

Binary file not shown.

Before

(image error) Size: 43 KiB

After

(image error) Size: 23 KiB

Binary file not shown.

After

(image error) Size: 26 KiB

Binary file not shown.

After

(image error) Size: 15 KiB

Binary file not shown.

After

(image error) Size: 14 KiB

Binary file not shown.

After

(image error) Size: 12 KiB

Binary file not shown.

After

(image error) Size: 12 KiB

Binary file not shown.

After

(image error) Size: 7.8 KiB

Binary file not shown.

After

(image error) Size: 2.6 KiB

BIN
loader/resources/reload.png Normal file

Binary file not shown.

After

(image error) Size: 4.7 KiB

View file

@ -238,15 +238,41 @@ size_t CCNode::getEventListenerCount() {
}
void CCNode::addChildAtPosition(CCNode* child, Anchor anchor, CCPoint const& offset, bool useAnchorLayout) {
return this->addChildAtPosition(child, anchor, offset, child->getAnchorPoint(), useAnchorLayout);
}
void CCNode::addChildAtPosition(CCNode* child, Anchor anchor, CCPoint const& offset, CCPoint const& nodeAnchor, bool useAnchorLayout) {
auto layout = this->getLayout();
if (!layout && useAnchorLayout) {
this->setLayout(AnchorLayout::create());
}
// Set the position
child->setPosition(AnchorLayout::getAnchoredPosition(this, anchor, offset));
child->setAnchorPoint(nodeAnchor);
// Set dynamic positioning
if (useAnchorLayout) {
child->setLayoutOptions(AnchorLayoutOptions::create()->setAnchor(anchor)->setOffset(offset));
}
this->addChild(child);
}
void CCNode::updateAnchoredPosition(Anchor anchor, CCPoint const& offset) {
return this->updateAnchoredPosition(anchor, offset, this->getAnchorPoint());
}
void CCNode::updateAnchoredPosition(Anchor anchor, CCPoint const& offset, CCPoint const& nodeAnchor) {
// Always require a parent
if (!m_pParent) {
return;
}
// Set the position
this->setPosition(AnchorLayout::getAnchoredPosition(m_pParent, anchor, offset));
this->setAnchorPoint(nodeAnchor);
// Update dynamic positioning
if (auto opts = typeinfo_cast<AnchorLayoutOptions*>(this->getLayoutOptions())) {
opts->setAnchor(anchor);
opts->setOffset(offset);
}
}
#pragma warning(pop)

View file

@ -5,10 +5,6 @@ bool BaseModItem::init() {
if (!CCNode::init())
return false;
return true;
}
void BaseModItem::setupCommonInfo() {
auto meta = this->getMetadata();
m_logo = this->createModLogo();
@ -29,38 +25,70 @@ void BaseModItem::setupCommonInfo() {
m_developers->addChildAtPosition(developersBtn, Anchor::Center);
m_developers->setAnchorPoint({ .0f, .5f });
this->addChild(m_developers);
m_viewMenu = CCMenu::create();
m_viewMenu->setAnchorPoint({ 1.f, .5f });
m_viewMenu->setLayout(
RowLayout::create()
->setAxisReverse(true)
->setAxisAlignment(AxisAlignment::End)
);
this->addChildAtPosition(m_viewMenu, Anchor::Right, ccp(-10, 0));
this->updateState();
return true;
}
void BaseModItem::updateState() {
m_viewMenu->removeAllChildren();
if (this->wantsRestart()) {
auto restartSpr = ButtonSprite::create("Restart", "bigFont.fnt", "GE_button_02.png"_spr, .8f);
restartSpr->setScale(.5f);
auto restartBtn = CCMenuItemSpriteExtra::create(
restartSpr, this, nullptr
);
m_viewMenu->addChild(restartBtn);
}
else {
auto viewSpr = ButtonSprite::create("View", "bigFont.fnt", "GE_button_05.png"_spr, .8f);
viewSpr->setScale(.5f);
auto viewBtn = CCMenuItemSpriteExtra::create(
viewSpr, this, nullptr
);
m_viewMenu->addChild(viewBtn);
}
m_viewMenu->updateLayout();
}
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);
}
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);
}
m_title->setPosition(m_obContentSize.height + 10, m_obContentSize.height * .7f);
limitNodeSize(m_title, titleSpace, 1.f, .1f);
m_developers->setPosition(m_obContentSize.height + 10, m_obContentSize.height * .3f);
limitNodeSize(m_developers, titleSpace, .4f, .1f);
m_viewMenu->setContentWidth(m_obContentSize.width / 2 - 20);
m_viewMenu->updateLayout();
this->updateLayout();
}
bool InstalledModItem::init(Mod* mod) {
m_mod = mod;
if (!BaseModItem::init())
return false;
m_mod = mod;
this->setupCommonInfo();
return true;
}
@ -81,3 +109,7 @@ ModMetadata InstalledModItem::getMetadata() const {
CCNode* InstalledModItem::createModLogo() const {
return geode::createModLogo(m_mod);
}
bool InstalledModItem::wantsRestart() const {
return m_mod->getRequestedAction() != ModRequestedAction::None;
}

View file

@ -9,16 +9,21 @@ protected:
CCNode* m_logo = nullptr;
CCNode* m_title = nullptr;
CCNode* m_developers = nullptr;
CCMenu* m_viewMenu;
/**
* @warning Make sure `getMetadata` and `createModLogo` are callable
* before calling `init`!
*/
bool init();
void setupCommonInfo();
public:
virtual ModMetadata getMetadata() const = 0;
virtual CCNode* createModLogo() const = 0;
virtual bool wantsRestart() const = 0;
virtual void updateSize(float width, bool big);
virtual void updateState();
};
class InstalledModItem : public BaseModItem {
@ -28,8 +33,12 @@ protected:
bool init(Mod* mod);
public:
/**
* @note Make sure to call `updateSize` afterwards
*/
static InstalledModItem* create(Mod* mod);
ModMetadata getMetadata() const override;
CCNode* createModLogo() const override;
bool wantsRestart() const override;
};

View file

@ -20,13 +20,34 @@ bool ModsLayer::init() {
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 actionsMenu = CCMenu::create();
actionsMenu->setContentHeight(200.f);
actionsMenu->setAnchorPoint({ .5f, .0f });
auto reloadSpr = CircleButtonSprite::create(
CCSprite::createWithSpriteFrameName("reload.png"_spr),
CircleBaseColor::DarkPurple,
CircleBaseSize::Medium
);
reloadSpr->setScale(.8f);
auto reloadBtn = CCMenuItemSpriteExtra::create(
reloadSpr, this, menu_selector(ModsLayer::onRefreshList)
);
actionsMenu->addChild(reloadBtn);
actionsMenu->setLayout(
ColumnLayout::create()
->setAxisAlignment(AxisAlignment::Start)
);
this->addChildAtPosition(actionsMenu, Anchor::BottomLeft, ccp(35, 12), false);
auto frame = CCNode::create();
frame->setAnchorPoint({ .5f, .5f });
frame->setContentSize({ 380, 205 });
@ -97,12 +118,12 @@ bool ModsLayer::init() {
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);
spr->addChildAtPosition(icon, Anchor::Left, ccp(itemSize.height / 2, 0), false);
auto title = CCLabelBMFont::create(std::get<1>(item), "bigFont.fnt");
title->limitLabelWidth(spr->getContentWidth() - iconSize.width - 15, .55f, .1f);
title->limitLabelWidth(spr->getContentWidth() - itemSize.height - 10, .55f, .1f);
title->setAnchorPoint({ .0f, .5f });
spr->addChildAtPosition(title, Anchor::Left, ccp((iconSize.width + 10), 0), false);
spr->addChildAtPosition(title, Anchor::Left, ccp(itemSize.height, 0), false);
auto btn = CCMenuItemSpriteExtra::create(spr, this, menu_selector(ModsLayer::onTab));
btn->setID(std::get<2>(item));
@ -135,6 +156,7 @@ void ModsLayer::loadList(std::string const& id, bool update) {
}
} break;
}
cache.id = id;
cache.scrollPosition = std::numeric_limits<float>::max();
m_listItemsCache[id] = std::move(cache);
}
@ -170,6 +192,12 @@ void ModsLayer::keyBackClicked() {
this->onBack(nullptr);
}
void ModsLayer::onRefreshList(CCObject*) {
if (m_currentList) {
this->loadList(m_currentList->id, true);
}
}
void ModsLayer::onBack(CCObject*) {
CCDirector::get()->replaceScene(CCTransitionFade::create(.5f, MenuLayer::scene(false)));
}

View file

@ -7,6 +7,7 @@
using namespace geode::prelude;
struct ListCache {
std::string id;
std::vector<Ref<BaseModItem>> items;
float scrollPosition;
};
@ -30,4 +31,5 @@ public:
static ModsLayer* scene();
void onBack(CCObject*);
void onRefreshList(CCObject*);
};

View file

@ -25,7 +25,7 @@ const char* geode::baseEnumToString(CircleBaseColor value) {
case CircleBaseColor::Gray: return "Gray";
case CircleBaseColor::Blue: return "Blue";
case CircleBaseColor::Cyan: return "Cyan";
case CircleBaseColor::Geode: return "Geode";
case CircleBaseColor::DarkPurple: return "DarkPurple";
}
return "Unknown";
}