mirror of
https://github.com/geode-sdk/geode.git
synced 2024-11-26 17:36:05 -05:00
index work!!
- add tag support for index - rename CategoryNode to TagNode - add them back to the UI + fix spacing issues related to them - deleted ModListView, now using a generic ListView with the mod cells added as children to it
This commit is contained in:
parent
e763e271bf
commit
84bdeb7beb
14 changed files with 339 additions and 408 deletions
|
@ -58,6 +58,7 @@ namespace geode {
|
|||
std::unordered_set<PlatformID> platforms;
|
||||
} download;
|
||||
bool isFeatured;
|
||||
std::unordered_set<std::string> tags;
|
||||
|
||||
/**
|
||||
* Create IndexItem from a directory
|
||||
|
|
|
@ -122,6 +122,7 @@ Result<IndexItemHandle> IndexItem::createFromDir(
|
|||
.platforms = platforms,
|
||||
},
|
||||
.isFeatured = root.has("is-featured").template get<bool>(),
|
||||
.tags = root.has("tags").template get<std::unordered_set<std::string>>()
|
||||
});
|
||||
if (checker.isError()) {
|
||||
return Err(checker.getError());
|
||||
|
|
|
@ -1,22 +0,0 @@
|
|||
#pragma once
|
||||
|
||||
#include <cocos2d.h>
|
||||
|
||||
USE_GEODE_NAMESPACE();
|
||||
|
||||
enum class CategoryNodeStyle {
|
||||
Tag,
|
||||
Dot,
|
||||
};
|
||||
|
||||
class CategoryNode : public CCNode {
|
||||
protected:
|
||||
bool init(std::string const& category, CategoryNodeStyle style);
|
||||
|
||||
public:
|
||||
static CategoryNode* create(
|
||||
std::string const& category, CategoryNodeStyle style = CategoryNodeStyle::Tag
|
||||
);
|
||||
|
||||
static ccColor3B categoryToColor(std::string const& category);
|
||||
};
|
|
@ -1,7 +1,7 @@
|
|||
#include "ModInfoPopup.hpp"
|
||||
|
||||
#include "../dev/HookListLayer.hpp"
|
||||
#include "../list/ModListView.hpp"
|
||||
#include "../list/ModListLayer.hpp"
|
||||
#include "../settings/ModSettingsPopup.hpp"
|
||||
#include "../settings/AdvancedSettingsPopup.hpp"
|
||||
#include <InternalLoader.hpp>
|
||||
|
@ -17,6 +17,7 @@
|
|||
#include <Geode/ui/BasedButton.hpp>
|
||||
#include <Geode/ui/IconButtonSprite.hpp>
|
||||
#include <Geode/ui/GeodeUI.hpp>
|
||||
#include <Geode/ui/MDPopup.hpp>
|
||||
#include <Geode/utils/casts.hpp>
|
||||
#include <Geode/utils/ranges.hpp>
|
||||
#include <Geode/utils/web.hpp>
|
||||
|
@ -30,9 +31,9 @@ static constexpr int const TAG_CONFIRM_UNINSTALL = 5;
|
|||
static constexpr int const TAG_DELETE_SAVEDATA = 6;
|
||||
static const CCSize LAYER_SIZE = { 440.f, 290.f };
|
||||
|
||||
bool ModInfoPopup::init(ModInfo const& info, ModListView* list) {
|
||||
bool ModInfoPopup::init(ModInfo const& info, ModListLayer* list) {
|
||||
m_noElasticity = true;
|
||||
m_list = list;
|
||||
m_layer = list;
|
||||
|
||||
auto winSize = CCDirector::sharedDirector()->getWinSize();
|
||||
|
||||
|
@ -274,7 +275,7 @@ void ModInfoPopup::onClose(CCObject* pSender) {
|
|||
|
||||
// LocalModInfoPopup
|
||||
|
||||
bool LocalModInfoPopup::init(Mod* mod, ModListView* list) {
|
||||
bool LocalModInfoPopup::init(Mod* mod, ModListLayer* list) {
|
||||
m_mod = mod;
|
||||
|
||||
if (!ModInfoPopup::init(mod->getModInfo(), list))
|
||||
|
@ -458,7 +459,7 @@ void LocalModInfoPopup::onEnableMod(CCObject* sender) {
|
|||
"OK"
|
||||
)
|
||||
->show();
|
||||
if (m_list) m_list->updateAllStates(nullptr);
|
||||
if (m_layer) m_layer->updateAllStates(nullptr);
|
||||
return;
|
||||
}
|
||||
if (as<CCMenuItemToggler*>(sender)->isToggled()) {
|
||||
|
@ -479,7 +480,7 @@ void LocalModInfoPopup::onEnableMod(CCObject* sender) {
|
|||
)->show();
|
||||
}
|
||||
}
|
||||
if (m_list) m_list->updateAllStates(nullptr);
|
||||
if (m_layer) m_layer->updateAllStates(nullptr);
|
||||
as<CCMenuItemToggler*>(sender)->toggle(m_mod->isEnabled());
|
||||
}
|
||||
|
||||
|
@ -530,7 +531,7 @@ void LocalModInfoPopup::FLAlert_Clicked(FLAlertLayer* layer, bool btn2) {
|
|||
)->show();
|
||||
}
|
||||
}
|
||||
if (m_list) m_list->refreshList();
|
||||
if (m_layer) m_layer->reloadList();
|
||||
this->onClose(nullptr);
|
||||
} break;
|
||||
}
|
||||
|
@ -556,7 +557,7 @@ void LocalModInfoPopup::uninstall() {
|
|||
layer->show();
|
||||
}
|
||||
|
||||
LocalModInfoPopup* LocalModInfoPopup::create(Mod* mod, ModListView* list) {
|
||||
LocalModInfoPopup* LocalModInfoPopup::create(Mod* mod, ModListLayer* list) {
|
||||
auto ret = new LocalModInfoPopup;
|
||||
if (ret && ret->init(mod, list)) {
|
||||
ret->autorelease();
|
||||
|
@ -568,7 +569,7 @@ LocalModInfoPopup* LocalModInfoPopup::create(Mod* mod, ModListView* list) {
|
|||
|
||||
// IndexItemInfoPopup
|
||||
|
||||
bool IndexItemInfoPopup::init(IndexItemHandle item, ModListView* list) {
|
||||
bool IndexItemInfoPopup::init(IndexItemHandle item, ModListLayer* list) {
|
||||
m_item = item;
|
||||
|
||||
auto winSize = CCDirector::sharedDirector()->getWinSize();
|
||||
|
@ -608,7 +609,7 @@ ModInfo IndexItemInfoPopup::getModInfo() const {
|
|||
}
|
||||
|
||||
IndexItemInfoPopup* IndexItemInfoPopup::create(
|
||||
IndexItemHandle item, ModListView* list
|
||||
IndexItemHandle item, ModListLayer* list
|
||||
) {
|
||||
auto ret = new IndexItemInfoPopup;
|
||||
if (ret && ret->init(item, list)) {
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
|
||||
USE_GEODE_NAMESPACE();
|
||||
|
||||
class ModListView;
|
||||
class ModListLayer;
|
||||
class ModObject;
|
||||
|
||||
class DownloadStatusNode : public CCNode {
|
||||
|
@ -28,7 +28,7 @@ public:
|
|||
|
||||
class ModInfoPopup : public FLAlertLayer {
|
||||
protected:
|
||||
ModListView* m_list = nullptr;
|
||||
ModListLayer* m_layer = nullptr;
|
||||
DownloadStatusNode* m_installStatus = nullptr;
|
||||
IconButtonSprite* m_installBtnSpr;
|
||||
CCMenuItemSpriteExtra* m_installBtn;
|
||||
|
@ -43,7 +43,7 @@ protected:
|
|||
void onSupport(CCObject*);
|
||||
void onInfo(CCObject*);
|
||||
|
||||
bool init(ModInfo const& info, ModListView* list);
|
||||
bool init(ModInfo const& info, ModListLayer* list);
|
||||
|
||||
void keyDown(cocos2d::enumKeyCodes) override;
|
||||
void onClose(cocos2d::CCObject*);
|
||||
|
@ -56,7 +56,7 @@ class LocalModInfoPopup : public ModInfoPopup, public FLAlertLayerProtocol {
|
|||
protected:
|
||||
Mod* m_mod;
|
||||
|
||||
bool init(Mod* mod, ModListView* list);
|
||||
bool init(Mod* mod, ModListLayer* list);
|
||||
|
||||
void onIssues(CCObject*);
|
||||
void onSettings(CCObject*);
|
||||
|
@ -74,18 +74,18 @@ protected:
|
|||
ModInfo getModInfo() const override;
|
||||
|
||||
public:
|
||||
static LocalModInfoPopup* create(Mod* mod, ModListView* list);
|
||||
static LocalModInfoPopup* create(Mod* mod, ModListLayer* list);
|
||||
};
|
||||
|
||||
class IndexItemInfoPopup : public ModInfoPopup {
|
||||
protected:
|
||||
IndexItemHandle m_item;
|
||||
|
||||
bool init(IndexItemHandle item, ModListView* list);
|
||||
bool init(IndexItemHandle item, ModListLayer* list);
|
||||
|
||||
CCNode* createLogo(CCSize const& size) override;
|
||||
ModInfo getModInfo() const override;
|
||||
|
||||
public:
|
||||
static IndexItemInfoPopup* create(IndexItemHandle item, ModListView* list);
|
||||
static IndexItemInfoPopup* create(IndexItemHandle item, ModListLayer* list);
|
||||
};
|
||||
|
|
|
@ -1,6 +1,9 @@
|
|||
#include "CategoryNode.hpp"
|
||||
#include "TagNode.hpp"
|
||||
#include <Geode/utils/general.hpp>
|
||||
#include <cocos-ext.h>
|
||||
#include <Geode/loader/Mod.hpp>
|
||||
|
||||
ccColor3B CategoryNode::categoryToColor(std::string const& category) {
|
||||
ccColor3B TagNode::categoryToColor(std::string const& category) {
|
||||
// all we need is to convert a string into some number
|
||||
// between 0 and 360 and for that number to always be the
|
||||
// same for the same string
|
||||
|
@ -17,8 +20,8 @@ ccColor3B CategoryNode::categoryToColor(std::string const& category) {
|
|||
static_cast<GLubyte>(rgb.b * 255) };
|
||||
}
|
||||
|
||||
bool CategoryNode::init(std::string const& category, CategoryNodeStyle style) {
|
||||
if (style == CategoryNodeStyle::Dot) {
|
||||
bool TagNode::init(std::string const& category, TagNodeStyle style) {
|
||||
if (style == TagNodeStyle::Dot) {
|
||||
auto dot = CCSprite::createWithSpriteFrameName("category-dot.png"_spr);
|
||||
dot->setColor(categoryToColor(category));
|
||||
dot->setPosition({ 20.f, 20.f });
|
||||
|
@ -52,8 +55,8 @@ bool CategoryNode::init(std::string const& category, CategoryNodeStyle style) {
|
|||
return true;
|
||||
}
|
||||
|
||||
CategoryNode* CategoryNode::create(std::string const& category, CategoryNodeStyle style) {
|
||||
auto ret = new CategoryNode();
|
||||
TagNode* TagNode::create(std::string const& category, TagNodeStyle style) {
|
||||
auto ret = new TagNode();
|
||||
if (ret && ret->init(category, style)) {
|
||||
ret->autorelease();
|
||||
return ret;
|
22
loader/src/ui/internal/info/TagNode.hpp
Normal file
22
loader/src/ui/internal/info/TagNode.hpp
Normal file
|
@ -0,0 +1,22 @@
|
|||
#pragma once
|
||||
|
||||
#include <cocos2d.h>
|
||||
|
||||
USE_GEODE_NAMESPACE();
|
||||
|
||||
enum class TagNodeStyle {
|
||||
Tag,
|
||||
Dot,
|
||||
};
|
||||
|
||||
class TagNode : public CCNode {
|
||||
protected:
|
||||
bool init(std::string const& category, TagNodeStyle style);
|
||||
|
||||
public:
|
||||
static TagNode* create(
|
||||
std::string const& category, TagNodeStyle style = TagNodeStyle::Tag
|
||||
);
|
||||
|
||||
static ccColor3B categoryToColor(std::string const& category);
|
||||
};
|
|
@ -1,5 +1,5 @@
|
|||
#include "ModListCell.hpp"
|
||||
#include "ModListView.hpp"
|
||||
#include "ModListLayer.hpp"
|
||||
#include "../info/ModInfoPopup.hpp"
|
||||
#include <Geode/binding/StatsCell.hpp>
|
||||
#include <Geode/binding/FLAlertLayer.hpp>
|
||||
|
@ -8,6 +8,7 @@
|
|||
#include <Geode/binding/CCMenuItemToggler.hpp>
|
||||
#include <Geode/ui/GeodeUI.hpp>
|
||||
#include <InternalLoader.hpp>
|
||||
#include "../info/TagNode.hpp"
|
||||
|
||||
template <class T>
|
||||
static bool tryOrAlert(Result<T> const& res, char const* title) {
|
||||
|
@ -17,45 +18,46 @@ static bool tryOrAlert(Result<T> const& res, char const* title) {
|
|||
return res.isOk();
|
||||
}
|
||||
|
||||
ModListCell::ModListCell(char const* name, CCSize const& size)
|
||||
: TableViewCell(name, size.width, size.height) {}
|
||||
|
||||
void ModListCell::draw() {
|
||||
reinterpret_cast<StatsCell*>(this)->StatsCell::draw();
|
||||
}
|
||||
|
||||
void ModListCell::setupInfo(ModInfo const& info, bool spaceForCategories) {
|
||||
m_mainLayer->setVisible(true);
|
||||
m_backgroundLayer->setOpacity(255);
|
||||
float ModListCell::getLogoSize() const {
|
||||
return m_height / 1.5f;
|
||||
}
|
||||
|
||||
void ModListCell::setupInfo(ModInfo const& info, bool spaceForTags) {
|
||||
m_menu = CCMenu::create();
|
||||
m_menu->setPosition(m_width - 40.f, m_height / 2);
|
||||
m_mainLayer->addChild(m_menu);
|
||||
this->addChild(m_menu);
|
||||
|
||||
auto logoSize = m_height / 1.5f;
|
||||
auto logoSize = this->getLogoSize();
|
||||
|
||||
auto logoSpr = this->createLogo({ logoSize, logoSize });
|
||||
logoSpr->setPosition({ logoSize / 2 + 12.f, m_height / 2 });
|
||||
m_mainLayer->addChild(logoSpr);
|
||||
this->addChild(logoSpr);
|
||||
|
||||
bool hasDesc =
|
||||
m_display == ModListDisplay::Expanded &&
|
||||
m_layer->getDisplay() == ModListDisplay::Expanded &&
|
||||
info.m_description.has_value();
|
||||
|
||||
auto titleLabel = CCLabelBMFont::create(info.m_name.c_str(), "bigFont.fnt");
|
||||
titleLabel->setAnchorPoint({ .0f, .5f });
|
||||
titleLabel->setPositionX(m_height / 2 + logoSize / 2 + 13.f);
|
||||
if (hasDesc && spaceForCategories) {
|
||||
if (hasDesc && spaceForTags) {
|
||||
titleLabel->setPositionY(m_height / 2 + 20.f);
|
||||
}
|
||||
else if (hasDesc || spaceForCategories) {
|
||||
else if (spaceForTags) {
|
||||
titleLabel->setPositionY(m_height / 2 + 12.f);
|
||||
}
|
||||
else if (hasDesc) {
|
||||
titleLabel->setPositionY(m_height / 2 + 15.f);
|
||||
}
|
||||
else {
|
||||
titleLabel->setPositionY(m_height / 2 + 7.f);
|
||||
}
|
||||
titleLabel->limitLabelWidth(m_width / 2 - 40.f, .5f, .1f);
|
||||
m_mainLayer->addChild(titleLabel);
|
||||
this->addChild(titleLabel);
|
||||
|
||||
auto versionLabel = CCLabelBMFont::create(info.m_version.toString().c_str(), "bigFont.fnt");
|
||||
versionLabel->setAnchorPoint({ .0f, .5f });
|
||||
|
@ -65,23 +67,23 @@ void ModListCell::setupInfo(ModInfo const& info, bool spaceForCategories) {
|
|||
titleLabel->getPositionY() - 1.f
|
||||
);
|
||||
versionLabel->setColor({ 0, 255, 0 });
|
||||
m_mainLayer->addChild(versionLabel);
|
||||
this->addChild(versionLabel);
|
||||
|
||||
auto creatorStr = "by " + info.m_developer;
|
||||
auto creatorLabel = CCLabelBMFont::create(creatorStr.c_str(), "goldFont.fnt");
|
||||
creatorLabel->setAnchorPoint({ .0f, .5f });
|
||||
creatorLabel->setScale(.43f);
|
||||
creatorLabel->setPositionX(m_height / 2 + logoSize / 2 + 13.f);
|
||||
if (hasDesc && spaceForCategories) {
|
||||
if (hasDesc && spaceForTags) {
|
||||
creatorLabel->setPositionY(m_height / 2 + 7.5f);
|
||||
}
|
||||
else if (hasDesc || spaceForCategories) {
|
||||
else if (hasDesc || spaceForTags) {
|
||||
creatorLabel->setPositionY(m_height / 2);
|
||||
}
|
||||
else {
|
||||
creatorLabel->setPositionY(m_height / 2 - 7.f);
|
||||
}
|
||||
m_mainLayer->addChild(creatorLabel);
|
||||
this->addChild(creatorLabel);
|
||||
|
||||
if (hasDesc) {
|
||||
auto descBG = CCScale9Sprite::create("square02b_001.png", { 0.0f, 0.0f, 80.0f, 80.0f });
|
||||
|
@ -90,48 +92,41 @@ void ModListCell::setupInfo(ModInfo const& info, bool spaceForCategories) {
|
|||
descBG->setContentSize({ m_width * 2, 60.f });
|
||||
descBG->setAnchorPoint({ .0f, .5f });
|
||||
descBG->setPositionX(m_height / 2 + logoSize / 2 + 13.f);
|
||||
if (spaceForCategories) {
|
||||
if (spaceForTags) {
|
||||
descBG->setPositionY(m_height / 2 - 7.5f);
|
||||
}
|
||||
else {
|
||||
descBG->setPositionY(m_height / 2 - 17.f);
|
||||
}
|
||||
descBG->setScale(.25f);
|
||||
m_mainLayer->addChild(descBG);
|
||||
this->addChild(descBG);
|
||||
|
||||
auto descText = CCLabelBMFont::create(info.m_description.value().c_str(), "chatFont.fnt");
|
||||
descText->setAnchorPoint({ .0f, .5f });
|
||||
descText->setPosition(m_height / 2 + logoSize / 2 + 18.f, descBG->getPositionY());
|
||||
descText->limitLabelWidth(m_width / 2 - 10.f, .5f, .1f);
|
||||
m_mainLayer->addChild(descText);
|
||||
m_description = CCLabelBMFont::create(info.m_description.value().c_str(), "chatFont.fnt");
|
||||
m_description->setAnchorPoint({ .0f, .5f });
|
||||
m_description->setPosition(m_height / 2 + logoSize / 2 + 18.f, descBG->getPositionY());
|
||||
m_description->limitLabelWidth(m_width / 2 - 10.f, .5f, .1f);
|
||||
this->addChild(m_description);
|
||||
}
|
||||
}
|
||||
|
||||
void ModListCell::updateBGColor(int index) {
|
||||
if (index % 2) {
|
||||
m_backgroundLayer->setColor(ccc3(0xc2, 0x72, 0x3e));
|
||||
}
|
||||
else m_backgroundLayer->setColor(ccc3(0xa1, 0x58, 0x2c));
|
||||
m_backgroundLayer->setOpacity(0xff);
|
||||
}
|
||||
|
||||
bool ModListCell::init(ModListView* list, ModListDisplay display) {
|
||||
m_list = list;
|
||||
m_display = display;
|
||||
bool ModListCell::init(ModListLayer* list, CCSize const& size) {
|
||||
m_width = size.width;
|
||||
m_height = size.height;
|
||||
m_layer = list;
|
||||
this->setContentSize(size);
|
||||
this->setID("mod-list-cell");
|
||||
return true;
|
||||
}
|
||||
|
||||
// ModCell
|
||||
|
||||
ModCell::ModCell(const char* name, CCSize const& size)
|
||||
: ModListCell(name, size) {}
|
||||
|
||||
ModCell* ModCell::create(
|
||||
ModListView* list, ModListDisplay display,
|
||||
const char* key, CCSize const& size
|
||||
Mod* mod,
|
||||
ModListLayer* list,
|
||||
CCSize const& size
|
||||
) {
|
||||
auto ret = new ModCell(key, size);
|
||||
if (ret && ret->init(list, display)) {
|
||||
auto ret = new ModCell();
|
||||
if (ret && ret->init(mod, list, size)) {
|
||||
return ret;
|
||||
}
|
||||
CC_SAFE_DELETE(ret);
|
||||
|
@ -148,7 +143,7 @@ void ModCell::onEnable(CCObject* sender) {
|
|||
"need to <cg>restart</c> the game to have it fully unloaded.",
|
||||
"OK"
|
||||
)->show();
|
||||
m_list->updateAllStates(this);
|
||||
m_layer->updateAllStates(this);
|
||||
return;
|
||||
}
|
||||
if (!as<CCMenuItemToggler*>(sender)->isToggled()) {
|
||||
|
@ -157,7 +152,7 @@ void ModCell::onEnable(CCObject* sender) {
|
|||
else {
|
||||
tryOrAlert(m_mod->disable(), "Error disabling mod");
|
||||
}
|
||||
m_list->updateAllStates(this);
|
||||
m_layer->updateAllStates(this);
|
||||
}
|
||||
|
||||
void ModCell::onUnresolvedInfo(CCObject*) {
|
||||
|
@ -176,7 +171,7 @@ void ModCell::onUnresolvedInfo(CCObject*) {
|
|||
}
|
||||
|
||||
void ModCell::onInfo(CCObject*) {
|
||||
LocalModInfoPopup::create(m_mod, m_list)->show();
|
||||
LocalModInfoPopup::create(m_mod, m_layer)->show();
|
||||
}
|
||||
|
||||
void ModCell::updateState() {
|
||||
|
@ -192,7 +187,14 @@ void ModCell::updateState() {
|
|||
m_unresolvedExMark->setVisible(unresolved);
|
||||
}
|
||||
|
||||
void ModCell::loadFromMod(Mod* mod) {
|
||||
bool ModCell::init(
|
||||
Mod* mod,
|
||||
ModListLayer* list,
|
||||
CCSize const& size
|
||||
) {
|
||||
if (!ModListCell::init(list, size))
|
||||
return false;
|
||||
|
||||
m_mod = mod;
|
||||
|
||||
this->setupInfo(mod->getModInfo(), false);
|
||||
|
@ -238,6 +240,8 @@ void ModCell::loadFromMod(Mod* mod) {
|
|||
// }
|
||||
|
||||
this->updateState();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
CCNode* ModCell::createLogo(CCSize const& size) {
|
||||
|
@ -246,29 +250,34 @@ CCNode* ModCell::createLogo(CCSize const& size) {
|
|||
|
||||
// IndexItemCell
|
||||
|
||||
IndexItemCell::IndexItemCell(char const* name, CCSize const& size)
|
||||
: ModListCell(name, size) {}
|
||||
|
||||
void IndexItemCell::onInfo(CCObject*) {
|
||||
IndexItemInfoPopup::create(m_item, m_list)->show();
|
||||
IndexItemInfoPopup::create(m_item, m_layer)->show();
|
||||
}
|
||||
|
||||
IndexItemCell* IndexItemCell::create(
|
||||
ModListView* list, ModListDisplay display,
|
||||
const char* key, CCSize const& size
|
||||
IndexItemHandle item,
|
||||
ModListLayer* list,
|
||||
CCSize const& size
|
||||
) {
|
||||
auto ret = new IndexItemCell(key, size);
|
||||
if (ret && ret->init(list, display)) {
|
||||
auto ret = new IndexItemCell();
|
||||
if (ret && ret->init(item, list, size)) {
|
||||
return ret;
|
||||
}
|
||||
CC_SAFE_DELETE(ret);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void IndexItemCell::loadFromItem(IndexItemHandle item) {
|
||||
bool IndexItemCell::init(
|
||||
IndexItemHandle item,
|
||||
ModListLayer* list,
|
||||
CCSize const& size
|
||||
) {
|
||||
if (!ModListCell::init(list, size))
|
||||
return false;
|
||||
|
||||
m_item = item;
|
||||
|
||||
this->setupInfo(item->info, true);
|
||||
this->setupInfo(item->info, item->tags.size());
|
||||
|
||||
auto viewSpr = ButtonSprite::create(
|
||||
"View", "bigFont.fnt", "GJ_button_01.png", .8f
|
||||
|
@ -280,26 +289,28 @@ void IndexItemCell::loadFromItem(IndexItemHandle item) {
|
|||
);
|
||||
m_menu->addChild(viewBtn);
|
||||
|
||||
// if (hasCategories) {
|
||||
// float x = m_height / 2 + logoSize / 2 + 13.f;
|
||||
// for (auto& category : modobj->m_index.m_categories) {
|
||||
// auto node = CategoryNode::create(category);
|
||||
// node->setAnchorPoint({ .0f, .5f });
|
||||
// node->setPositionX(x);
|
||||
// node->setScale(.3f);
|
||||
// if (hasDesc) {
|
||||
// node->setPositionY(m_height / 2 - 23.f);
|
||||
// }
|
||||
// else {
|
||||
// node->setPositionY(m_height / 2 - 17.f);
|
||||
// }
|
||||
// m_mainLayer->addChild(node);
|
||||
if (item->tags.size()) {
|
||||
float x = m_height / 2 + this->getLogoSize() / 2 + 13.f;
|
||||
for (auto& category : item->tags) {
|
||||
auto node = TagNode::create(category);
|
||||
node->setAnchorPoint({ .0f, .5f });
|
||||
node->setPositionX(x);
|
||||
node->setScale(.3f);
|
||||
if (m_description) {
|
||||
node->setPositionY(m_height / 2 - 23.f);
|
||||
}
|
||||
else {
|
||||
node->setPositionY(m_height / 2 - 12.f);
|
||||
}
|
||||
this->addChild(node);
|
||||
|
||||
// x += node->getScaledContentSize().width + 5.f;
|
||||
// }
|
||||
// }
|
||||
x += node->getScaledContentSize().width + 5.f;
|
||||
}
|
||||
}
|
||||
|
||||
this->updateState();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void IndexItemCell::updateState() {}
|
||||
|
@ -310,9 +321,6 @@ CCNode* IndexItemCell::createLogo(CCSize const& size) {
|
|||
|
||||
// InvalidGeodeFileCell
|
||||
|
||||
InvalidGeodeFileCell::InvalidGeodeFileCell(const char* name, CCSize const& size)
|
||||
: ModListCell(name, size) {}
|
||||
|
||||
void InvalidGeodeFileCell::onInfo(CCObject*) {
|
||||
FLAlertLayer::create(
|
||||
this, "Error Info",
|
||||
|
@ -345,36 +353,29 @@ void InvalidGeodeFileCell::FLAlert_Clicked(FLAlertLayer*, bool btn2) {
|
|||
)->show();
|
||||
}
|
||||
(void)Loader::get()->refreshModsList();
|
||||
m_list->refreshList();
|
||||
m_layer->reloadList();
|
||||
}
|
||||
}
|
||||
|
||||
InvalidGeodeFileCell* InvalidGeodeFileCell::create(
|
||||
ModListView* list, ModListDisplay display,
|
||||
char const* key, CCSize const& size
|
||||
bool InvalidGeodeFileCell::init(
|
||||
InvalidGeodeFile const& info,
|
||||
ModListLayer* list,
|
||||
CCSize const& size
|
||||
) {
|
||||
auto ret = new InvalidGeodeFileCell(key, size);
|
||||
if (ret && ret->init(list, display)) {
|
||||
return ret;
|
||||
}
|
||||
CC_SAFE_DELETE(ret);
|
||||
return nullptr;
|
||||
}
|
||||
if (!ModListCell::init(list, size))
|
||||
return false;
|
||||
|
||||
void InvalidGeodeFileCell::loadFromInfo(InvalidGeodeFile const& info) {
|
||||
m_info = info;
|
||||
|
||||
m_mainLayer->setVisible(true);
|
||||
|
||||
auto menu = CCMenu::create();
|
||||
menu->setPosition(m_width - m_height, m_height / 2);
|
||||
m_mainLayer->addChild(menu);
|
||||
this->addChild(menu);
|
||||
|
||||
auto titleLabel = CCLabelBMFont::create("Failed to Load", "bigFont.fnt");
|
||||
titleLabel->setAnchorPoint({ .0f, .5f });
|
||||
titleLabel->setScale(.5f);
|
||||
titleLabel->setPosition(m_height / 2, m_height / 2 + 7.f);
|
||||
m_mainLayer->addChild(titleLabel);
|
||||
this->addChild(titleLabel);
|
||||
|
||||
auto pathLabel = CCLabelBMFont::create(
|
||||
m_info.m_path.string().c_str(),
|
||||
|
@ -384,7 +385,7 @@ void InvalidGeodeFileCell::loadFromInfo(InvalidGeodeFile const& info) {
|
|||
pathLabel->setScale(.43f);
|
||||
pathLabel->setPosition(m_height / 2, m_height / 2 - 7.f);
|
||||
pathLabel->setColor({ 255, 255, 0 });
|
||||
m_mainLayer->addChild(pathLabel);
|
||||
this->addChild(pathLabel);
|
||||
|
||||
auto whySpr = ButtonSprite::create(
|
||||
"Info", 0, 0, "bigFont.fnt", "GJ_button_01.png", 0, .8f
|
||||
|
@ -395,6 +396,22 @@ void InvalidGeodeFileCell::loadFromInfo(InvalidGeodeFile const& info) {
|
|||
whySpr, this, menu_selector(InvalidGeodeFileCell::onInfo)
|
||||
);
|
||||
menu->addChild(viewBtn);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
InvalidGeodeFileCell* InvalidGeodeFileCell::create(
|
||||
InvalidGeodeFile const& file,
|
||||
ModListLayer* list,
|
||||
CCSize const& size
|
||||
) {
|
||||
auto ret = new InvalidGeodeFileCell();
|
||||
if (ret && ret->init(file, list, size)) {
|
||||
ret->autorelease();
|
||||
return ret;
|
||||
}
|
||||
CC_SAFE_DELETE(ret);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void InvalidGeodeFileCell::updateState() {}
|
||||
|
|
|
@ -8,33 +8,45 @@
|
|||
|
||||
USE_GEODE_NAMESPACE();
|
||||
|
||||
class ModListView;
|
||||
class ModListLayer;
|
||||
enum class ModListDisplay;
|
||||
|
||||
class ModListCell : public TableViewCell {
|
||||
/**
|
||||
* Base class for mod list items
|
||||
*/
|
||||
class ModListCell : public CCLayer {
|
||||
protected:
|
||||
ModListView* m_list;
|
||||
float m_width;
|
||||
float m_height;
|
||||
ModListLayer* m_layer;
|
||||
CCMenu* m_menu;
|
||||
CCLabelBMFont* m_description;
|
||||
CCMenuItemToggler* m_enableToggle = nullptr;
|
||||
CCMenuItemSpriteExtra* m_unresolvedExMark;
|
||||
ModListDisplay m_display;
|
||||
|
||||
ModListCell(char const* name, CCSize const& size);
|
||||
bool init(ModListView* list, ModListDisplay display);
|
||||
void setupInfo(ModInfo const& info, bool spaceForCategories);
|
||||
bool init(ModListLayer* list, CCSize const& size);
|
||||
void setupInfo(ModInfo const& info, bool spaceForTags);
|
||||
void draw() override;
|
||||
|
||||
float getLogoSize() const;
|
||||
|
||||
public:
|
||||
void updateBGColor(int index);
|
||||
virtual void updateState() = 0;
|
||||
virtual CCNode* createLogo(CCSize const& size) = 0;
|
||||
};
|
||||
|
||||
/**
|
||||
* Mod list item for a mod
|
||||
*/
|
||||
class ModCell : public ModListCell {
|
||||
protected:
|
||||
Mod* m_mod;
|
||||
|
||||
ModCell(char const* name, CCSize const& size);
|
||||
bool init(
|
||||
Mod* mod,
|
||||
ModListLayer* list,
|
||||
CCSize const& size
|
||||
);
|
||||
|
||||
void onInfo(CCObject*);
|
||||
void onEnable(CCObject*);
|
||||
|
@ -42,50 +54,64 @@ protected:
|
|||
|
||||
public:
|
||||
static ModCell* create(
|
||||
ModListView* list, ModListDisplay display,
|
||||
const char* key, CCSize const& size
|
||||
Mod* mod,
|
||||
ModListLayer* list,
|
||||
CCSize const& size
|
||||
);
|
||||
|
||||
void loadFromMod(Mod* mod);
|
||||
void updateState() override;
|
||||
CCNode* createLogo(CCSize const& size) override;
|
||||
};
|
||||
|
||||
/**
|
||||
* Mod list item for an index item
|
||||
*/
|
||||
class IndexItemCell : public ModListCell {
|
||||
protected:
|
||||
IndexItemHandle m_item;
|
||||
|
||||
IndexItemCell(char const* name, CCSize const& size);
|
||||
bool init(
|
||||
IndexItemHandle item,
|
||||
ModListLayer* list,
|
||||
CCSize const& size
|
||||
);
|
||||
|
||||
void onInfo(CCObject*);
|
||||
|
||||
public:
|
||||
static IndexItemCell* create(
|
||||
ModListView* list, ModListDisplay display,
|
||||
const char* key, CCSize const& size
|
||||
IndexItemHandle item,
|
||||
ModListLayer* list,
|
||||
CCSize const& size
|
||||
);
|
||||
|
||||
void loadFromItem(IndexItemHandle item);
|
||||
void updateState() override;
|
||||
CCNode* createLogo(CCSize const& size) override;
|
||||
};
|
||||
|
||||
/**
|
||||
* Mod list item for an invalid Geode package
|
||||
*/
|
||||
class InvalidGeodeFileCell : public ModListCell, public FLAlertLayerProtocol {
|
||||
protected:
|
||||
InvalidGeodeFile m_info;
|
||||
|
||||
InvalidGeodeFileCell(char const* name, CCSize const& size);
|
||||
bool init(
|
||||
InvalidGeodeFile const& file,
|
||||
ModListLayer* list,
|
||||
CCSize const& size
|
||||
);
|
||||
|
||||
void onInfo(CCObject*);
|
||||
void FLAlert_Clicked(FLAlertLayer*, bool btn2) override;
|
||||
|
||||
public:
|
||||
static InvalidGeodeFileCell* create(
|
||||
ModListView* list, ModListDisplay display,
|
||||
const char* key, CCSize const& size
|
||||
InvalidGeodeFile const& file,
|
||||
ModListLayer* list,
|
||||
CCSize const& size
|
||||
);
|
||||
|
||||
void loadFromInfo(InvalidGeodeFile const& file);
|
||||
void updateState() override;
|
||||
CCNode* createLogo(CCSize const& size) override;
|
||||
};
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
#include "ModListLayer.hpp"
|
||||
|
||||
#include "ModListCell.hpp"
|
||||
#include "SearchFilterPopup.hpp"
|
||||
|
||||
#include <Geode/binding/ButtonSprite.hpp>
|
||||
|
@ -14,11 +14,42 @@
|
|||
#include <Geode/ui/Notification.hpp>
|
||||
#include <Geode/utils/casts.hpp>
|
||||
#include <Geode/loader/Dirs.hpp>
|
||||
#include <Geode/loader/Loader.hpp>
|
||||
#include <optional>
|
||||
#include <Geode/ui/ListView.hpp>
|
||||
|
||||
static ModListType g_tab = ModListType::Installed;
|
||||
static ModListLayer* g_instance = nullptr;
|
||||
|
||||
static void sortInstalledMods(std::vector<Mod*>& mods) {
|
||||
if (!mods.size()) return;
|
||||
// keep track of first object
|
||||
size_t frontIndex = 0;
|
||||
auto front = mods.front();
|
||||
for (auto mod = mods.begin(); mod != mods.end(); mod++) {
|
||||
// move mods with updates to front
|
||||
if (auto item = Index::get()->getItem(*mod)) {
|
||||
if (Index::get()->updateAvailable(item)) {
|
||||
// swap first object and updatable mod
|
||||
// if the updatable mod is the first object,
|
||||
// nothing changes
|
||||
std::rotate(mods.begin(), mod, mod + 1);
|
||||
|
||||
// get next object at front for next mod
|
||||
// to sort
|
||||
frontIndex++;
|
||||
front = mods[frontIndex];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static std::vector<Mod*> sortedInstalledMods() {
|
||||
auto mods = Loader::get()->getAllMods();
|
||||
sortInstalledMods(mods);
|
||||
return std::move(mods);
|
||||
}
|
||||
|
||||
bool ModListLayer::init() {
|
||||
if (!CCLayer::init()) return false;
|
||||
|
||||
|
@ -216,11 +247,15 @@ void ModListLayer::reloadList() {
|
|||
m_list->removeFromParent();
|
||||
}
|
||||
|
||||
auto items = ModListView::modsForType(g_tab);
|
||||
auto items = this->createModCells(g_tab);
|
||||
|
||||
// create new list
|
||||
auto list = ModListView::create(items, m_display);
|
||||
list->setLayer(this);
|
||||
auto list = ListView::create(
|
||||
items,
|
||||
this->getCellSize().height,
|
||||
this->getListSize().width,
|
||||
this->getListSize().height
|
||||
);
|
||||
|
||||
// set list status
|
||||
if (!items->count()) {
|
||||
|
@ -306,6 +341,68 @@ void ModListLayer::reloadList() {
|
|||
}
|
||||
}
|
||||
|
||||
CCSize ModListLayer::getListSize() const {
|
||||
return { 358.f, 190.f };
|
||||
}
|
||||
|
||||
CCSize ModListLayer::getCellSize() const {
|
||||
return {
|
||||
getListSize().width,
|
||||
m_display == ModListDisplay::Expanded ? 60.f : 40.f
|
||||
};
|
||||
}
|
||||
|
||||
ModListDisplay ModListLayer::getDisplay() const {
|
||||
return m_display;
|
||||
}
|
||||
|
||||
CCArray* ModListLayer::createModCells(ModListType type) {
|
||||
auto mods = CCArray::create();
|
||||
switch (type) {
|
||||
default:
|
||||
case ModListType::Installed: {
|
||||
// failed mods first
|
||||
for (auto const& mod : Loader::get()->getFailedMods()) {
|
||||
mods->addObject(InvalidGeodeFileCell::create(mod, this, this->getCellSize()));
|
||||
}
|
||||
// internal geode representation always at the top
|
||||
auto imod = Loader::getInternalMod();
|
||||
mods->addObject(ModCell::create(imod, this, this->getCellSize()));
|
||||
|
||||
// then other mods
|
||||
for (auto const& mod : sortedInstalledMods()) {
|
||||
// if the mod is no longer installed nor
|
||||
// loaded, it's as good as not existing
|
||||
// (because it doesn't)
|
||||
if (mod->isUninstalled() && !mod->isLoaded()) continue;
|
||||
mods->addObject(ModCell::create(mod, this, this->getCellSize()));
|
||||
}
|
||||
} break;
|
||||
|
||||
case ModListType::Download: {
|
||||
for (auto const& item : Index::get()->getItems()) {
|
||||
mods->addObject(IndexItemCell::create(item, this, this->getCellSize()));
|
||||
}
|
||||
} break;
|
||||
|
||||
case ModListType::Featured: {
|
||||
// todo: featured
|
||||
} break;
|
||||
}
|
||||
return mods;
|
||||
}
|
||||
|
||||
void ModListLayer::updateAllStates(ModListCell* toggled) {
|
||||
for (auto cell : CCArrayExt<GenericListCell>(
|
||||
m_list->m_listView->m_tableView->m_cellArray
|
||||
)) {
|
||||
auto node = static_cast<ModListCell*>(cell->getChildByID("mod-list-cell"));
|
||||
if (toggled != node) {
|
||||
node->updateState();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ModListLayer::onCheckForUpdates(CCObject*) {
|
||||
// store instance in a global so the
|
||||
// layer stays in memory even if the
|
||||
|
@ -331,10 +428,6 @@ void ModListLayer::onIndexUpdate(IndexUpdateEvent* event) {
|
|||
}, event->status);
|
||||
}
|
||||
|
||||
void ModListLayer::textChanged(CCTextInputNode* input) {
|
||||
this->reloadList();
|
||||
}
|
||||
|
||||
void ModListLayer::onExit(CCObject*) {
|
||||
CCDirector::sharedDirector()->replaceScene(
|
||||
CCTransitionFade::create(.5f, MenuLayer::scene(false))
|
||||
|
@ -365,12 +458,6 @@ void ModListLayer::onResetSearch(CCObject*) {
|
|||
m_searchInput->setString("");
|
||||
}
|
||||
|
||||
void ModListLayer::keyDown(enumKeyCodes key) {
|
||||
if (key == KEY_Escape) {
|
||||
this->onExit(nullptr);
|
||||
}
|
||||
}
|
||||
|
||||
void ModListLayer::onTab(CCObject* pSender) {
|
||||
if (pSender) {
|
||||
g_tab = static_cast<ModListType>(pSender->getTag());
|
||||
|
@ -394,6 +481,16 @@ void ModListLayer::onTab(CCObject* pSender) {
|
|||
toggleTab(m_featuredTabBtn);
|
||||
}
|
||||
|
||||
void ModListLayer::keyDown(enumKeyCodes key) {
|
||||
if (key == KEY_Escape) {
|
||||
this->onExit(nullptr);
|
||||
}
|
||||
}
|
||||
|
||||
void ModListLayer::textChanged(CCTextInputNode* input) {
|
||||
this->reloadList();
|
||||
}
|
||||
|
||||
ModListLayer* ModListLayer::create() {
|
||||
// return global instance if one exists
|
||||
if (g_instance) return g_instance;
|
||||
|
|
|
@ -1,13 +1,23 @@
|
|||
#pragma once
|
||||
|
||||
#include "ModListView.hpp"
|
||||
|
||||
#include <Geode/binding/TextInputDelegate.hpp>
|
||||
#include <Geode/loader/Index.hpp>
|
||||
|
||||
USE_GEODE_NAMESPACE();
|
||||
|
||||
class SearchFilterPopup;
|
||||
class ModListCell;
|
||||
|
||||
enum class ModListType {
|
||||
Installed,
|
||||
Download,
|
||||
Featured,
|
||||
};
|
||||
|
||||
enum class ModListDisplay {
|
||||
Concise,
|
||||
Expanded,
|
||||
};
|
||||
|
||||
class ModListLayer : public CCLayer, public TextInputDelegate {
|
||||
protected:
|
||||
|
@ -46,11 +56,18 @@ protected:
|
|||
void createSearchControl();
|
||||
void onIndexUpdate(IndexUpdateEvent* event);
|
||||
|
||||
CCArray* createModCells(ModListType type);
|
||||
CCSize getCellSize() const;
|
||||
CCSize getListSize() const;
|
||||
|
||||
friend class SearchFilterPopup;
|
||||
|
||||
public:
|
||||
static ModListLayer* create();
|
||||
static ModListLayer* scene();
|
||||
void updateAllStates(ModListCell* except = nullptr);
|
||||
|
||||
ModListDisplay getDisplay() const;
|
||||
|
||||
void reloadList();
|
||||
};
|
||||
|
|
|
@ -1,164 +0,0 @@
|
|||
#include "ModListView.hpp"
|
||||
|
||||
#include "../info/CategoryNode.hpp"
|
||||
#include "ModListLayer.hpp"
|
||||
#include "ModListCell.hpp"
|
||||
|
||||
#include <Geode/binding/ButtonSprite.hpp>
|
||||
#include <Geode/binding/CCMenuItemSpriteExtra.hpp>
|
||||
#include <Geode/binding/TableView.hpp>
|
||||
#include <Geode/binding/CCMenuItemToggler.hpp>
|
||||
#include <Geode/binding/CCContentLayer.hpp>
|
||||
#include <Geode/loader/Mod.hpp>
|
||||
#include <Geode/utils/casts.hpp>
|
||||
#include <Geode/utils/cocos.hpp>
|
||||
#include <Geode/utils/string.hpp>
|
||||
#include <Geode/loader/Index.hpp>
|
||||
#include <InternalLoader.hpp>
|
||||
|
||||
void ModListView::updateAllStates(ModListCell* toggled) {
|
||||
for (auto cell : CCArrayExt<ModListCell>(m_tableView->m_cellArray)) {
|
||||
if (toggled != cell) {
|
||||
cell->updateState();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ModListView::setupList() {
|
||||
m_itemSeparation = m_display == ModListDisplay::Expanded ? 60.f : 40.0f;
|
||||
|
||||
if (!m_entries->count()) return;
|
||||
|
||||
m_tableView->reloadData();
|
||||
|
||||
// fix content layer content size so the
|
||||
// list is properly aligned to the top
|
||||
auto coverage = calculateChildCoverage(m_tableView->m_contentLayer);
|
||||
m_tableView->m_contentLayer->setContentSize({
|
||||
-coverage.origin.x + coverage.size.width,
|
||||
-coverage.origin.y + coverage.size.height
|
||||
});
|
||||
|
||||
if (m_entries->count() == 1) {
|
||||
m_tableView->moveToTopWithOffset(m_itemSeparation * 2);
|
||||
}
|
||||
else if (m_entries->count() == 2) {
|
||||
m_tableView->moveToTopWithOffset(-m_itemSeparation);
|
||||
}
|
||||
else {
|
||||
m_tableView->moveToTop();
|
||||
}
|
||||
}
|
||||
|
||||
TableViewCell* ModListView::getListCell(char const* key) {
|
||||
return ModCell::create(this, m_display, key, { m_width, m_itemSeparation });
|
||||
}
|
||||
|
||||
void ModListView::loadCell(TableViewCell* cell, unsigned int index) {
|
||||
auto obj = m_entries->objectAtIndex(index);
|
||||
if (auto mod = typeinfo_cast<ModObject*>(obj)) {
|
||||
as<ModCell*>(cell)->loadFromMod(mod->mod);
|
||||
}
|
||||
if (auto mod = typeinfo_cast<IndexItemObject*>(obj)) {
|
||||
// as<IndexItemCell*>(cell)->loadFromItem(mod->item);
|
||||
}
|
||||
if (auto failed = typeinfo_cast<InvalidGeodeFileObject*>(obj)) {
|
||||
as<InvalidGeodeFileCell*>(cell)->loadFromInfo(failed->info);
|
||||
}
|
||||
as<ModListCell*>(cell)->updateBGColor(index);
|
||||
}
|
||||
|
||||
static void sortInstalledMods(std::vector<Mod*>& mods) {
|
||||
if (!mods.size()) return;
|
||||
// keep track of first object
|
||||
size_t frontIndex = 0;
|
||||
auto front = mods.front();
|
||||
for (auto mod = mods.begin(); mod != mods.end(); mod++) {
|
||||
// move mods with updates to front
|
||||
if (auto item = Index::get()->getItem(*mod)) {
|
||||
if (Index::get()->updateAvailable(item)) {
|
||||
// swap first object and updatable mod
|
||||
// if the updatable mod is the first object,
|
||||
// nothing changes
|
||||
std::rotate(mods.begin(), mod, mod + 1);
|
||||
|
||||
// get next object at front for next mod
|
||||
// to sort
|
||||
frontIndex++;
|
||||
front = mods[frontIndex];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static std::vector<Mod*> sortedInstalledMods() {
|
||||
auto mods = Loader::get()->getAllMods();
|
||||
sortInstalledMods(mods);
|
||||
return std::move(mods);
|
||||
}
|
||||
|
||||
bool ModListView::init(CCArray* mods, ModListDisplay display) {
|
||||
m_display = display;
|
||||
return CustomListView::init(mods, BoomListType::Default, 358.f, 190.f);
|
||||
}
|
||||
|
||||
CCArray* ModListView::modsForType(ModListType type) {
|
||||
auto mods = CCArray::create();
|
||||
switch (type) {
|
||||
default:
|
||||
case ModListType::Installed: {
|
||||
// failed mods first
|
||||
for (auto const& mod : Loader::get()->getFailedMods()) {
|
||||
mods->addObject(new InvalidGeodeFileObject(mod));
|
||||
}
|
||||
// internal geode representation always at the top
|
||||
auto imod = Loader::getInternalMod();
|
||||
mods->addObject(new ModObject(imod));
|
||||
|
||||
// then other mods
|
||||
for (auto const& mod : sortedInstalledMods()) {
|
||||
// if the mod is no longer installed nor
|
||||
// loaded, it's as good as not existing
|
||||
// (because it doesn't)
|
||||
if (mod->isUninstalled() && !mod->isLoaded()) continue;
|
||||
mods->addObject(new ModObject(mod));
|
||||
}
|
||||
} break;
|
||||
|
||||
case ModListType::Download: {
|
||||
for (auto const& item : Index::get()->getItems()) {
|
||||
mods->addObject(new IndexItemObject(item));
|
||||
}
|
||||
} break;
|
||||
|
||||
case ModListType::Featured: {
|
||||
} break;
|
||||
}
|
||||
return mods;
|
||||
}
|
||||
|
||||
ModListView* ModListView::create(CCArray* mods, ModListDisplay display) {
|
||||
auto pRet = new ModListView;
|
||||
if (pRet) {
|
||||
if (pRet->init(mods, display)) {
|
||||
pRet->autorelease();
|
||||
return pRet;
|
||||
}
|
||||
}
|
||||
CC_SAFE_DELETE(pRet);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
ModListView* ModListView::create(ModListType type, ModListDisplay display) {
|
||||
return ModListView::create(modsForType(type), display);
|
||||
}
|
||||
|
||||
void ModListView::setLayer(ModListLayer* layer) {
|
||||
m_layer = layer;
|
||||
}
|
||||
|
||||
void ModListView::refreshList() {
|
||||
if (m_layer) {
|
||||
m_layer->reloadList();
|
||||
}
|
||||
}
|
|
@ -1,67 +0,0 @@
|
|||
#pragma once
|
||||
|
||||
#include <Geode/binding/CustomListView.hpp>
|
||||
#include <Geode/binding/FLAlertLayerProtocol.hpp>
|
||||
#include <Geode/binding/TableViewCell.hpp>
|
||||
#include <Geode/loader/Index.hpp>
|
||||
#include <Geode/loader/Loader.hpp>
|
||||
#include <optional>
|
||||
|
||||
USE_GEODE_NAMESPACE();
|
||||
|
||||
enum class ModListType {
|
||||
Installed,
|
||||
Download,
|
||||
Featured,
|
||||
};
|
||||
|
||||
enum class ModListDisplay {
|
||||
Concise,
|
||||
Expanded,
|
||||
};
|
||||
|
||||
class ModListLayer;
|
||||
class ModListCell;
|
||||
|
||||
// for passing invalid files as CCObject
|
||||
struct InvalidGeodeFileObject : public CCObject {
|
||||
InvalidGeodeFile info;
|
||||
inline InvalidGeodeFileObject(InvalidGeodeFile const& info) : info(info) {
|
||||
this->autorelease();
|
||||
}
|
||||
};
|
||||
|
||||
struct ModObject : public CCObject {
|
||||
Mod* mod;
|
||||
inline ModObject(Mod* mod) : mod(mod) {
|
||||
this->autorelease();
|
||||
}
|
||||
};
|
||||
|
||||
struct IndexItemObject : public CCObject {
|
||||
IndexItemHandle item;
|
||||
inline IndexItemObject(IndexItemHandle item) : item(item) {
|
||||
this->autorelease();
|
||||
}
|
||||
};
|
||||
|
||||
class ModListView : public CustomListView {
|
||||
protected:
|
||||
ModListLayer* m_layer = nullptr;
|
||||
ModListDisplay m_display;
|
||||
|
||||
void setupList() override;
|
||||
TableViewCell* getListCell(char const* key) override;
|
||||
void loadCell(TableViewCell* cell, unsigned int index) override;
|
||||
|
||||
bool init(CCArray* mods, ModListDisplay display);
|
||||
|
||||
public:
|
||||
static ModListView* create(CCArray* mods, ModListDisplay display);
|
||||
static ModListView* create(ModListType type, ModListDisplay display);
|
||||
static CCArray* modsForType(ModListType type);
|
||||
|
||||
void updateAllStates(ModListCell* except = nullptr);
|
||||
void setLayer(ModListLayer* layer);
|
||||
void refreshList();
|
||||
};
|
|
@ -1,8 +1,7 @@
|
|||
#include "SearchFilterPopup.hpp"
|
||||
|
||||
#include "../info/CategoryNode.hpp"
|
||||
#include "../info/TagNode.hpp"
|
||||
#include "ModListLayer.hpp"
|
||||
#include "ModListView.hpp"
|
||||
|
||||
#include <Geode/binding/GameToolbox.hpp>
|
||||
#include <Geode/binding/CCMenuItemToggler.hpp>
|
||||
|
|
Loading…
Reference in a new issue