diff --git a/changelog.md b/changelog.md index 63f0a51..83880a7 100644 --- a/changelog.md +++ b/changelog.md @@ -1,3 +1,7 @@ +# v1.5.1 +- Added "Copy Song ID" button (suggested by [Akashnil](https://discord.com/users/1068096599701590056)). This button only appears when using songs you've downloaded from Newgrounds or the Music Library. NONGs will not return a song ID. +- Added "Blacklist Song" button (suggested by [AlphaQuata](https://discord.com/users/766876726566846505)). +- Fix a bug where Playlist Mode would ignore the in-game "Menu Music" toggle if that was disabled. # v1.5.0 - Added "Playlist Mode" (suggested by [TheKevineer](https://discord.com/users/633040761256017963)). This feature is incredibly unstable, especially outside of Windows. I have done everything I could to keep its behavior consistent between Windows, macOS, and Android, but any crashes/issues from this feature are either beyond my control or have been acknowledged during beta testing without an obvious/more immediate fix. - Added "Remember Last Menu Loop" (suggested by [HexCodesGMD](https://discord.com/users/1222327935315218506)). diff --git a/mod.json b/mod.json index 0216733..be29e03 100644 --- a/mod.json +++ b/mod.json @@ -40,9 +40,21 @@ "type": "bool", "default": false }, + "enableCopySongID": { + "name": "\"Copy Song ID\" Button", + "description": "Original idea by Akashnil.\n\nEnables the copy Song ID in the main menu.\n\nIf \"Use Custom Songs Instead\" is enabled, this button will copy the song name instead.", + "type": "bool", + "default": true + }, "enableShuffleButton": { "name": "Shuffle Button", - "description": "Enables the shuffle button in the main menu.\n\nTo clarify: This button is not the same feature as \"Shuffle Mode\", although it *can* work with \"Shuffle Mode\" enabled. The button only changes the current menu loop to a different song *when pressed*.", + "description": "Enables the shuffle button in the main menu.\n\nUsing this button is not the same feature as enabling \"Playlist Mode\", although it *can* work with \"Playlist Mode\" enabled. This button only changes the menu loop to a different song *when pressed*, instead of when a song finishes.", + "type": "bool", + "default": true + }, + "enableBlacklistButton": { + "name": "Blacklist Button", + "description": "Original idea by AlphaQuata.\n\nEnables the blacklist button in the main menu.\n\nUsing this button prevents a song from being chosen as a menu loop, and chooses a new menu loop song.", "type": "bool", "default": true }, diff --git a/resources/copy-btn-sprite-original.png b/resources/copy-btn-sprite-original.png new file mode 100644 index 0000000..e920961 Binary files /dev/null and b/resources/copy-btn-sprite-original.png differ diff --git a/resources/copy-btn-sprite.png b/resources/copy-btn-sprite.png new file mode 100644 index 0000000..63a25c0 Binary files /dev/null and b/resources/copy-btn-sprite.png differ diff --git a/src/MenuLayer.cpp b/src/MenuLayer.cpp index b7e866a..c5db1c4 100644 --- a/src/MenuLayer.cpp +++ b/src/MenuLayer.cpp @@ -25,6 +25,9 @@ class $modify(MenuLayerMLHook, MenuLayer) { if (Utils::getBool("enableNotification") && Utils::getBool("enableNewNotification")) MenuLayerMLHook::addRegenButton(); + if (Utils::getBool("enableCopySongID")) + MenuLayerMLHook::addCopyButton(); + return true; } @@ -71,4 +74,23 @@ class $modify(MenuLayerMLHook, MenuLayer) { if (Utils::getBool("enableNotification")) Utils::generateNotification(); } + + void addCopyButton() { + auto menu = getChildByID("right-side-menu"); + + auto btn = CCMenuItemSpriteExtra::create( + CircleButtonSprite::create(CCSprite::create("copy-btn-sprite.png"_spr)), + this, + menu_selector(MenuLayerMLHook::onCopyButton) + ); + btn->setID("copy-button"_spr); + + menu->addChild(btn); + menu->updateLayout(); + } + + void onCopyButton(CCObject*) { + Utils::copyCurrentSongName(); + Notification::create("[MLR] Current song name copied!", NotificationIcon::None, Mod::get()->getSettingValue("notificationTime")); + } }; \ No newline at end of file diff --git a/src/SongManager.cpp b/src/SongManager.cpp index 163b475..4fde011 100644 --- a/src/SongManager.cpp +++ b/src/SongManager.cpp @@ -48,6 +48,7 @@ bool SongManager::isOriginalMenuLoop() { } void SongManager::update(float dt) { + if (!GameManager::sharedState()->getGameVariable("0122")) return; auto fmod = FMODAudioEngine::get(); if (!Utils::getBool("playlistMode") || GJBaseGameLayer::get() || m_isMenuLoop || m_songs.size() < 2 || !fmod) return; // geode::log::info("channelIsPlaying: {}", fmod->isMusicPlaying(0)); diff --git a/src/Utils.cpp b/src/Utils.cpp index d1922af..c530e9c 100644 --- a/src/Utils.cpp +++ b/src/Utils.cpp @@ -2,6 +2,12 @@ #include "ui/PlayingCard.hpp" #include "Utils.hpp" #include +#include + +static std::regex m_songEffectRegex(R"(.*(?:\\|\/)(\S+)\.(mp3|ogg|wav|flac|oga))", std::regex::optimize | std::regex::icase); // see https://regex101.com/r/CqvIvI/1. +static const std::regex m_geodeAudioRegex(R"(((?!\S+geode)(?:\\|\/)(?:([a-z0-9\-_]+\.[a-z0-9\-_]+)(?:\\|\/))([\S ]+)\.(mp3|ogg|wav|flac|oga))$)", std::regex::optimize | std::regex::icase); // see https://regex101.com/r/0b9rY1/1. +static const std::regex m_possiblyJukeboxRegex(R"(.*.[\\\/]([\S]+))", std::regex::optimize | std::regex::icase); // see https://regex101.com/r/Brmwbs/1. +static const int m_desiredIndexForFileName = 1; // easier place to change index int Utils::randomIndex(int size) { // select a random item from the vector and return the path @@ -52,6 +58,7 @@ void Utils::setNewSong() { } void Utils::playlistModeNewSong() { + if (!GameManager::sharedState()->getGameVariable("0122")) return; if (!Utils::getBool("playlistMode")) { return Utils::setNewSong(); } @@ -74,7 +81,7 @@ void Utils::playlistModeNewSong() { } // create notif card stuff -void Utils::makeNewCard(std::string notifString) { +void Utils::makeNewCard(const std::string& notifString) { if (auto oldCard = Utils::findCardRemotely()) { oldCard->removeMeAndCleanup(); } @@ -163,4 +170,37 @@ void Utils::playlistModePLAndEPL() { auto gjbgl = GJBaseGameLayer::get(); if (gjbgl) { return; } Utils::playlistModeNewSong(); +} + +void Utils::copyCurrentSongName() { + std::string currentSongName = SongManager::get().getCurrentSong(); + std::smatch match; + std::smatch geodeMatch; + std::smatch jukeboxMatch; + std::string result = ""; + currentSongName = std::regex_replace(currentSongName, std::regex(R"(com\.geode\.launcher\/)"), ""); // android is cring, original is [ "com\.geode\.launcher\/" ] + currentSongName = fmt::format("/{}", currentSongName); // adding an extra slash to get it working on all possible paths. this is because combo burst does some stuff under the hood i am too scared to look at and i don't want to define more regex than necessary. + geode::log::info("path after: {}", currentSongName); + if (currentSongName.find("geode") != std::string::npos && (currentSongName.find("mods") != std::string::npos || currentSongName.find("config") != std::string::npos)) { + if (std::regex_search(currentSongName, geodeMatch, m_geodeAudioRegex)) { + result = geodeMatch[geodeMatch.size() - 2].str(); + if (std::regex_search(result, jukeboxMatch, m_possiblyJukeboxRegex)) { + result = jukeboxMatch[jukeboxMatch.size() - 1].str(); + } + } else { + result = "Something went wrong..."; + } + } else if (std::regex_match(currentSongName, match, m_songEffectRegex)) { + if (std::regex_search(currentSongName, geodeMatch, m_geodeAudioRegex)) { + result = geodeMatch[geodeMatch.size() - 2].str(); + if (std::regex_search(result, jukeboxMatch, m_possiblyJukeboxRegex)) { + result = jukeboxMatch[jukeboxMatch.size() - 1].str(); + } + } else { + result = match[m_desiredIndexForFileName].str(); + } + } else { + result = currentSongName; + } + geode::utils::clipboard::write(result); } \ No newline at end of file diff --git a/src/Utils.hpp b/src/Utils.hpp index 6cdb6e3..665617f 100644 --- a/src/Utils.hpp +++ b/src/Utils.hpp @@ -1,4 +1,5 @@ #pragma once +#include class Utils { public: @@ -10,7 +11,8 @@ class Utils { static cocos2d::CCNode* findCardRemotely(); static void setNewSong(); static void playlistModeNewSong(); - static void makeNewCard(std::string); + static void makeNewCard(const std::string &); static void generateNotification(); static void playlistModePLAndEPL(); + static void copyCurrentSongName(); }; \ No newline at end of file