mirror of
https://github.com/geode-sdk/geode.git
synced 2025-04-15 22:44:42 -04:00
working on better index filtering
This commit is contained in:
parent
59ada9e7f0
commit
bfa5206704
7 changed files with 199 additions and 67 deletions
loader
include/Geode/ui
src
120
loader/include/Geode/ui/SelectList.hpp
Normal file
120
loader/include/Geode/ui/SelectList.hpp
Normal file
|
@ -0,0 +1,120 @@
|
|||
#pragma once
|
||||
|
||||
#include <Geode/Bindings.hpp>
|
||||
|
||||
namespace geode {
|
||||
|
||||
template<class T>
|
||||
T do_nothing(T t) {
|
||||
return t;
|
||||
}
|
||||
|
||||
template<class T = std::string, auto Stringify = do_nothing<std::string>>
|
||||
class SelectList : public cocos2d::CCMenu {
|
||||
protected:
|
||||
std::vector<T> m_list;
|
||||
size_t m_index = 0;
|
||||
std::function<void(T const&, size_t)> m_onChange;
|
||||
cocos2d::CCLabelBMFont* m_label;
|
||||
CCMenuItemSpriteExtra* m_prevBtn;
|
||||
CCMenuItemSpriteExtra* m_nextBtn;
|
||||
|
||||
bool init(
|
||||
float width,
|
||||
std::vector<T> const& list,
|
||||
std::function<void(T const&, size_t)> onChange
|
||||
) {
|
||||
if (!cocos2d::CCMenu::init())
|
||||
return false;
|
||||
|
||||
m_list = list;
|
||||
m_onChange = onChange;
|
||||
|
||||
this->setContentSize({ width, 30.f });
|
||||
|
||||
auto prevSpr = cocos2d::CCSprite::createWithSpriteFrameName("navArrowBtn_001.png");
|
||||
prevSpr->setFlipX(true);
|
||||
prevSpr->setScale(.3f);
|
||||
|
||||
m_prevBtn = CCMenuItemSpriteExtra::create(
|
||||
prevSpr, this, menu_selector(SelectList<T>::onPrev)
|
||||
);
|
||||
m_prevBtn->setPosition(-width / 2 + 10.f, 0.f);
|
||||
this->addChild(m_prevBtn);
|
||||
|
||||
auto nextSpr = cocos2d::CCSprite::createWithSpriteFrameName("navArrowBtn_001.png");
|
||||
nextSpr->setScale(.3f);
|
||||
|
||||
m_nextBtn = CCMenuItemSpriteExtra::create(
|
||||
nextSpr, this, menu_selector(SelectList<T>::onNext)
|
||||
);
|
||||
m_nextBtn->setPosition(width / 2 - 10.f, 0.f);
|
||||
this->addChild(m_nextBtn);
|
||||
|
||||
m_label = cocos2d::CCLabelBMFont::create("", "bigFont.fnt");
|
||||
this->addChild(m_label);
|
||||
|
||||
this->updateLabel();
|
||||
|
||||
cocos2d::CCDirector::sharedDirector()->getTouchDispatcher()->incrementForcePrio(2);
|
||||
this->registerWithTouchDispatcher();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void updateLabel() {
|
||||
if (m_list.size()) {
|
||||
m_label->setString(Stringify(m_list.at(m_index)).c_str());
|
||||
m_prevBtn->setEnabled(true);
|
||||
m_nextBtn->setEnabled(true);
|
||||
} else {
|
||||
m_label->setString("-");
|
||||
m_prevBtn->setEnabled(false);
|
||||
m_nextBtn->setEnabled(false);
|
||||
}
|
||||
m_label->limitLabelWidth(m_obContentSize.width - 40.f, .6f, .1f);
|
||||
}
|
||||
|
||||
void onPrev(CCObject* sender) {
|
||||
if (m_index == 0) {
|
||||
m_index = m_list.size() - 1;
|
||||
} else {
|
||||
m_index--;
|
||||
}
|
||||
this->updateLabel();
|
||||
m_onChange(m_list.at(m_index), m_index);
|
||||
}
|
||||
|
||||
void onNext(CCObject* sender) {
|
||||
if (m_index == m_list.size() - 1) {
|
||||
m_index = 0;
|
||||
} else {
|
||||
m_index++;
|
||||
}
|
||||
this->updateLabel();
|
||||
m_onChange(m_list.at(m_index), m_index);
|
||||
}
|
||||
|
||||
public:
|
||||
static SelectList* create(
|
||||
float width,
|
||||
std::vector<T> const& list,
|
||||
std::function<void(T const&, size_t)> onChange
|
||||
) {
|
||||
auto ret = new SelectList();
|
||||
if (ret && ret->init(width, list, onChange)) {
|
||||
ret->autorelease();
|
||||
return ret;
|
||||
}
|
||||
CC_SAFE_DELETE(ret);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void setItems(std::vector<T> const& list) {
|
||||
m_index = 0;
|
||||
m_list = list;
|
||||
this->updateLabel();
|
||||
}
|
||||
};
|
||||
|
||||
}
|
|
@ -383,31 +383,6 @@ std::vector<IndexItem> const& Index::getItems() const {
|
|||
return m_items;
|
||||
}
|
||||
|
||||
std::vector<IndexItem> Index::getNoninstalledItems(
|
||||
std::optional<std::unordered_set<PlatformID>> const& platforms
|
||||
) const {
|
||||
std::vector<IndexItem> items;
|
||||
for (auto& item : m_items) {
|
||||
if (!Loader::get()->isModInstalled(item.m_info.m_id)) {
|
||||
// return whatever is available on requested platforms
|
||||
if (platforms) {
|
||||
for (auto& plat : platforms.value()) {
|
||||
if (item.m_download.m_platforms.count(plat)) {
|
||||
items.push_back(item);
|
||||
}
|
||||
}
|
||||
}
|
||||
// otherwise just return whatever is available on current platform
|
||||
else {
|
||||
if (item.m_download.m_platforms.count(GEODE_PLATFORM_TARGET)) {
|
||||
items.push_back(item);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return items;
|
||||
}
|
||||
|
||||
bool Index::isKnownItem(std::string const& id) const {
|
||||
for (auto& item : m_items) {
|
||||
if (item.m_info.m_id == id) return true;
|
||||
|
|
|
@ -133,9 +133,6 @@ public:
|
|||
static Index* get();
|
||||
|
||||
std::vector<IndexItem> const& getItems() const;
|
||||
std::vector<IndexItem> getNoninstalledItems(
|
||||
std::optional<std::unordered_set<PlatformID>> const& platforms
|
||||
) const;
|
||||
bool isKnownItem(std::string const& id) const;
|
||||
IndexItem getKnownItem(std::string const& id) const;
|
||||
Result<InstallTicket*> installItems(
|
||||
|
|
|
@ -367,17 +367,13 @@ void ModListView::loadCell(TableViewCell* cell, unsigned int index) {
|
|||
}
|
||||
}
|
||||
|
||||
bool ModListView::filter(
|
||||
ModInfo const& info,
|
||||
std::optional<std::string> const& searchFilter,
|
||||
int searchFlags
|
||||
) {
|
||||
if (!searchFilter) return true;
|
||||
auto check = [searchFlags, searchFilter](SearchFlags flag, std::string const& name) -> bool {
|
||||
if (!(searchFlags & flag)) return false;
|
||||
bool ModListView::filter(ModInfo const& info, ModListQuery const& query) {
|
||||
if (!query.m_searchFilter) return true;
|
||||
auto check = [query](SearchFlags flag, std::string const& name) -> bool {
|
||||
if (!(query.m_searchFlags & flag)) return false;
|
||||
return string_utils::contains(
|
||||
string_utils::toLower(name),
|
||||
string_utils::toLower(searchFilter.value())
|
||||
string_utils::toLower(query.m_searchFilter.value())
|
||||
);
|
||||
};
|
||||
if (check(SearchFlag::Name, info.m_name)) return true;
|
||||
|
@ -388,6 +384,23 @@ bool ModListView::filter(
|
|||
return false;
|
||||
}
|
||||
|
||||
bool ModListView::filter(IndexItem const& item, ModListQuery const& query) {
|
||||
if (query.m_installed != ModListQuery::All) {
|
||||
if (
|
||||
Loader::get()->isModInstalled(item.m_info.m_id) !=
|
||||
(query.m_installed == ModListQuery::Installed)
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
for (auto& plat : query.m_platforms) {
|
||||
if (item.m_download.m_platforms.count(plat)) {
|
||||
return filter(item.m_info, query);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static void sortInstalledMods(std::vector<Mod*>& mods) {
|
||||
if (!mods.size()) return;
|
||||
// keep track of first object
|
||||
|
@ -432,7 +445,7 @@ bool ModListView::init(
|
|||
}
|
||||
// internal geode representation always at the top
|
||||
auto imod = Loader::getInternalMod();
|
||||
if (this->filter(imod->getModInfo(), query.m_searchFilter, query.m_searchFlags)) {
|
||||
if (this->filter(imod->getModInfo(), query)) {
|
||||
mods->addObject(new ModObject(imod));
|
||||
}
|
||||
// then other mods
|
||||
|
@ -441,7 +454,7 @@ bool ModListView::init(
|
|||
// loaded, it's as good as not existing
|
||||
// (because it doesn't)
|
||||
if (mod->isUninstalled() && !mod->isLoaded()) continue;
|
||||
if (this->filter(mod->getModInfo(), query.m_searchFilter, query.m_searchFlags)) {
|
||||
if (this->filter(mod->getModInfo(), query)) {
|
||||
mods->addObject(new ModObject(mod));
|
||||
}
|
||||
}
|
||||
|
@ -452,8 +465,8 @@ bool ModListView::init(
|
|||
|
||||
case ModListType::Download: {
|
||||
mods = CCArray::create();
|
||||
for (auto const& item : Index::get()->getNoninstalledItems(query.m_platforms)) {
|
||||
if (this->filter(item.m_info, query.m_searchFilter, query.m_searchFlags)) {
|
||||
for (auto const& item : Index::get()->getItems()) {
|
||||
if (this->filter(item, query)) {
|
||||
mods->addObject(new ModObject(item));
|
||||
}
|
||||
}
|
||||
|
@ -478,7 +491,7 @@ ModListView* ModListView::create(
|
|||
ModListType type,
|
||||
float width,
|
||||
float height,
|
||||
ModListQuery query
|
||||
ModListQuery const& query
|
||||
) {
|
||||
auto pRet = new ModListView;
|
||||
if (pRet) {
|
||||
|
@ -495,7 +508,7 @@ ModListView* ModListView::create(
|
|||
ModListType type,
|
||||
float width,
|
||||
float height,
|
||||
ModListQuery query
|
||||
ModListQuery const& query
|
||||
) {
|
||||
return ModListView::create(nullptr, type, width, height, query);
|
||||
}
|
||||
|
|
|
@ -100,6 +100,11 @@ static constexpr SearchFlags ALL_FLAGS =
|
|||
struct ModListQuery {
|
||||
std::optional<std::string> m_searchFilter = std::nullopt;
|
||||
int m_searchFlags = ALL_FLAGS;
|
||||
enum {
|
||||
Installed,
|
||||
Noninstalled,
|
||||
All,
|
||||
} m_installed = Installed;
|
||||
std::unordered_set<PlatformID> m_platforms { GEODE_PLATFORM_TARGET };
|
||||
};
|
||||
|
||||
|
@ -126,11 +131,8 @@ protected:
|
|||
float height,
|
||||
ModListQuery query
|
||||
);
|
||||
bool filter(
|
||||
ModInfo const& info,
|
||||
std::optional<std::string> const& searchFilter,
|
||||
SearchFlags searchFlags
|
||||
);
|
||||
bool filter(ModInfo const& info, ModListQuery const& query);
|
||||
bool filter(IndexItem const& item, ModListQuery const& query);
|
||||
|
||||
public:
|
||||
static ModListView* create(
|
||||
|
@ -138,13 +140,13 @@ public:
|
|||
ModListType type = ModListType::Installed,
|
||||
float width = 358.f,
|
||||
float height = 220.f,
|
||||
ModListQuery query = ModListQuery()
|
||||
ModListQuery const& query = ModListQuery()
|
||||
);
|
||||
static ModListView* create(
|
||||
ModListType type,
|
||||
float width = 358.f,
|
||||
float height = 220.f,
|
||||
ModListQuery query = ModListQuery()
|
||||
ModListQuery const& query = ModListQuery()
|
||||
);
|
||||
|
||||
void updateAllStates(ModCell* toggled = nullptr);
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
#include "SearchFilterPopup.hpp"
|
||||
#include "ModListLayer.hpp"
|
||||
#include "ModListView.hpp"
|
||||
#include <Geode/ui/SelectList.hpp>
|
||||
|
||||
bool SearchFilterPopup::setup(ModListLayer* layer, ModListType type) {
|
||||
// todo: clean this shitty ass popup up
|
||||
|
@ -22,8 +23,8 @@ bool SearchFilterPopup::setup(ModListLayer* layer, ModListType type) {
|
|||
);
|
||||
matchBG->setColor({ 0, 0, 0 });
|
||||
matchBG->setOpacity(90);
|
||||
matchBG->setContentSize({ 290.f, 300.f });
|
||||
matchBG->setPosition(winSize.width / 2 - 90.f, winSize.height / 2 - 21.f);
|
||||
matchBG->setContentSize({ 290.f, 295.f });
|
||||
matchBG->setPosition(winSize.width / 2 - 90.f, winSize.height / 2 - 21.5f);
|
||||
matchBG->setScale(.5f);
|
||||
m_mainLayer->addChild(matchBG);
|
||||
|
||||
|
@ -50,45 +51,67 @@ bool SearchFilterPopup::setup(ModListLayer* layer, ModListType type) {
|
|||
);
|
||||
platformBG->setColor({ 0, 0, 0 });
|
||||
platformBG->setOpacity(90);
|
||||
platformBG->setContentSize({ 290.f, 300.f });
|
||||
platformBG->setPosition(winSize.width / 2 + 90.f, winSize.height / 2 - 21.f);
|
||||
platformBG->setContentSize({ 290.f, 205.f });
|
||||
platformBG->setPosition(winSize.width / 2 + 90.f, winSize.height / 2 + 1.f);
|
||||
platformBG->setScale(.5f);
|
||||
m_mainLayer->addChild(platformBG);
|
||||
|
||||
pos = CCPoint { winSize.width / 2 + 45.f, winSize.height / 2 + 35.f };
|
||||
pos = CCPoint { winSize.width / 2 + 35.f, winSize.height / 2 + 35.f };
|
||||
|
||||
this->addPlatformToggle("Windows", PlatformID::Windows, pos);
|
||||
this->addPlatformToggle("MacOS", PlatformID::MacOS, pos);
|
||||
this->addPlatformToggle("iOS", PlatformID::iOS, pos);
|
||||
this->addPlatformToggle("Android", PlatformID::Android, pos);
|
||||
this->enable(this->addPlatformToggle("Windows", PlatformID::Windows, pos), type);
|
||||
this->enable(this->addPlatformToggle("MacOS", PlatformID::MacOS, pos), type);
|
||||
this->enable(this->addPlatformToggle("iOS", PlatformID::iOS, pos), type);
|
||||
this->enable(this->addPlatformToggle("Android", PlatformID::Android, pos), type);
|
||||
|
||||
auto installedBG = CCScale9Sprite::create(
|
||||
"square02b_001.png", { 0.0f, 0.0f, 80.0f, 80.0f }
|
||||
);
|
||||
installedBG->setColor({ 0, 0, 0 });
|
||||
installedBG->setOpacity(90);
|
||||
installedBG->setContentSize({ 290.f, 65.f });
|
||||
installedBG->setPosition(winSize.width / 2 + 90.f, winSize.height / 2 - 80.f);
|
||||
installedBG->setScale(.5f);
|
||||
m_mainLayer->addChild(installedBG);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void SearchFilterPopup::addSearchMatch(const char* title, int flag, CCPoint& pos) {
|
||||
GameToolbox::createToggleButton(
|
||||
void SearchFilterPopup::enable(CCMenuItemToggler* toggle, ModListType type) {
|
||||
if (type == ModListType::Installed) {
|
||||
toggle->setEnabled(false);
|
||||
toggle->m_onButton->setColor(cc3x(0x50));
|
||||
toggle->m_offButton->setColor(cc3x(0x50));
|
||||
}
|
||||
}
|
||||
|
||||
CCMenuItemToggler* SearchFilterPopup::addSearchMatch(const char* title, int flag, CCPoint& pos) {
|
||||
auto toggle = GameToolbox::createToggleButton(
|
||||
title, menu_selector(SearchFilterPopup::onSearchToggle),
|
||||
m_modLayer->m_query.m_searchFlags & flag,
|
||||
m_buttonMenu, pos, this,
|
||||
m_buttonMenu, .5f, .5f, 100.f,
|
||||
{ 10.f, .0f }, nullptr, false, flag, nullptr
|
||||
)->setTag(flag);
|
||||
);
|
||||
toggle->setTag(flag);
|
||||
pos.y -= 22.5f;
|
||||
return toggle;
|
||||
}
|
||||
|
||||
void SearchFilterPopup::addPlatformToggle(
|
||||
CCMenuItemToggler* SearchFilterPopup::addPlatformToggle(
|
||||
const char* title,
|
||||
PlatformID id,
|
||||
CCPoint& pos
|
||||
) {
|
||||
GameToolbox::createToggleButton(
|
||||
auto toggle = GameToolbox::createToggleButton(
|
||||
title, menu_selector(SearchFilterPopup::onPlatformToggle),
|
||||
m_modLayer->m_query.m_platforms.count(id),
|
||||
m_buttonMenu, pos, this,
|
||||
m_buttonMenu, .5f, .5f, 100.f,
|
||||
{ 10.f, .0f }, nullptr, false, id.to<int>(), nullptr
|
||||
)->setTag(id.to<int>());
|
||||
);
|
||||
toggle->setTag(id.to<int>());
|
||||
pos.y -= 22.5f;
|
||||
return toggle;
|
||||
}
|
||||
|
||||
void SearchFilterPopup::onSearchToggle(CCObject* sender) {
|
||||
|
|
|
@ -12,12 +12,14 @@ protected:
|
|||
ModListLayer* m_modLayer;
|
||||
|
||||
bool setup(ModListLayer* layer, ModListType type) override;
|
||||
void addSearchMatch(const char* title, int flag, CCPoint& pos);
|
||||
void addPlatformToggle(const char* title, PlatformID id, CCPoint& pos);
|
||||
CCMenuItemToggler* addSearchMatch(const char* title, int flag, CCPoint& pos);
|
||||
CCMenuItemToggler* addPlatformToggle(const char* title, PlatformID id, CCPoint& pos);
|
||||
|
||||
void onSearchToggle(CCObject*);
|
||||
void onPlatformToggle(CCObject*);
|
||||
|
||||
void enable(CCMenuItemToggler* toggle, ModListType type);
|
||||
|
||||
void onClose(CCObject*) override;
|
||||
|
||||
public:
|
||||
|
|
Loading…
Add table
Reference in a new issue