diff --git a/mod.json b/mod.json index f6e9371..3cc3e41 100644 --- a/mod.json +++ b/mod.json @@ -4,7 +4,7 @@ "win": "2.206", "android": "*" }, - "version": "v7.0.0-beta.3", + "version": "v7.0.0-beta.4", "id": "user95401.mainlevelseditor", "name": "Main Levels Editor", "developer": "user95401", diff --git a/src/_main.hpp b/src/_main.hpp index af9d160..36bb465 100644 --- a/src/_main.hpp +++ b/src/_main.hpp @@ -2,6 +2,8 @@ #include using namespace geode::prelude; +#include + //lol #define SETTING(type, key_name) Mod::get()->getSettingValue(key_name) @@ -121,4 +123,150 @@ inline auto jsonFromLevel(GJGameLevel* level) { value.try_set("m_songIDs", std::string(level->m_songIDs.data())); value.try_set("m_sfxIDs", std::string(level->m_sfxIDs.data())); return value; +} + +inline void updateLevelByJson(GJGameLevel* level) { + auto level_meta_file = levels_meta_path / fmt::format("{}.json", level->m_levelID.value()); + auto file_content = my_fs::read(level_meta_file); + //json val + auto value = matjson::parse("{}"); + //file parse + auto error = std::string(); + auto parse = matjson::parse(file_content, error); + if (parse.has_value()) value = parse.value(); + //setup level + levelFromJson(parse, level); + //setup json + value = jsonFromLevel(level); + //save json + std::ofstream(level_meta_file) << value.dump(matjson::TAB_INDENTATION); +} + +namespace MLE_UI { + inline auto DeleteButtonSprite() { + auto hi = geode::AccountButtonSprite::create( + CCSprite::createWithSpriteFrameName("edit_delBtn_001.png"), + AccountBaseColor::Gray + ); + hi->setScale(0.8f); + typeinfo_cast(hi->getChildren()->objectAtIndex(0))->setScale(1.1f); + return hi; + } + inline auto SettingsButtonSprite() { + auto hi = geode::AccountButtonSprite::create( + CCSprite::createWithSpriteFrameName("d_cogwheel_04_001.png"), + AccountBaseColor::Gray + ); + hi->setScale(0.8f); + typeinfo_cast(hi->getChildren()->objectAtIndex(0))->setScale(1.1f); + typeinfo_cast(hi->getChildren()->objectAtIndex(0))->setColor({ 20, 20, 20 }); + hi->addChild(typeinfo_cast(hi->getChildren()->objectAtIndex(0)));//make it darker + return hi; + } + class LevelConfigPopup : public FLAlertLayer, FLAlertLayerProtocol, TextInputDelegate { + public: + GJGameLevel* m_level; + std::function m_onSave = []() {}; + inline static auto create(GJGameLevel* for_level = LevelTools::getLevel(1, 0)) { + auto rtn = new LevelConfigPopup; + rtn->init( + rtn, + "Level Meta Config", + "\n \n \n \n \n \n \n \n ", + "Close", "Save", 352.000f, 0, 290.000f, 1.f + ); + rtn->setID("LevelConfigPopup"); + rtn->m_level = for_level; + rtn->customSetup(); + return rtn; + } + inline void customSetup() { + //form_box + auto form_box = CCLayer::create(); + if (form_box) { + //base sets + form_box->setID("form_box"); + form_box->setPosition(CCPoint(0.f, 116.f)); + form_box->setContentSize(CCSize(255.f, 175.f)); + form_box->ignoreAnchorPointForPosition(false); + //add + this->m_buttonMenu->addChild(form_box); + //layout + auto layout = ColumnLayout::create(); + layout->setAxisReverse(1); + layout->setCrossAxisOverflow(0); + form_box->setLayout(layout); + } + //addInputs + auto addInput = [this, form_box](auto label = "", auto id = "", CommonFilter commonFilter = CommonFilter::Any) { + //labelNode + auto labelNode = CCLabelBMFont::create(label, "bigFont.fnt"); + labelNode->setID(id + std::string("/label")); + form_box->addChild(labelNode); + //inputNode + auto inputNode = TextInput::create(form_box->getContentWidth(), label, "gjFont41.fnt"); + inputNode->getInputNode()->setID(id); + inputNode->setCommonFilter(commonFilter); + inputNode->setDelegate(this); + form_box->addChild(inputNode); + //upd + form_box->updateLayout(); + }; + addInput("Name", "m_levelName"); + addInput("Audio Track", "m_audioTrack", CommonFilter::Int); + addInput("Difficulty", "m_difficulty", CommonFilter::Int); + addInput("Stars", "m_stars", CommonFilter::Int); + loadInputs(); + } + inline void loadInputs() { + if (not this->m_level) return; + auto m_levelName = typeinfo_cast(this->getChildByIDRecursive("m_levelName")); + auto m_audioTrack = typeinfo_cast(this->getChildByIDRecursive("m_audioTrack")); + auto m_difficulty = typeinfo_cast(this->getChildByIDRecursive("m_difficulty")); + auto m_stars = typeinfo_cast(this->getChildByIDRecursive("m_stars")); + if (m_levelName) m_levelName->setString(fmt::format("{}", this->m_level->m_levelName.data())); + if (m_audioTrack) m_audioTrack->setString(fmt::format("{}", this->m_level->m_audioTrack)); + if (m_difficulty) m_difficulty->setString(fmt::format("{}", (int)this->m_level->m_difficulty)); + if (m_stars) m_stars->setString(fmt::format("{}", this->m_level->m_stars.value())); + } + inline void applyInputs() { + if (not this->m_level) return; + auto m_levelName = typeinfo_cast(this->getChildByIDRecursive("m_levelName")); + auto m_audioTrack = typeinfo_cast(this->getChildByIDRecursive("m_audioTrack")); + auto m_difficulty = typeinfo_cast(this->getChildByIDRecursive("m_difficulty")); + auto m_stars = typeinfo_cast(this->getChildByIDRecursive("m_stars")); + if (m_levelName) m_level->m_levelName = m_levelName->getString(); + if (m_audioTrack) m_level->m_audioTrack = utils::numFromString(m_audioTrack->getString().data()).value_or(m_level->m_audioTrack); + if (m_difficulty) m_level->m_difficulty = (GJDifficulty)utils::numFromString(m_difficulty->getString().data()).value_or((int)m_level->m_difficulty); + if (m_stars) m_level->m_stars = utils::numFromString(m_stars->getString().data()).value_or(m_level->m_stars.value()); + } + inline void textChanged(CCTextInputNode* p0) { + log::debug("{}({}) id: {}", __FUNCTION__, p0, p0->getID()); + if (p0->getID() == "m_difficulty") { + auto difficulty = utils::numFromString(p0->getString().data()).value_or(0); + GJDifficultySprite* difficultyPrev; + if (difficultyPrev = typeinfo_cast(this->getChildByIDRecursive("difficultyPrev"))); + else { + difficultyPrev = GJDifficultySprite::create(difficulty, GJDifficultyName::Short); + difficultyPrev->setAnchorPoint(CCPoint(0.f, 0.f)); + difficultyPrev->setPosition(CCPoint(260.f, 0.f)); + difficultyPrev->setScale(1.2f); + difficultyPrev->setID("difficultyPrev"); + p0->getParent()->addChild(difficultyPrev); + } + difficultyPrev->updateDifficultyFrame(difficulty, GJDifficultyName::Short); + } + } + inline void FLAlert_Clicked(FLAlertLayer* p0, bool p1) { + if (not p1) return; + applyInputs(); + //json + auto value = jsonFromLevel(this->m_level); + //save json + auto level_meta_file = levels_meta_path / fmt::format("{}.json", m_level->m_levelID.value()); + std::ofstream(level_meta_file) << value.dump(matjson::TAB_INDENTATION); + //call custom func + this->m_onSave(); + }; + }; } \ No newline at end of file diff --git a/src/control_ui.cpp b/src/control_ui.cpp index 620b510..6052a48 100644 --- a/src/control_ui.cpp +++ b/src/control_ui.cpp @@ -2,13 +2,14 @@ #include class $modify(LevelPageExt, LevelPage) { - void updateUI(float) { - if (auto pCCMenu = this->getChildByIDRecursive("menu_for_level_page"_spr)) { - pCCMenu->setVisible(this->m_level->m_levelID >= 1); - pCCMenu->setZOrder(this->m_level->m_levelID); - } - } void editLevel(CCObject*) { + auto ae = MLE_UI::LevelConfigPopup::create(this->m_level); + ae->m_onSave = [ae]() { + CCDirector::get()->pushScene(CCTransitionCrossFade::create( + 0.15f, LevelSelectLayer::scene(ae->m_level->m_levelID.value() - 1) + )); + }; + ae->show(); } void deleteLevel(CCObject*) { auto currentLevel = this->m_level; @@ -25,27 +26,20 @@ class $modify(LevelPageExt, LevelPage) { ); geode::createQuickPopup("Delete Level", content, "No", "Yes", [this, levelFile, levelMetaFile, currentID, currentLevel](void*, bool asd) { if (!asd) return; - //level setup + //remove meta std::remove(levelMetaFile.string().data()); - //data store + //remove data std::remove(levelFile.string().data()); - //_PagesSetupPatch - { - //update settings here - Mod::get()->setSettingValue("max_id", SETTING(int64_t, "max_id") - 1); - }; - //_AudioTracks - { - //idk lol - }; - //asshell + //update settings here + Mod::get()->setSettingValue("max_id", SETTING(int64_t, "max_id") - 1); + //change ids of all next levels { - //level setup + //level meta for (int levelID = 0; levelID < 500; levelID++) { if (levelID > currentID and levelID < 500) { auto rn1 = levels_meta_path / fmt::format("{}.json", levelID); auto rn2 = levels_meta_path / fmt::format("{}.json", levelID - 1); - my_fs::rename(rn1, rn2); + if (my_fs::exists(rn1)) my_fs::rename(rn1, rn2); }; } //level data @@ -53,54 +47,46 @@ class $modify(LevelPageExt, LevelPage) { if (levelID > currentID) { auto rn1 = levels_path / fmt::format("{}.txt", levelID); auto rn2 = levels_path / fmt::format("{}.txt", levelID - 1); - my_fs::rename(rn1, rn2); + if (my_fs::exists(rn1)) my_fs::rename(rn1, rn2); } } } - auto newLevelSelectLayerScene = LevelSelectLayer::scene(currentID - 1); - CCDirector::get()->pushScene(CCTransitionCrossFade::create(0.1f, newLevelSelectLayerScene)); - }); + //reset layer + CCDirector::get()->pushScene(CCTransitionCrossFade::create( + 0.15f, LevelSelectLayer::scene(currentID - 1) + )); + }); } - bool init(GJGameLevel* p0) { + $override bool init(GJGameLevel* p0) { auto rtn = LevelPage::init(p0); if (SETTING(bool, "ui")) { - this->schedule(schedule_selector(LevelPageExt::updateUI)); - CCMenuItemSpriteExtra* deleteLevel; - { - auto hi = geode::AccountButtonSprite::create( - CCSprite::createWithSpriteFrameName("edit_delBtn_001.png"), - AccountBaseColor::Gray - ); - hi->setScale(0.8f); - typeinfo_cast(hi->getChildren()->objectAtIndex(0))->setScale(1.1f); - deleteLevel = CCMenuItemSpriteExtra::create(hi, this, menu_selector(LevelPageExt::deleteLevel)); + CCMenuItemSpriteExtra* deleteLevel; { + deleteLevel = CCMenuItemSpriteExtra::create(MLE_UI::DeleteButtonSprite(), this, menu_selector(LevelPageExt::deleteLevel)); deleteLevel->setID("deleteLevel"_spr); deleteLevel->setPosition(CCPoint(190, 30)); deleteLevel->m_baseScale = 0.8f; deleteLevel->setScale(deleteLevel->m_baseScale); }; - CCMenuItemSpriteExtra* editLevel; - { - auto hi = geode::AccountButtonSprite::create( - CCSprite::createWithSpriteFrameName("d_cogwheel_04_001.png"), - AccountBaseColor::Gray - ); - hi->setScale(0.8f); - typeinfo_cast(hi->getChildren()->objectAtIndex(0))->setScale(1.1f); - typeinfo_cast(hi->getChildren()->objectAtIndex(0))->setColor({ 20, 20, 20 }); - hi->addChild(typeinfo_cast(hi->getChildren()->objectAtIndex(0)));//make it darker - editLevel = CCMenuItemSpriteExtra::create(hi, this, menu_selector(LevelPageExt::editLevel)); + CCMenuItemSpriteExtra* editLevel; { + editLevel = CCMenuItemSpriteExtra::create(MLE_UI::SettingsButtonSprite(), this, menu_selector(LevelPageExt::editLevel)); editLevel->setID("editLevel"_spr); editLevel->setPosition(CCPoint(190, 0)); editLevel->m_baseScale = 0.8f; editLevel->setScale(editLevel->m_baseScale); }; - auto levelMenu = getChildByIDRecursive("level-menu"); - { + if (auto levelMenu = getChildByIDRecursive("level-menu")) { levelMenu->addChild(deleteLevel); levelMenu->addChild(editLevel); }; } return rtn; }; + $override void updateDynamicPage(GJGameLevel* p0) { + LevelPage::updateDynamicPage(p0); + //my menu_for_level_page + if (auto pCCMenu = this->getChildByIDRecursive("menu_for_level_page"_spr)) { + pCCMenu->setVisible(p0->m_levelID >= 1); + pCCMenu->setZOrder(p0->m_levelID); + } + } }; \ No newline at end of file diff --git a/src/level_data.cpp b/src/level_data.cpp index d7cb75e..1aee45d 100644 --- a/src/level_data.cpp +++ b/src/level_data.cpp @@ -23,7 +23,7 @@ void Loaded() { }; #include class $modify(LoadingLayer) { - void loadAssets() { + $override void loadAssets() { if (m_loadStep == 0) Loaded(); LoadingLayer::loadAssets(); } @@ -32,7 +32,7 @@ class $modify(LoadingLayer) { //huh #include class $modify(PlayLayer) { - bool init(GJGameLevel * level, bool useReplay, bool dontCreateObjects) { + $override bool init(GJGameLevel * level, bool useReplay, bool dontCreateObjects) { auto oldID = level->m_levelID.value(); level->m_levelID = 999; //temp "Load Failed" bypass auto rtn = PlayLayer::init(level, useReplay, dontCreateObjects); @@ -43,7 +43,7 @@ class $modify(PlayLayer) { #include class $modify(LocalLevelManagerExt, LocalLevelManager) { - gd::string getMainLevelString(int p0) { + $override gd::string getMainLevelString(int p0) { //LocalLevelManager::getMainLevelString(p0); auto levelID = p0; //get data file path @@ -63,29 +63,14 @@ class $modify(LocalLevelManagerExt, LocalLevelManager) { #include class $modify(LevelTools) { - static void updateLevelByJson(GJGameLevel * level) { - auto level_meta_file = levels_meta_path / fmt::format("{}.json", level->m_levelID.value()); - auto file_content = my_fs::read(level_meta_file); - //json val - auto value = matjson::parse("{}"); - //file parse - auto error = std::string(); - auto parse = matjson::parse(file_content, error); - if (parse.has_value()) value = parse.value(); - //setup level - levelFromJson(parse, level); - //setup json - value = jsonFromLevel(level); - //save json - std::ofstream(level_meta_file) << value.dump(matjson::TAB_INDENTATION); - } - static GJGameLevel* getLevel(int levelID, bool dontGetLevelString) { + $override static GJGameLevel* getLevel(int levelID, bool dontGetLevelString) { auto level = LevelTools::getLevel(levelID, dontGetLevelString); //json meta updateLevelByJson(level); + level->m_isUnlocked = true; return level; }; - static bool NOT_NOW___verifyLevelIntegrity(gd::string p0, int p1) { + $override static bool NOT_NOW___verifyLevelIntegrity(gd::string p0, int p1) { //hooking error lol return 1; } diff --git a/src/level_listing.cpp b/src/level_listing.cpp index 826d9c3..4ece033 100644 --- a/src/level_listing.cpp +++ b/src/level_listing.cpp @@ -3,10 +3,10 @@ #include class $modify(BoomScrollLayerExt, BoomScrollLayer) { static BoomScrollLayer* create(cocos2d::CCArray* pages, int unk1, bool unk2, cocos2d::CCArray* unk3, DynamicScrollDelegate* delegate) { - log::debug( + /*log::debug( "\n{}(\ncocos2d::CCArray* {},\n int {}, bool {},\n cocos2d::CCArray* {},\n DynamicScrollDelegate* {}\n)\n", __FUNCTION__, pages, unk1, unk2, unk3, (CCObject*)delegate - ); + );*/ if (auto mainLevelsLayer = typeinfo_cast(delegate)) { //mainLevelsLayer->setRotation(12.f); //yeaa pages is standing for 3 level pages (dont touch them :D) @@ -18,7 +18,7 @@ class $modify(BoomScrollLayerExt, BoomScrollLayer) { int id = SETTING(int64_t, "start_id"); int max_id = SETTING(int64_t, "max_id"); for (id; id <= max_id; id++) - myLevelsArray->addObject(GameLevelManager::sharedState()->getMainLevel(id, 0)); + myLevelsArray->addObject(LevelTools::getLevel(id, 0)); //the_tower if (SETTING(bool, "the_tower")) myLevelsArray->addObject(unk3->objectAtIndex(unk3->count() - 2)); @@ -30,4 +30,18 @@ class $modify(BoomScrollLayerExt, BoomScrollLayer) { } return BoomScrollLayer::create(pages, unk1, unk2, unk3, delegate); } +}; + +#include +class $modify(LevelPage) { + $override void updateDynamicPage(GJGameLevel* p0) { + LevelPage::updateDynamicPage(p0); + //difficultySprite + if (auto difficultySprite = typeinfo_cast(this->getChildByIDRecursive("difficulty-sprite"))) { + std::string frameName = GJDifficultySprite::getDifficultyFrame((int)p0->m_difficulty, GJDifficultyName::Short).data(); + frameName = std::regex_replace(frameName, std::regex("difficulty"), "diffIcon"); + if (auto frame = CCSpriteFrameCache::get()->spriteFrameByName(frameName.data())) + difficultySprite->setDisplayFrame(frame); + } + } }; \ No newline at end of file