Skip to content

Commit

Permalink
Merge pull request #63 from HJfod/offset-next-free
Browse files Browse the repository at this point in the history
Color and group offsets for "Next Free"
  • Loading branch information
Fleeym authored Oct 12, 2023
2 parents 463bb25 + 78583a2 commit 35ded60
Show file tree
Hide file tree
Showing 6 changed files with 418 additions and 0 deletions.
1 change: 1 addition & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ file(GLOB SOURCES
src/features/VisibilityToggle/*.cpp
src/features/BetterScaling/*.cpp
src/features/StartPosSwitcher/*.cpp
src/features/OffsetNextFree/*.cpp
src/features/*.cpp
src/other/*.cpp
src/*.cpp
Expand Down
26 changes: 26 additions & 0 deletions src/Features/OffsetNextFree/OffsetManager.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
#pragma once

#include <Geode/Geode.hpp>

using namespace geode::prelude;

class OffsetManager : public CCObject {
protected:
inline static OffsetManager* s_instance = nullptr;

public:
size_t m_groupOffset = 0;
size_t m_colorOffset = 0;
static OffsetManager* get() {
if (!s_instance) {
s_instance = new OffsetManager;
if (s_instance) {
return s_instance;
}
CC_SAFE_DELETE(s_instance);
return nullptr;
}

return s_instance;
}
};
206 changes: 206 additions & 0 deletions src/Features/OffsetNextFree/OffsetNextFree.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,206 @@
#include <Geode/Geode.hpp>
#include <Geode/modify/CustomizeObjectLayer.hpp>
#include <Geode/modify/SetGroupIDLayer.hpp>
#include <Geode/modify/LevelEditorLayer.hpp>

#include "OffsetNextFreePopup.hpp"
#include "OffsetManager.hpp"

using namespace geode::prelude;

class $modify(LevelEditorLayer) {
int getNextColorChannel() {
std::array<bool, 1000> usedColors = this->getUsedColors();
auto offset = OffsetManager::get()->m_colorOffset;
for (int i = 1; i < 1000; i++) {
if (!usedColors[i] && i >= offset) {
return i;
}
}
return 999;
}

int getNextFreeGroupID(CCArray* p0) {
auto objects = this->getAllObjects();
auto offset = OffsetManager::get()->m_groupOffset;
std::array<bool, 1000> usedGroups = this->getUsedGroups(CCArrayExt<GameObject*>(objects));
for (size_t i = 1; i < 1000; i++) {
if (!usedGroups[i] && i >= offset) {
return i;
}
}
return 999;
}

std::array<bool, 1000> getUsedGroups(CCArrayExt<GameObject*> objects) {
std::array<bool, 1000> ret;
std::fill(ret.begin(), ret.end(), false);
for (auto object : objects) {
for (short id : object->getGroupIDs()) {
ret[id] = true;
}
}

return ret;
}

std::array<bool, 1000> getUsedColors() {
std::array<bool, 1000> ret;
std::fill(ret.begin(), ret.end(), false);
for (auto object : CCArrayExt<GameObject*>(m_objects)) {
if (object->m_baseColor) {
int colorID = 0;
if (object->m_baseColor->m_colorID == 0) {
colorID = object->m_baseColor->m_defaultColorID;
} else {
colorID = object->m_baseColor->m_colorID;
}

if (colorID < 1000) {
ret[colorID] = true;
}
}

if (object->m_detailColor) {
int colorID = 0;
if (object->m_detailColor->m_colorID == 0) {
colorID = object->m_detailColor->m_defaultColorID;
} else {
colorID = object->m_detailColor->m_colorID;
}

if (colorID < 1000) {
ret[colorID] = true;
}
}
}
auto effectManager = GJEffectManager::get();
for (auto colorAction : effectManager->m_colorActionsForColor) {
if (!colorAction) {
continue;
}
ccColor3B white = {255, 255, 255};
bool isDefaultColor = colorAction->m_fromColor == white &&
colorAction->m_targetColor == white &&
colorAction->m_duration == 0;

if (isDefaultColor || colorAction->m_colorID > 999) {
continue;
}

ret[colorAction->m_colorID] = true;
}

return ret;
}

bool colorExists(int colorID) {
bool ret = false;
for (auto object : CCArrayExt<GameObject*>(m_objects)) {
if (object->m_baseColor) {
if (
(object->m_baseColor->m_colorID == 0 &&
object->m_baseColor->m_defaultColorID == colorID) ||
object->m_baseColor->m_colorID == colorID
) {
ret = true;
break;
}
}
if (object->m_detailColor) {
if (
(object->m_detailColor->m_colorID == 0 &&
object->m_detailColor->m_defaultColorID == colorID) ||
object->m_detailColor->m_colorID == colorID
) {
ret = true;
break;
}
}
}
return ret;
}
};

class $modify(OffsetCustomizeObjectLayer, CustomizeObjectLayer) {
bool init(GameObject* target, CCArray* targets) {
if (!CustomizeObjectLayer::init(target, targets)) {
return false;
}
auto offset = OffsetManager::get()->m_colorOffset;
std::string sprite;
if (offset == 0) {
sprite = "GJ_button_04.png";
} else {
sprite = "GJ_button_02.png";
}

auto spr = ButtonSprite::create(std::to_string(offset).c_str(), 20, true, "goldFont.fnt", sprite.c_str(), 25, 0.6f);
auto button = CCMenuItemSpriteExtra::create(
spr,
this,
menu_selector(OffsetCustomizeObjectLayer::openOffsetPopup)
);
button->setID("offset-button"_spr);
auto menu = static_cast<CCMenu*>(m_mainLayer->getChildByID("next-free-menu"));
menu->addChild(button);
menu->updateLayout();

return true;
}

void openOffsetPopup(CCObject* sender) {
OffsetNextFreePopup::create(OffsetType::Color, this)->show();
}
};

class $modify(OffsetSetGroupIDLayer, SetGroupIDLayer) {
bool init(GameObject* object, CCArray* objects) {
if (!SetGroupIDLayer::init(object, objects)) {
return false;
}

auto menu = getChildOfType<CCMenu>(this->m_mainLayer, 0);
auto offset = OffsetManager::get()->m_groupOffset;
std::string sprite;
if (offset == 0) {
sprite = "GJ_button_04.png";
} else {
sprite = "GJ_button_02.png";
}

auto spr = ButtonSprite::create(std::to_string(offset).c_str(), 20, true, "goldFont.fnt", sprite.c_str(), 25, 0.6f);
auto button = CCMenuItemSpriteExtra::create(
spr,
this,
menu_selector(OffsetSetGroupIDLayer::openOffsetPopup)
);
button->setID("offset-button"_spr);
menu->addChild(button);
button->setPosition(-85.f, 175.f);

// This is some high level badassery
for (auto object : CCArrayExt<CCNode*>(menu->getChildren())) {
auto buttonSprite = getChildOfType<ButtonSprite>(object, 0);
if (!buttonSprite) {
continue;
}

auto label = getChildOfType<CCLabelBMFont>(buttonSprite, 0);
if (!label) {
continue;
}

std::string labelStr = label->getString();
if (labelStr == "Next Free") {
object->setPositionX(-140.f);
}
}

return true;
}

void openOffsetPopup(CCObject* sender) {
OffsetNextFreePopup::create(OffsetType::Group, this)->show();
}
};
146 changes: 146 additions & 0 deletions src/Features/OffsetNextFree/OffsetNextFreePopup.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,146 @@
#include "OffsetNextFreePopup.hpp"

bool OffsetNextFreePopup::setup(OffsetType offsetType, FLAlertLayer* parent) {
this->setTitle("Setup Offset");
m_offsetType = offsetType;
m_parent = parent;
auto pos = CCDirector::sharedDirector()->getWinSize() / 2;
size_t offset = 0;

switch (offsetType) {
case OffsetType::Color:
offset = OffsetManager::get()->m_colorOffset;
break;
case OffsetType::Group:
offset = OffsetManager::get()->m_groupOffset;
break;
}

auto bg = CCScale9Sprite::create("square02b_001.png", { 0.0f, 0.0f, 80.0f, 80.0f });
bg->setScale(0.5f);
bg->setColor({ 0, 0, 0 });
bg->setOpacity(100);
bg->setContentSize({ 115.0f, 75.0f });
bg->setPosition(pos);
bg->setID("offset-input-bg"_spr);
m_mainLayer->addChild(bg);

auto input = CCTextInputNode::create(60.0f, 30.0f, "0", "bigFont.fnt");
input->setPosition(pos);
input->setLabelPlaceholderColor({ 120, 120, 120 });
input->setAllowedChars("0123456789");
input->m_maxLabelLength = 4;
input->setScale(0.7f);
input->setID("offset-input"_spr);
if (offset != 0) {
input->setString(std::to_string(offset).c_str());
}
m_offsetInput = input;
m_mainLayer->addChild(input);

auto center = CCDirector::sharedDirector()->getWinSize() / 2;

auto menu = CCMenu::create();
menu->setID("offset-menu"_spr);
auto spr = ButtonSprite::create("Apply", 50, true, "goldFont.fnt", "GJ_button_01.png", 30, 1.f);
auto okButton = CCMenuItemSpriteExtra::create(
spr,
this,
menu_selector(OffsetNextFreePopup::onClose)
);
okButton->setID("ok-button"_spr);
okButton->setPositionY(-50.f);
menu->addChild(okButton);

if (offset != 0) {
auto spr2 = CCSprite::createWithSpriteFrameName("GJ_trashBtn_001.png");
spr2->setScale(0.6f);
auto clearButton = CCMenuItemSpriteExtra::create(
spr2,
this,
menu_selector(OffsetNextFreePopup::onClear)
);
clearButton->setID("clear-button"_spr);
clearButton->setPosition(-65.f, -50.f);
menu->addChild(clearButton);
}

m_mainLayer->addChild(menu);
return true;
}

void OffsetNextFreePopup::onClose(CCObject* sender) {
this->updateOffset();
this->updateParentButton();
switch (m_offsetType) {
case OffsetType::Color: {
auto parent = static_cast<CustomizeObjectLayer*>(m_parent);
parent->onNextColorChannel(sender);
} break;
case OffsetType::Group: {
auto parent = static_cast<SetGroupIDLayer*>(m_parent);
parent->onNextGroupID1(sender);
} break;
}
Popup::onClose(sender);
}

size_t OffsetNextFreePopup::getOffsetFromInput() {
size_t offset = 0;
std::string strValue = m_offsetInput->getString();
if (strValue.length() != 0) {
try {
offset = std::stoi(strValue);
} catch (...) {}
}
if (offset > 999) {
offset = 999;
}

return offset;
}

void OffsetNextFreePopup::updateOffset() {
auto offset = this->getOffsetFromInput();
switch (m_offsetType) {
case OffsetType::Color:
OffsetManager::get()->m_colorOffset = offset;
break;
case OffsetType::Group:
OffsetManager::get()->m_groupOffset = offset;
break;
}
}

void OffsetNextFreePopup::updateParentButton() {
size_t offset;
switch (m_offsetType) {
case OffsetType::Color:
offset = OffsetManager::get()->m_colorOffset;
break;
case OffsetType::Group:
offset = OffsetManager::get()->m_groupOffset;
break;
}
std::string sprite;
if (offset == 0) {
sprite = "GJ_button_04.png";
} else {
sprite = "GJ_button_02.png";
}

auto spr = ButtonSprite::create(std::to_string(offset).c_str(), 20, true, "goldFont.fnt", sprite.c_str(), 25, 0.6f);
CCMenu* menu;
menu = static_cast<CCMenu*>(m_parent->m_mainLayer->getChildByID("next-free-menu"));
if (!menu) {
menu = getChildOfType<CCMenu>(m_parent->m_mainLayer, 0);
}
auto button = static_cast<CCMenuItemSpriteExtra*>(menu->getChildByID("offset-button"_spr));
button->setNormalImage(spr);
}

void OffsetNextFreePopup::onClear(CCObject* sender) {
m_offsetInput->setString("0");

this->onClose(sender);
}
Loading

0 comments on commit 35ded60

Please sign in to comment.