Skip to content

Commit

Permalink
Oh?
Browse files Browse the repository at this point in the history
  • Loading branch information
hiimjasmine00 committed Oct 6, 2024
1 parent cd425b8 commit 4df9abb
Show file tree
Hide file tree
Showing 13 changed files with 311 additions and 96 deletions.
2 changes: 1 addition & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_OSX_ARCHITECTURES "x86_64;arm64")
set(CMAKE_CXX_VISIBILITY_PRESET hidden)

project(MoreIcons VERSION 1.0.4)
project(MoreIcons VERSION 1.1.0)

add_library(${PROJECT_NAME} SHARED
src/hooks/CharacterColorPage.cpp
Expand Down
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
# More Icons
A mod that loads custom icons.

[YouTube Tutorial](https://youtu.be/s2AM98Yj59k)

## Adding Icons
To add a custom icon, you need an icon spritesheet (.plist) and an icon atlas (.png).

Expand Down
2 changes: 2 additions & 0 deletions about.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
# More Icons
A mod that loads custom icons.

[YouTube Tutorial](https://youtu.be/s2AM98Yj59k)

## Adding Icons
To add a custom icon, you need an icon spritesheet (.plist) and an icon atlas (.png).

Expand Down
5 changes: 5 additions & 0 deletions changelog.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,9 @@
# More Icons Changelog
## v1.1.0 (2024-10-06)
- Added support for Separate Dual Icons
- Added loaded icon list in saved.json
- Added icon popups when selecting an icon

## v1.0.4 (2024-10-04)
- Fixed pages resetting when selecting a new tab
- Fixed a bug where the game would crash when selecting the death effect tab
Expand Down
2 changes: 1 addition & 1 deletion mod.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
"win": "2.206",
"mac": "2.206"
},
"version": "v1.0.4",
"version": "v1.1.0",
"id": "hiimjustin000.more_icons",
"name": "More Icons",
"developer": "hiimjustin000",
Expand Down
6 changes: 4 additions & 2 deletions src/MoreIcons.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -96,17 +96,19 @@ void MoreIcons::loadIcons(const std::filesystem::path& path, std::vector<std::st
list.push_back(name);
textures.emplace(name, fullTexturePath);
}

Mod::get()->setSavedValue(path.filename().string() + "s", list);
}

void MoreIcons::changeSimplePlayer(SimplePlayer* player, const std::string& file, IconType iconType) {
if (!player) return;

if (iconType == IconType::Robot) {
static_cast<MIRobotSprite*>(player->m_robotSprite)->useCustomRobot(file);
MIRobotSprite::useCustomRobot(player->m_robotSprite, file);
return;
}
else if (iconType == IconType::Spider) {
static_cast<MIRobotSprite*>(static_cast<GJRobotSprite*>(player->m_spiderSprite))->useCustomSpider(file);
MIRobotSprite::useCustomSpider(player->m_spiderSprite, file);
return;
}

Expand Down
57 changes: 37 additions & 20 deletions src/MoreIcons.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -50,16 +50,25 @@ class MoreIcons {

static void clear() {
ICONS.clear();
geode::Mod::get()->setSavedValue("icons", ICONS);
SHIPS.clear();
geode::Mod::get()->setSavedValue("ships", SHIPS);
BALLS.clear();
geode::Mod::get()->setSavedValue("balls", BALLS);
UFOS.clear();
geode::Mod::get()->setSavedValue("ufos", UFOS);
WAVES.clear();
geode::Mod::get()->setSavedValue("waves", WAVES);
ROBOTS.clear();
ROBOT_TEXTURES.clear();
geode::Mod::get()->setSavedValue("robots", ROBOTS);
SPIDERS.clear();
SPIDER_TEXTURES.clear();
geode::Mod::get()->setSavedValue("spiders", SPIDERS);
SWINGS.clear();
geode::Mod::get()->setSavedValue("swings", SWINGS);
JETPACKS.clear();
geode::Mod::get()->setSavedValue("jetpacks", JETPACKS);
}
static void load() {
auto configDir = geode::Mod::get()->getConfigDir();
Expand All @@ -82,6 +91,16 @@ class MoreIcons {
static bool doesExist(cocos2d::CCSpriteFrame* frame) {
return frame != nullptr && frame->getTag() != 105871529;
}
static std::string getDual(const std::string& name, bool dual) {
return geode::Loader::get()->isModLoaded("weebify.separate_dual_icons") && dual ? name + "-dual" : name;
}
static void swapDual(const std::string& name) {
auto dualName = name + "-dual";
auto normalIcon = geode::Mod::get()->getSavedValue<std::string>(name, "");
auto dualIcon = geode::Mod::get()->getSavedValue<std::string>(dualName, "");
geode::Mod::get()->setSavedValue(name, dualIcon);
geode::Mod::get()->setSavedValue(dualName, normalIcon);
}

static std::vector<std::string>& vectorForType(IconType type) {
switch (type) {
Expand Down Expand Up @@ -111,28 +130,26 @@ class MoreIcons {
}

static std::string savedForType(IconType type) {
auto sdi = geode::Loader::get()->getLoadedMod("weebify.separate_dual_icons");
return savedForType(type, sdi && sdi->getSavedValue("2pselected", false));
}

static std::string savedForType(IconType type, bool dual) {
std::string prefix;
switch (type) {
case IconType::Cube:
return "icon";
case IconType::Ship:
return "ship";
case IconType::Ball:
return "ball";
case IconType::Ufo:
return "ufo";
case IconType::Wave:
return "wave";
case IconType::Robot:
return "robot";
case IconType::Spider:
return "spider";
case IconType::Swing:
return "swing";
case IconType::Jetpack:
return "jetpack";
default:
return "";
case IconType::Cube: prefix = "icon"; break;
case IconType::Ship: prefix = "ship"; break;
case IconType::Ball: prefix = "ball"; break;
case IconType::Ufo: prefix = "ufo"; break;
case IconType::Wave: prefix = "wave"; break;
case IconType::Robot: prefix = "robot"; break;
case IconType::Spider: prefix = "spider"; break;
case IconType::Swing: prefix = "swing"; break;
case IconType::Jetpack: prefix = "jetpack"; break;
default: prefix = ""; break;
}

return getDual(prefix, dual);
}

static std::vector<std::string> getPage(IconType type, int page) {
Expand Down
5 changes: 5 additions & 0 deletions src/hooks/CharacterColorPage.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,11 @@ using namespace geode::prelude;

#include <Geode/modify/CharacterColorPage.hpp>
class $modify(MICharacterColorPage, CharacterColorPage) {
static void onModify(auto& self) {
(void)self.setHookPriority("CharacterColorPage::init", -1);
(void)self.setHookPriority("CharacterColorPage::toggleShip", -1);
}

bool init() {
if (!CharacterColorPage::init()) return false;

Expand Down
90 changes: 82 additions & 8 deletions src/hooks/GJGarageLayer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,19 +10,47 @@ class $modify(MIGarageLayer, GJGarageLayer) {
std::map<IconType, int> m_pages;
int m_page;
bool m_custom;
CCObject* m_originalSDISwitchTarget;
SEL_MenuHandler m_originalSDISwitch;
CCObject* m_originalSDISwapTarget;
SEL_MenuHandler m_originalSDISwap;
};

static void onModify(auto& self) {
(void)self.setHookPriority("GJGarageLayer::init", -1);
(void)self.setHookPriority("GJGarageLayer::setupPage", 1);
}

bool init() {
if (!GJGarageLayer::init()) return false;

auto iconType = GameManager::get()->m_playerIconType;
MoreIcons::changeSimplePlayer(m_playerObject, Mod::get()->getSavedValue<std::string>(MoreIcons::savedForType(iconType), ""), iconType);
MoreIcons::changeSimplePlayer(m_playerObject, Mod::get()->getSavedValue<std::string>(MoreIcons::savedForType(iconType, false), ""), iconType);
auto sdi = Loader::get()->getLoadedMod("weebify.separate_dual_icons");
if (sdi) {
auto lastmode = (IconType)sdi->getSavedValue("lastmode", 0);
MoreIcons::changeSimplePlayer(static_cast<SimplePlayer*>(getChildByID("player2-icon")),
Mod::get()->getSavedValue<std::string>(MoreIcons::savedForType(lastmode, true), ""), lastmode);
}

createNavMenu();
auto customIcon = Mod::get()->getSavedValue<std::string>("icon", "");
if (!customIcon.empty() && MoreIcons::hasIcon(customIcon)) setupCustomPage(MoreIcons::findIconPage(IconType::Cube));
else createNavMenu();

if (sdi) {
auto f = m_fields.self();
auto p1Button = static_cast<CCMenuItemSpriteExtra*>(getChildByID("player-buttons-menu")->getChildByID("player1-button"));
auto p2Button = static_cast<CCMenuItemSpriteExtra*>(getChildByID("player-buttons-menu")->getChildByID("player2-button"));
f->m_originalSDISwitchTarget = p1Button->m_pListener;
f->m_originalSDISwitch = p2Button->m_pfnSelector;
p1Button->setTarget(this, menu_selector(MIGarageLayer::newOn2PToggle));
p2Button->setTarget(this, menu_selector(MIGarageLayer::newOn2PToggle));

auto swap2PButton = static_cast<CCMenuItemSpriteExtra*>(getChildByID("shards-menu")->getChildByID("swap-2p-button"));
f->m_originalSDISwapTarget = swap2PButton->m_pListener;
f->m_originalSDISwap = swap2PButton->m_pfnSelector;
swap2PButton->setTarget(this, menu_selector(MIGarageLayer::newSwap2PKit));
}

return true;
}
Expand All @@ -33,6 +61,34 @@ class $modify(MIGarageLayer, GJGarageLayer) {
Mod::get()->setSavedValue<std::string>(MoreIcons::savedForType(m_iconType), "");
}

void newOn2PToggle(CCObject* sender) {
auto f = m_fields.self();
(f->m_originalSDISwitchTarget->*f->m_originalSDISwitch)(sender);
if (f->m_custom) setupCustomPage(f->m_page);
else createNavMenu();
}

void newSwap2PKit(CCObject* sender) {
auto f = m_fields.self();
(f->m_originalSDISwapTarget->*f->m_originalSDISwap)(sender);
MoreIcons::swapDual("icon");
MoreIcons::swapDual("ship");
MoreIcons::swapDual("ball");
MoreIcons::swapDual("ufo");
MoreIcons::swapDual("wave");
MoreIcons::swapDual("robot");
MoreIcons::swapDual("spider");
MoreIcons::swapDual("swing");
MoreIcons::swapDual("jetpack");
auto iconType = GameManager::get()->m_playerIconType;
MoreIcons::changeSimplePlayer(m_playerObject, Mod::get()->getSavedValue<std::string>(MoreIcons::savedForType(iconType, false), ""), iconType);
auto lastmode = (IconType)Loader::get()->getLoadedMod("weebify.separate_dual_icons")->getSavedValue("lastmode", 0);
MoreIcons::changeSimplePlayer(static_cast<SimplePlayer*>(getChildByID("player2-icon")),
Mod::get()->getSavedValue<std::string>(MoreIcons::savedForType(lastmode, true), ""), lastmode);
if (f->m_custom) setupCustomPage(f->m_page);
else createNavMenu();
}

void updatePlayerColors() {
GJGarageLayer::updatePlayerColors();

Expand Down Expand Up @@ -150,19 +206,37 @@ class $modify(MIGarageLayer, GJGarageLayer) {
auto objs = CCArray::create();
CCMenuItemSpriteExtra* current = nullptr;
auto savedType = MoreIcons::savedForType(m_iconType);
auto sdi = Loader::get()->getLoadedMod("weebify.separate_dual_icons");
auto dual = sdi && sdi->getSavedValue("2pselected", false);
int i = 1;
for (auto name : MoreIcons::getPage(m_iconType, f->m_page)) {
auto itemIcon = GJItemIcon::createBrowserItem(unlockType, 1);
itemIcon->setScale(GJItemIcon::scaleForType(unlockType));
MoreIcons::changeSimplePlayer(itemIcon->m_player, name, m_iconType);
auto iconButton = CCMenuItemExt::createSpriteExtra(itemIcon, [this, f, name, savedType, gameManager](CCMenuItemSpriteExtra* sender) {
Mod::get()->setSavedValue<std::string>(savedType, name);
auto iconButton = CCMenuItemExt::createSpriteExtra(itemIcon, [this, f, name, sdi, dual, savedType, gameManager, unlockType](CCMenuItemSpriteExtra* sender) {
m_cursor1->setPosition(sender->getParent()->convertToWorldSpace(sender->getPosition()));
m_cursor1->setVisible(true);
m_playerObject->updatePlayerFrame(1, m_iconType);
MoreIcons::changeSimplePlayer(m_playerObject, name, m_iconType);
gameManager->m_playerIconType = m_iconType;
m_playerObject->setScale(m_iconType == IconType::Jetpack ? 1.5f : 1.6f);
auto player = dual ? static_cast<SimplePlayer*>(getChildByID("player2-icon")) : m_playerObject;
player->updatePlayerFrame(1, m_iconType);
player->updateColors();
MoreIcons::changeSimplePlayer(player, name, m_iconType);
if (!dual) gameManager->m_playerIconType = m_iconType;
player->setScale(m_iconType == IconType::Jetpack ? 1.5f : 1.6f);
auto selectedIconType = dual ? (IconType)sdi->getSavedValue("lasttype", 0) : m_selectedIconType;
if (Mod::get()->setSavedValue<std::string>(savedType, name) == name && selectedIconType == m_iconType) {
auto popup = ItemInfoPopup::create(1, unlockType);
if (auto nameLabel = getChildOfType<CCLabelBMFont>(popup->m_mainLayer, 0)) nameLabel->setString(name.c_str());
if (auto achLabel = getChildOfType<CCLabelBMFont>(popup->m_mainLayer, 1)) achLabel->setString("Custom");
if (auto popupIcon = getChildOfType<GJItemIcon>(popup->m_mainLayer, 0)) MoreIcons::changeSimplePlayer(popupIcon->m_player, name, m_iconType);
if (auto descText = getChildOfType<TextArea>(popup->m_mainLayer, 0)) descText->setString(
fmt::format("This <cg>{}</c> is added by the <cl>More Icons</c> mod.", std::string(ItemInfoPopup::nameForUnlockType(1, unlockType))));
popup->show();
}
if (dual) {
sdi->setSavedValue("lastmode", (int)m_iconType);
sdi->setSavedValue("lasttype", (int)m_iconType);
}
else m_selectedIconType = m_iconType;
});
iconButton->setContentSize(playerSquare->getContentSize());
itemIcon->setPosition(iconButton->getContentSize() / 2);
Expand Down
63 changes: 27 additions & 36 deletions src/hooks/GJRobotSprite.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,25 +3,8 @@

using namespace geode::prelude;

void MIRobotSprite::updateFrame(int frame) {
GJRobotSprite::updateFrame(frame);

auto gameLayer = GJBaseGameLayer::get();
if (!gameLayer) return;

if (!gameLayer->m_player1 || !gameLayer->m_player2) {
useCustomSprite();
return;
}

if (gameLayer->m_player1->m_robotSprite == this ||
gameLayer->m_player2->m_robotSprite == this ||
gameLayer->m_player1->m_spiderSprite == static_cast<GJRobotSprite*>(this) ||
gameLayer->m_player2->m_spiderSprite == static_cast<GJRobotSprite*>(this)) useCustomSprite();
}

void MIRobotSprite::useCustom(std::string file) {
auto spriteParts = m_paSprite->m_spriteParts;
void MIRobotSprite::useCustom(GJRobotSprite* robot, std::string file) {
auto spriteParts = robot->m_paSprite->m_spriteParts;
auto spriteFrameCache = CCSpriteFrameCache::get();
for (int i = 0; i < spriteParts->count(); i++) {
auto spritePart = static_cast<CCSpritePart*>(spriteParts->objectAtIndex(i));
Expand All @@ -32,44 +15,52 @@ void MIRobotSprite::useCustom(std::string file) {
auto spriteExtraFrame = fmt::format("{}_{:02}_extra_001.png"_spr, file, tag);
auto spriteGlowFrame = fmt::format("{}_{:02}_glow_001.png"_spr, file, tag);

spritePart->setBatchNode(nullptr);
spritePart->setDisplayFrame(spriteFrameCache->spriteFrameByName(spriteFrame.c_str()));
if (auto secondSprite = static_cast<CCSprite*>(m_secondArray->objectAtIndex(i))) {
if (auto secondSprite = static_cast<CCSprite*>(robot->m_secondArray->objectAtIndex(i))) {
secondSprite->setBatchNode(nullptr);
secondSprite->setDisplayFrame(spriteFrameCache->spriteFrameByName(sprite2Frame.c_str()));
secondSprite->setPosition(spritePart->getContentSize() / 2);
}

auto glowChild = static_cast<CCSprite*>(m_glowSprite->getChildren()->objectAtIndex(i));
auto glowChild = static_cast<CCSprite*>(robot->m_glowSprite->getChildren()->objectAtIndex(i));
glowChild->setBatchNode(nullptr);
glowChild->setDisplayFrame(spriteFrameCache->spriteFrameByName(spriteGlowFrame.c_str()));

if (spritePart == m_headSprite) {
if (spritePart == robot->m_headSprite) {
auto extraFrame = spriteFrameCache->spriteFrameByName(spriteExtraFrame.c_str());
auto hasExtra = MoreIcons::doesExist(extraFrame);
if (hasExtra) {
if (m_extraSprite) m_extraSprite->setDisplayFrame(extraFrame);
if (robot->m_extraSprite) {
robot->m_extraSprite->setBatchNode(nullptr);
robot->m_extraSprite->setDisplayFrame(extraFrame);
}
else {
m_extraSprite = CCSprite::createWithSpriteFrame(extraFrame);
m_headSprite->addChild(m_extraSprite, 2);
robot->m_extraSprite = CCSprite::createWithSpriteFrame(extraFrame);
robot->m_headSprite->addChild(robot->m_extraSprite, 2);
}
m_extraSprite->setPosition(spritePart->getContentSize() / 2);
robot->m_extraSprite->setPosition(spritePart->getContentSize() / 2);
}
m_extraSprite->setVisible(hasExtra);
robot->m_extraSprite->setVisible(hasExtra);
}
}
}

void MIRobotSprite::useCustomSprite() {
if (m_iconType == IconType::Robot) useCustomRobot(Mod::get()->getSavedValue<std::string>("robot", ""));
else if (m_iconType == IconType::Spider) useCustomSpider(Mod::get()->getSavedValue<std::string>("spider", ""));
void MIRobotSprite::useCustomSprite(GJRobotSprite* robot, bool dual) {
if (robot->m_iconType == IconType::Robot) useCustomRobot(robot, Mod::get()->getSavedValue<std::string>(MoreIcons::getDual("robot", dual), ""));
else if (robot->m_iconType == IconType::Spider) useCustomSpider(robot, Mod::get()->getSavedValue<std::string>(MoreIcons::getDual("spider", dual), ""));
}

void MIRobotSprite::useCustomRobot(std::string robotFile) {
void MIRobotSprite::useCustomRobot(GJRobotSprite* robot, std::string robotFile) {
if (robotFile.empty() || !MoreIcons::hasRobot(robotFile)) return;
setTexture(CCTextureCache::get()->textureForKey(MoreIcons::ROBOT_TEXTURES[robotFile].c_str()));
useCustom(robotFile);
robot->setBatchNode(nullptr);
robot->setTexture(CCTextureCache::get()->textureForKey(MoreIcons::ROBOT_TEXTURES[robotFile].c_str()));
useCustom(robot, robotFile);
}

void MIRobotSprite::useCustomSpider(std::string spiderFile) {
void MIRobotSprite::useCustomSpider(GJRobotSprite* spider, std::string spiderFile) {
if (spiderFile.empty() || !MoreIcons::hasSpider(spiderFile)) return;
setTexture(CCTextureCache::get()->textureForKey(MoreIcons::SPIDER_TEXTURES[spiderFile].c_str()));
useCustom(spiderFile);
spider->setBatchNode(nullptr);
spider->setTexture(CCTextureCache::get()->textureForKey(MoreIcons::SPIDER_TEXTURES[spiderFile].c_str()));
useCustom(spider, spiderFile);
}
Loading

0 comments on commit 4df9abb

Please sign in to comment.