diff --git a/loader/include/Geode/cocos/base_nodes/CCNode.h b/loader/include/Geode/cocos/base_nodes/CCNode.h index 62b3704c..212e9f84 100644 --- a/loader/include/Geode/cocos/base_nodes/CCNode.h +++ b/loader/include/Geode/cocos/base_nodes/CCNode.h @@ -995,14 +995,11 @@ public: */ GEODE_DLL LayoutOptions* getLayoutOptions(); /** - * Set the position of this node relative to its parent. **This requires - * the parent node to have AnchorLayout set as its layout** - this function - * will set it if the parent has no layout enabled, but if the parent has - * something else, this function does nothing. - * @param anchor The position of this node relative to its parent - * @param offset Offset from the anchored position + * Adds a child at an anchored position + * Overrides the current layout to AnchorLayout! + * @note Geode addition */ - GEODE_DLL void setAnchoredPosition(Anchor anchor, CCPoint const& offset = CCPointZero); + GEODE_DLL void addChildAtPosition(CCNode* child, Anchor anchor, CCPoint const& offset = CCPointZero); /** * Swap two children diff --git a/loader/include/Geode/cocos/base_nodes/Layout.hpp b/loader/include/Geode/cocos/base_nodes/Layout.hpp index f3223077..19846993 100644 --- a/loader/include/Geode/cocos/base_nodes/Layout.hpp +++ b/loader/include/Geode/cocos/base_nodes/Layout.hpp @@ -410,6 +410,23 @@ public: void apply(CCNode* on) override; CCSize getSizeHint(CCNode* on) const override; + + static CCPoint getAnchoredPosition(CCNode* in, Anchor anchor, CCPoint const& offset); +}; + +class AutoSizeLayout : public cocos2d::AnchorLayout { +protected: + cocos2d::CCArray* m_targets; + +public: + static AutoSizeLayout* create(); + virtual ~AutoSizeLayout(); + + AutoSizeLayout* add(cocos2d::CCNode* target); + AutoSizeLayout* remove(cocos2d::CCNode* target); + + void apply(cocos2d::CCNode* in) override; + cocos2d::CCSize getSizeHint(cocos2d::CCNode* in) const override; }; #pragma warning(pop) diff --git a/loader/include/Geode/ui/Popup.hpp b/loader/include/Geode/ui/Popup.hpp index 1229b321..f59f0835 100644 --- a/loader/include/Geode/ui/Popup.hpp +++ b/loader/include/Geode/ui/Popup.hpp @@ -13,15 +13,19 @@ namespace geode { cocos2d::extension::CCScale9Sprite* m_bgSprite; cocos2d::CCLabelBMFont* m_title = nullptr; CCMenuItemSpriteExtra* m_closeBtn; + bool m_dynamic; ~Popup() override { cocos2d::CCTouchDispatcher::get()->unregisterForcePrio(this); } - bool init( - float width, float height, InitArgs... args, char const* bg = "GJ_square01.png", - cocos2d::CCRect bgRect = { 0, 0, 80, 80 } + private: + bool initBase( + float width, float height, InitArgs... args, char const* bg, + cocos2d::CCRect bgRect, bool dynamic ) { + m_dynamic = dynamic; + auto winSize = cocos2d::CCDirector::sharedDirector()->getWinSize(); m_size = cocos2d::CCSize { width, height }; @@ -38,6 +42,17 @@ namespace geode { m_buttonMenu->setZOrder(100); m_mainLayer->addChild(m_buttonMenu); + if (dynamic) { + m_mainLayer->ignoreAnchorPointForPosition(false); + m_mainLayer->setPosition(winSize / 2); + m_mainLayer->setContentSize(m_size); + m_mainLayer->setLayout( + cocos2d::AutoSizeLayout::create() + ->add(m_buttonMenu) + ->add(m_bgSprite) + ); + } + this->setTouchEnabled(true); auto closeSpr = cocos2d::CCSprite::createWithSpriteFrameName("GJ_closeBtn_001.png"); @@ -46,8 +61,13 @@ namespace geode { m_closeBtn = CCMenuItemSpriteExtra::create( closeSpr, this, (cocos2d::SEL_MenuHandler)(&Popup::onClose) ); - m_closeBtn->setAnchoredPosition(cocos2d::Anchor::TopLeft); - m_buttonMenu->addChild(m_closeBtn); + if (dynamic) { + m_buttonMenu->addChildAtPosition(m_closeBtn, cocos2d::Anchor::TopLeft, { 3.f, -3.f }); + } + else { + m_closeBtn->setPosition(-m_size.width / 2 + 3.f, m_size.height / 2 - 3.f); + m_buttonMenu->addChild(m_closeBtn); + } if (!setup(std::forward(args)...)) { return false; @@ -63,6 +83,22 @@ namespace geode { return true; } + protected: + [[deprecated("Use Popup::initDynamic instead, as it has more reasonable menu and layer content sizes")]] + bool init( + float width, float height, InitArgs... args, char const* bg = "GJ_square01.png", + cocos2d::CCRect bgRect = { 0, 0, 80, 80 } + ) { + return this->initBase(width, height, std::forward(args)..., bg, bgRect, false); + } + + bool initDynamic( + float width, float height, InitArgs... args, char const* bg = "GJ_square01.png", + cocos2d::CCRect bgRect = { 0, 0, 80, 80 } + ) { + return this->initBase(width, height, std::forward(args)..., bg, bgRect, true); + } + virtual bool setup(InitArgs... args) = 0; void keyDown(cocos2d::enumKeyCodes key) { @@ -84,11 +120,17 @@ namespace geode { ) { if (m_title) { m_title->setString(title.c_str()); - } else { - auto winSize = cocos2d::CCDirector::sharedDirector()->getWinSize(); + } + else { m_title = cocos2d::CCLabelBMFont::create(title.c_str(), font); - m_title->setAnchoredPosition(cocos2d::Anchor::Top, ccp(0, -offset)); - m_mainLayer->addChild(m_title, 2); + m_title->setZOrder(2); + if (m_dynamic) { + m_mainLayer->addChildAtPosition(m_title, cocos2d::Anchor::Top, ccp(0, -offset)); + } + else { + auto winSize = cocos2d::CCDirector::get()->getWinSize(); + m_title->setPosition(winSize / 2 + ccp(0, m_size.height / 2 - offset)); + } } m_title->limitLabelWidth(m_size.width - 20.f, scale, .1f); } diff --git a/loader/src/cocos2d-ext/AnchorLayout.cpp b/loader/src/cocos2d-ext/AnchorLayout.cpp index 2ae52069..ddb953e7 100644 --- a/loader/src/cocos2d-ext/AnchorLayout.cpp +++ b/loader/src/cocos2d-ext/AnchorLayout.cpp @@ -38,7 +38,7 @@ AnchorLayout* AnchorLayout::create() { void AnchorLayout::apply(CCNode* on) { on->ignoreAnchorPointForPosition(false); for (auto node : CCArrayExt(this->getNodesToPosition(on))) { - if (auto opts = typeinfo_cast(node)) { + if (auto opts = typeinfo_cast(node->getLayoutOptions())) { auto pos = opts->getOffset(); auto size = on->getContentSize(); switch (opts->getAnchor()) { @@ -60,6 +60,23 @@ void AnchorLayout::apply(CCNode* on) { } CCSize AnchorLayout::getSizeHint(CCNode* on) const { - // AnchorLayout doesn't resize its target in any way return on->getContentSize(); } + +CCPoint AnchorLayout::getAnchoredPosition(CCNode* in, Anchor anchor, CCPoint const& offset) { + auto pos = offset; + auto size = in->getContentSize(); + switch (anchor) { + default: + case Anchor::Center: pos += size / 2; break; + case Anchor::TopLeft: pos += ccp(0, size.height); break; + case Anchor::Top: pos += ccp(size.width / 2, size.height); break; + case Anchor::TopRight: pos += ccp(size.width, size.height); break; + case Anchor::Right: pos += ccp(size.width, size.height / 2); break; + case Anchor::BottomRight: pos += ccp(size.width, 0); break; + case Anchor::Bottom: pos += ccp(size.width / 2, 0); break; + case Anchor::BottomLeft: pos += ccp(0, 0); break; + case Anchor::Left: pos += ccp(0, size.height / 2); break; + } + return pos; +} diff --git a/loader/src/cocos2d-ext/AutoSizeLayout.cpp b/loader/src/cocos2d-ext/AutoSizeLayout.cpp new file mode 100644 index 00000000..ed19594c --- /dev/null +++ b/loader/src/cocos2d-ext/AutoSizeLayout.cpp @@ -0,0 +1,46 @@ +#include +#include +#include +#include +#include +#include + +using namespace geode::prelude; + +AutoSizeLayout* AutoSizeLayout::create() { + auto ret = new AutoSizeLayout(); + ret->m_targets = CCArray::create(); + ret->m_targets->retain(); + ret->autorelease(); + return ret; +} + +AutoSizeLayout::~AutoSizeLayout() { + m_targets->release(); +} + +AutoSizeLayout* AutoSizeLayout::add(CCNode* target) { + m_targets->addObject(target); + return this; +} + +AutoSizeLayout* AutoSizeLayout::remove(CCNode* target) { + m_targets->removeObject(target); + return this; +} + +void AutoSizeLayout::apply(CCNode* in) { + AnchorLayout::apply(in); + for (auto& node : CCArrayExt(m_targets)) { + // Prevent accidental infinite loop + if (node == in) continue; + node->ignoreAnchorPointForPosition(false); + node->setContentSize(in->getContentSize()); + node->setPosition(in->getContentSize() / 2); + node->updateLayout(); + } +} + +CCSize AutoSizeLayout::getSizeHint(CCNode* in) const { + return in->getContentSize(); +} diff --git a/loader/src/hooks/GeodeNodeMetadata.cpp b/loader/src/hooks/GeodeNodeMetadata.cpp index 218598fd..dadd3f30 100644 --- a/loader/src/hooks/GeodeNodeMetadata.cpp +++ b/loader/src/hooks/GeodeNodeMetadata.cpp @@ -237,17 +237,16 @@ size_t CCNode::getEventListenerCount() { GeodeNodeMetadata::set(this)->m_eventListeners.size(); } -void CCNode::setAnchoredPosition(Anchor anchor, CCPoint const& offset) { - auto parent = this->getParent(); - // If this node's parent doesn't have any layout, then set it as AnchorLayout - if (parent && parent->getLayout() == nullptr) { - parent->setLayout(AnchorLayout::create()); +void CCNode::addChildAtPosition(CCNode* child, Anchor anchor, CCPoint const& offset) { + auto layout = this->getLayout(); + if (!layout) { + this->setLayout(AnchorLayout::create()); } - // Otherwise require that it already has AnchorLayout (or AnchorLayout-derived class) - else if (parent && !typeinfo_cast(parent->getLayout())) { - return; - } - this->setLayoutOptions(AnchorLayoutOptions::create()->setAnchor(anchor)->setOffset(offset)); + // Setting the layout options always (even if the parent isn't AnchorLayout) + // so if it set as AnchorLayout later it will auto-update + child->setPosition(AnchorLayout::getAnchoredPosition(this, anchor, offset)); + child->setLayoutOptions(AnchorLayoutOptions::create()->setAnchor(anchor)->setOffset(offset)); + this->addChild(child); } #pragma warning(pop) diff --git a/loader/src/ui/internal/info/ModInfoPopup.cpp b/loader/src/ui/internal/info/ModInfoPopup.cpp index 7b1da9bf..e99340af 100644 --- a/loader/src/ui/internal/info/ModInfoPopup.cpp +++ b/loader/src/ui/internal/info/ModInfoPopup.cpp @@ -37,16 +37,15 @@ bool ModInfoPopup::setup(ModMetadata const& metadata, ModListLayer* list) { constexpr float logoOffset = 10.f; auto topNode = CCNode::create(); - topNode->setContentSize({350.f, 80.f}); + topNode->setAnchorPoint({ .5f, .5f }); + topNode->setContentSize({ 350.f, 80.f }); topNode->setLayout( RowLayout::create() ->setAxisAlignment(AxisAlignment::Center) ->setAutoScale(false) ->setCrossAxisOverflow(true) ); - m_mainLayer->addChild(topNode); - topNode->setAnchorPoint({.5f, .5f}); - topNode->setPosition(winSize.width / 2, winSize.height / 2 + 115.f); + m_mainLayer->addChildAtPosition(topNode, Anchor::Top, ccp(0, -30)); auto logoSpr = this->createLogo({logoSize, logoSize}); topNode->addChild(logoSpr); @@ -88,18 +87,13 @@ bool ModInfoPopup::setup(ModMetadata const& metadata, ModListLayer* list) { (metadata.getDetails() ? metadata.getDetails().value() : "### No description provided."), { 350.f, 137.5f } ); - m_detailsArea->setPosition( - winSize.width / 2 - m_detailsArea->getScaledContentSize().width / 2, - winSize.height / 2 - m_detailsArea->getScaledContentSize().height / 2 - 20.f - ); - m_mainLayer->addChild(m_detailsArea); + m_mainLayer->addChildAtPosition(m_detailsArea, Anchor::Center, ccp(0, -20)); m_scrollbar = Scrollbar::create(m_detailsArea->getScrollLayer()); - m_scrollbar->setPosition( - winSize.width / 2 + m_detailsArea->getScaledContentSize().width / 2 + 20.f, - winSize.height / 2 - 20.f + m_mainLayer->addChildAtPosition( + m_scrollbar, Anchor::Center, + ccp(m_detailsArea->getScaledContentSize().width / 2 + 20.f, -20) ); - m_mainLayer->addChild(m_scrollbar); // changelog if (metadata.getChangelog()) { @@ -127,10 +121,10 @@ bool ModInfoPopup::setup(ModMetadata const& metadata, ModListLayer* list) { changelogBtnOnSpr->setScale(.65f); auto changelogBtn = CCMenuItemToggler::create( - changelogBtnOffSpr, changelogBtnOnSpr, this, menu_selector(ModInfoPopup::onChangelog) + changelogBtnOffSpr, changelogBtnOnSpr, + this, menu_selector(ModInfoPopup::onChangelog) ); - changelogBtn->setPosition(-LAYER_SIZE.width / 2 + 21.5f, .0f); - m_buttonMenu->addChild(changelogBtn); + m_buttonMenu->addChildAtPosition(changelogBtn, Anchor::Left, ccp(21.5f, 0)); } // mod metadata @@ -138,8 +132,7 @@ bool ModInfoPopup::setup(ModMetadata const& metadata, ModListLayer* list) { infoSpr->setScale(.85f); m_infoBtn = CCMenuItemSpriteExtra::create(infoSpr, this, menu_selector(ModInfoPopup::onInfo)); - m_infoBtn->setPosition(LAYER_SIZE.width / 2 - 25.f, LAYER_SIZE.height / 2 - 25.f); - m_buttonMenu->addChild(m_infoBtn); + m_buttonMenu->addChildAtPosition(m_infoBtn, Anchor::TopRight, ccp(-25, -25)); // repo button if (metadata.getRepository()) { @@ -148,8 +141,7 @@ bool ModInfoPopup::setup(ModMetadata const& metadata, ModListLayer* list) { this, menu_selector(ModInfoPopup::onRepository) ); - repoBtn->setPosition(LAYER_SIZE.width / 2 - 25.f, -LAYER_SIZE.height / 2 + 25.f); - m_buttonMenu->addChild(repoBtn); + m_buttonMenu->addChildAtPosition(repoBtn, Anchor::BottomRight, ccp(-25, 25)); } // support button @@ -159,8 +151,7 @@ bool ModInfoPopup::setup(ModMetadata const& metadata, ModListLayer* list) { this, menu_selector(ModInfoPopup::onSupport) ); - supportBtn->setPosition(LAYER_SIZE.width / 2 - 60.f, -LAYER_SIZE.height / 2 + 25.f); - m_buttonMenu->addChild(supportBtn); + m_buttonMenu->addChildAtPosition(supportBtn, Anchor::BottomRight, ccp(-60, 25)); } return true; @@ -204,40 +195,12 @@ void ModInfoPopup::onInfo(CCObject*) { } void ModInfoPopup::onChangelog(CCObject* sender) { - auto winSize = CCDirector::get()->getWinSize(); - - if (!m_changelogArea) { - m_changelogArea = MDTextArea::create(this->getMetadata().getChangelog().value(), { 350.f, 137.5f }); - m_changelogArea->setPosition( - -5000.f, winSize.height / 2 - m_changelogArea->getScaledContentSize().height / 2 - 20.f - ); - m_changelogArea->setVisible(false); - m_mainLayer->addChild(m_changelogArea); - } - auto toggle = static_cast(sender); - - m_detailsArea->setVisible(toggle->isToggled()); - // as it turns out, cocos2d is stupid and still passes touch - // events to invisible nodes - m_detailsArea->setPositionX( - toggle->isToggled() ? winSize.width / 2 - m_detailsArea->getScaledContentSize().width / 2 : - -5000.f - ); - - m_changelogArea->setVisible(!toggle->isToggled()); - // as it turns out, cocos2d is stupid and still passes touch - // events to invisible nodes - m_changelogArea->setPositionX( - !toggle->isToggled() ? winSize.width / 2 - m_changelogArea->getScaledContentSize().width / 2 : - -5000.f - ); - - m_scrollbar->setTarget( + m_detailsArea->setString(( toggle->isToggled() ? - m_detailsArea->getScrollLayer() : - m_changelogArea->getScrollLayer() - ); + this->getMetadata().getDetails().value() : + this->getMetadata().getChangelog().value() + ).c_str()); } void ModInfoPopup::setInstallStatus(std::optional const& progress) { @@ -349,14 +312,15 @@ LocalModInfoPopup::LocalModInfoPopup() ModInstallFilter("") ) {} - bool LocalModInfoPopup::init(Mod* mod, ModListLayer* list) { m_item = Index::get()->getMajorItem(mod->getMetadata().getID()); - if (m_item) + if (m_item) { m_installListener.setFilter(m_item->getMetadata().getID()); + } + m_mod = mod; - if (!ModInfoPopup::init(LAYER_SIZE.width, LAYER_SIZE.height, mod->getMetadata(), list)) return false; + if (!ModInfoPopup::initDynamic(LAYER_SIZE.width, LAYER_SIZE.height, mod->getMetadata(), list)) return false; auto winSize = CCDirector::sharedDirector()->getWinSize(); @@ -364,10 +328,10 @@ bool LocalModInfoPopup::init(Mod* mod, ModListLayer* list) { auto settingsSpr = CCSprite::createWithSpriteFrameName("GJ_optionsBtn_001.png"); settingsSpr->setScale(.65f); - auto settingsBtn = - CCMenuItemSpriteExtra::create(settingsSpr, this, menu_selector(LocalModInfoPopup::onSettings)); - settingsBtn->setPosition(-LAYER_SIZE.width / 2 + 25.f, -LAYER_SIZE.height / 2 + 25.f); - m_buttonMenu->addChild(settingsBtn); + auto settingsBtn = CCMenuItemSpriteExtra::create( + settingsSpr, this, menu_selector(LocalModInfoPopup::onSettings) + ); + m_buttonMenu->addChildAtPosition(settingsBtn, Anchor::BottomLeft, ccp(25, 25)); // Check if a config directory for the mod exists if (ghc::filesystem::exists(mod->getConfigDir(false))) { @@ -379,8 +343,7 @@ bool LocalModInfoPopup::init(Mod* mod, ModListLayer* list) { auto configBtn = CCMenuItemSpriteExtra::create( configSpr, this, menu_selector(LocalModInfoPopup::onOpenConfigDir) ); - configBtn->setPosition(-LAYER_SIZE.width / 2 + 65.f, -LAYER_SIZE.height / 2 + 25.f); - m_buttonMenu->addChild(configBtn); + m_buttonMenu->addChildAtPosition(configBtn, Anchor::BottomLeft, ccp(65, 25)); } if (!mod->hasSettings()) { @@ -397,9 +360,8 @@ bool LocalModInfoPopup::init(Mod* mod, ModListLayer* list) { auto enableBtn = CCMenuItemToggler::create( disableBtnSpr, enableBtnSpr, this, menu_selector(LocalModInfoPopup::onEnableMod) ); - enableBtn->setPosition(-155.f, 75.f); enableBtn->toggle(!mod->shouldLoad()); - m_buttonMenu->addChild(enableBtn); + m_buttonMenu->addChildAtPosition(enableBtn, Anchor::Center, ccp(-155, 75)); if (mod->isInternal()) { enableBtn->setTarget(this, menu_selector(LocalModInfoPopup::onDisablingNotSupported)); @@ -420,8 +382,7 @@ bool LocalModInfoPopup::init(Mod* mod, ModListLayer* list) { auto uninstallBtn = CCMenuItemSpriteExtra::create( uninstallBtnSpr, this, menu_selector(LocalModInfoPopup::onUninstall) ); - uninstallBtn->setPosition(-85.f, 75.f); - m_buttonMenu->addChild(uninstallBtn); + m_buttonMenu->addChildAtPosition(uninstallBtn, Anchor::Center, ccp(-85, 75)); // todo: show update button on loader that invokes the installer if (m_item && Index::get()->isUpdateAvailable(m_item)) { @@ -434,20 +395,21 @@ bool LocalModInfoPopup::init(Mod* mod, ModListLayer* list) { m_installBtnSpr->setScale(.6f); m_installBtn = CCMenuItemSpriteExtra::create(m_installBtnSpr, this, menu_selector(LocalModInfoPopup::onUpdate)); - m_installBtn->setPosition(-8.0f, 75.f); - m_buttonMenu->addChild(m_installBtn); + m_buttonMenu->addChildAtPosition(m_installBtn, Anchor::Center, ccp(-8, 75)); m_installStatus = DownloadStatusNode::create(); - m_installStatus->setPosition(winSize.width / 2 + 105.f, winSize.height / 2 + 75.f); m_installStatus->setVisible(false); - m_mainLayer->addChild(m_installStatus); + m_mainLayer->addChildAtPosition(m_installStatus, Anchor::Center, ccp(105, 75)); auto minorIndexItem = Index::get()->getItem( mod->getMetadata().getID(), ComparableVersionInfo(mod->getMetadata().getVersion(), VersionCompare::MoreEq) ); - // TODO: use column layout here? + auto availableContainer = CCNode::create(); + availableContainer->setLayout(ColumnLayout::create()->setGap(2)); + availableContainer->setAnchorPoint({ .0f, .5f }); + availableContainer->setContentSize({ 200.f, 45.f }); if (m_item->getMetadata().getVersion().getMajor() > minorIndexItem->getMetadata().getVersion().getMajor()) { // has major update @@ -458,8 +420,7 @@ bool LocalModInfoPopup::init(Mod* mod, ModListLayer* list) { m_latestVersionLabel->setScale(.35f); m_latestVersionLabel->setAnchorPoint({.0f, .5f}); m_latestVersionLabel->setColor({94, 219, 255}); - m_latestVersionLabel->setPosition(winSize.width / 2 + 35.f, winSize.height / 2 + 75.f); - m_mainLayer->addChild(m_latestVersionLabel); + availableContainer->addChild(m_latestVersionLabel); } if (minorIndexItem->getMetadata().getVersion() > mod->getMetadata().getVersion()) { @@ -471,20 +432,11 @@ bool LocalModInfoPopup::init(Mod* mod, ModListLayer* list) { m_minorVersionLabel->setScale(.35f); m_minorVersionLabel->setAnchorPoint({.0f, .5f}); m_minorVersionLabel->setColor({94, 219, 255}); - if (m_latestVersionLabel) { - m_latestVersionLabel->setPosition( - winSize.width / 2 + 35.f, winSize.height / 2 + 81.f - ); - m_minorVersionLabel->setPosition( - winSize.width / 2 + 35.f, winSize.height / 2 + 69.f - ); - } else { - m_minorVersionLabel->setPosition( - winSize.width / 2 + 35.f, winSize.height / 2 + 75.f - ); - } - m_mainLayer->addChild(m_minorVersionLabel); + availableContainer->addChild(m_minorVersionLabel); } + + availableContainer->updateLayout(); + m_mainLayer->addChildAtPosition(availableContainer, Anchor::Center, ccp(35, 75)); } } if (mod == Mod::get()) { @@ -494,11 +446,10 @@ bool LocalModInfoPopup::init(Mod* mod, ModListLayer* list) { "chatFont.fnt" ); label->setAlignment(kCCTextAlignmentRight); - label->setAnchorPoint(ccp(1, 0)); - label->setScale(0.6f); - label->setPosition(winSize.width - 3.f, 3.f); + label->setAnchorPoint({ .0f, .5f }); + label->setScale(.5f); label->setOpacity(89); - m_mainLayer->addChild(label); + m_mainLayer->addChildAtPosition(label, Anchor::BottomRight, ccp(5, 0)); } // issue report button @@ -511,8 +462,7 @@ bool LocalModInfoPopup::init(Mod* mod, ModListLayer* list) { auto issuesBtn = CCMenuItemSpriteExtra::create( issuesBtnSpr, this, menu_selector(LocalModInfoPopup::onIssues) ); - issuesBtn->setPosition(0.f, -LAYER_SIZE.height / 2 + 25.f); - m_buttonMenu->addChild(issuesBtn); + m_buttonMenu->addChildAtPosition(issuesBtn, Anchor::Bottom, ccp(0, 25)); } return true; @@ -685,7 +635,7 @@ bool IndexItemInfoPopup::init(IndexItemHandle item, ModListLayer* list) { auto winSize = CCDirector::sharedDirector()->getWinSize(); - if (!ModInfoPopup::init(LAYER_SIZE.width, LAYER_SIZE.height, item->getMetadata(), list)) return false; + if (!ModInfoPopup::initDynamic(LAYER_SIZE.width, LAYER_SIZE.height, item->getMetadata(), list)) return false; // bruh why is this here if we are allowing for browsing already installed mods // if (item->isInstalled()) return true; @@ -701,13 +651,11 @@ bool IndexItemInfoPopup::init(IndexItemHandle item, ModListLayer* list) { m_installBtn = CCMenuItemSpriteExtra::create( m_installBtnSpr, this, menu_selector(IndexItemInfoPopup::onInstall) ); - m_installBtn->setPosition(-143.0f, 75.f); - m_buttonMenu->addChild(m_installBtn); + m_buttonMenu->addChildAtPosition(m_installBtn, Anchor::Center, ccp(-143, 75)); m_installStatus = DownloadStatusNode::create(); - m_installStatus->setPosition(winSize.width / 2 - 25.f, winSize.height / 2 + 75.f); m_installStatus->setVisible(false); - m_mainLayer->addChild(m_installStatus); + m_mainLayer->addChildAtPosition(m_installStatus, Anchor::Center, ccp(-25, 75)); return true; } diff --git a/loader/src/ui/internal/info/ModInfoPopup.hpp b/loader/src/ui/internal/info/ModInfoPopup.hpp index 52c01a6e..029ceef6 100644 --- a/loader/src/ui/internal/info/ModInfoPopup.hpp +++ b/loader/src/ui/internal/info/ModInfoPopup.hpp @@ -36,7 +36,6 @@ protected: CCLabelBMFont* m_latestVersionLabel = nullptr; CCLabelBMFont* m_minorVersionLabel = nullptr; MDTextArea* m_detailsArea; - MDTextArea* m_changelogArea = nullptr; Scrollbar* m_scrollbar; IndexItemHandle m_item; diff --git a/loader/src/ui/nodes/MDPopup.cpp b/loader/src/ui/nodes/MDPopup.cpp index 2f0929da..83f4e5b5 100644 --- a/loader/src/ui/nodes/MDPopup.cpp +++ b/loader/src/ui/nodes/MDPopup.cpp @@ -19,7 +19,7 @@ bool MDPopup::setup( m_size.height - 120.f, }; auto content = MDTextArea::create(info, contentSize); - content->setPosition(winSize / 2 - contentSize / 2); + content->setPosition(winSize / 2); m_mainLayer->addChild(content); auto btnSpr = ButtonSprite::create(btn1Text); diff --git a/loader/src/ui/nodes/MDTextArea.cpp b/loader/src/ui/nodes/MDTextArea.cpp index b650f7e3..f0dbd9c9 100644 --- a/loader/src/ui/nodes/MDTextArea.cpp +++ b/loader/src/ui/nodes/MDTextArea.cpp @@ -108,6 +108,9 @@ Result colorForIdentifier(std::string const& tag) { bool MDTextArea::init(std::string const& str, CCSize const& size) { if (!CCLayer::init()) return false; + this->ignoreAnchorPointForPosition(false); + this->setAnchorPoint({ .5f, .5f }); + m_text = str; m_size = size - CCSize { 15.f, 0.f }; this->setContentSize(m_size); @@ -726,7 +729,6 @@ void MDTextArea::updateLabel() { m_content->setPositionY(-2.5f); } - m_scrollLayer->moveToTop(); } diff --git a/loader/src/ui/nodes/Popup.cpp b/loader/src/ui/nodes/Popup.cpp index f244933e..c2c074bb 100644 --- a/loader/src/ui/nodes/Popup.cpp +++ b/loader/src/ui/nodes/Popup.cpp @@ -2,6 +2,71 @@ using namespace geode::prelude; +// static void fixChildPositions(CCNode* in, CCSize const& size) { +// auto winSize = CCDirector::get()->getWinSize(); +// auto offset = size / 2 - in->getContentSize() / 2; + +// for (auto node : CCArrayExt(in->getChildren())) { +// node->setPosition(node->getPosition() + offset); + +// if (node->isIgnoreAnchorPointForPosition()) { +// node->setPosition(node->getPosition() + node->getScaledContentSize() * node->getAnchorPoint()); +// node->ignoreAnchorPointForPosition(false); +// } + +// constexpr int LEFT = 0b0001; +// constexpr int RIGHT = 0b0010; +// constexpr int BOTTOM = 0b0100; +// constexpr int TOP = 0b1000; + +// int p = 0b0000; +// if (node->getPositionX() <= winSize.width / 2 - size.width * 0.25) { +// p |= LEFT; +// } +// else if (node->getPositionX() >= winSize.width / 2 + size.width * 0.25) { +// p |= RIGHT; +// } +// if (node->getPositionY() <= winSize.height / 2 - size.height * 0.25) { +// p |= BOTTOM; +// } +// else if (node->getPositionY() >= winSize.height / 2 + size.height * 0.25) { +// p |= TOP; +// } + +// Anchor anchor = Anchor::Center; +// switch (p) { +// case LEFT | BOTTOM: anchor = Anchor::BottomLeft; break; +// case LEFT | TOP: anchor = Anchor::TopLeft; break; +// case LEFT: anchor = Anchor::Left; break; +// case RIGHT | BOTTOM: anchor = Anchor::BottomRight; break; +// case RIGHT | TOP: anchor = Anchor::TopRight; break; +// case RIGHT: anchor = Anchor::Right; break; +// case TOP: anchor = Anchor::Top; break; +// case BOTTOM: anchor = Anchor::Bottom; break; +// } + +// auto anchorPos = AnchorLayout::getAnchoredPosition(in, anchor, ccp(0, 0)); +// node->setLayoutOptions( +// AnchorLayoutOptions::create() +// ->setAnchor(anchor) +// ->setOffset(node->getPosition() - anchorPos) +// ); +// } + +// in->ignoreAnchorPointForPosition(false); +// } + +// void geode::enableDynamicLayoutForPopup(FLAlertLayer* alert, CCNode* bg) { +// auto winSize = CCDirector::get()->getWinSize(); + +// auto size = bg->getContentSize(); + +// alert->m_mainLayer->ignoreAnchorPointForPosition(false); +// alert->m_mainLayer->setContentSize(size); +// alert->m_mainLayer->setPosition(winSize / 2); +// alert->m_mainLayer->setLayout(AutoPopupLayout::create(alert->m_buttonMenu, bg)); +// } + class QuickPopup : public FLAlertLayer, public FLAlertLayerProtocol { protected: MiniFunction m_selected;