Skip to content

Commit 585979b

Browse files
authored
Merge pull request #87 from Fleeym/feat/refactor-and-verified-songs
add verified for level songs and refactor nong list and cells
2 parents 285b00a + 3994631 commit 585979b

26 files changed

+1167
-871
lines changed

jukebox/jukebox/events/start_download.cpp

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,11 @@ namespace jukebox {
88

99
namespace event {
1010

11-
StartDownload::StartDownload(IndexSongMetadata* song, int gdId)
12-
: m_song(song), m_gdId(gdId) {}
11+
StartDownload::StartDownload(int gdSongID, std::string uniqueID)
12+
: m_gdSongID(gdSongID), m_uniqueID(uniqueID) {}
1313

14-
IndexSongMetadata* StartDownload::song() { return m_song; }
15-
int StartDownload::gdId() { return m_gdId; }
14+
int StartDownload::gdSongID() { return m_gdSongID; }
15+
std::string StartDownload::uniqueID() { return m_uniqueID; }
1616

1717
} // namespace event
1818

jukebox/jukebox/events/start_download.hpp

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -10,14 +10,14 @@ namespace event {
1010

1111
class StartDownload final : public geode::Event {
1212
protected:
13-
index::IndexSongMetadata* m_song = nullptr;
14-
int m_gdId;
13+
int m_gdSongID;
14+
std::string m_uniqueID;
1515

1616
public:
17-
StartDownload(index::IndexSongMetadata* song, int gdId);
17+
StartDownload(int gdSongID, std::string uniqueID);
1818

19-
index::IndexSongMetadata* song();
20-
int gdId();
19+
int gdSongID();
20+
std::string uniqueID();
2121
};
2222

2323
} // namespace event

jukebox/jukebox/hooks/custom_song_widget.cpp

Lines changed: 99 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
#include <optional>
55
#include <sstream>
66

7+
#include <Geode/cocos/actions/CCActionInterval.h>
78
#include <Geode/cocos/cocoa/CCGeometry.h>
89
#include <Geode/cocos/cocoa/CCObject.h>
910
#include <Geode/cocos/label_nodes/CCLabelBMFont.h>
@@ -14,6 +15,7 @@
1415
#include <Geode/binding/CCMenuItemSpriteExtra.hpp>
1516
#include <Geode/binding/CustomSongWidget.hpp>
1617
#include <Geode/binding/FLAlertLayer.hpp>
18+
#include <Geode/binding/GJGameLevel.hpp>
1719
#include <Geode/binding/GameManager.hpp>
1820
#include <Geode/binding/SongInfoObject.hpp>
1921
#include <Geode/loader/Event.hpp>
@@ -23,6 +25,7 @@
2325
#include <Geode/modify/LevelInfoLayer.hpp> // IWYU pragma: keep
2426
#include <Geode/ui/GeodeUI.hpp>
2527
#include <Geode/ui/Layout.hpp>
28+
#include <Geode/ui/SimpleAxisLayout.hpp>
2629
#include <Geode/utils/cocos.hpp>
2730

2831
#include <jukebox/events/song_state_changed.hpp>
@@ -43,13 +46,67 @@ class $modify(JBSongWidget, CustomSongWidget) {
4346
std::string sfxIds = "";
4447
bool firstRun = true;
4548
bool searching = false;
49+
CCSprite* sprRays = nullptr;
50+
CCMenuItemSpriteExtra* btnDisc = nullptr;
4651
std::unordered_map<int, Nongs*> assetNongData;
4752
EventListener<NongManager::MultiAssetSizeTask> m_multiAssetListener;
4853
std::unique_ptr<
4954
EventListener<EventFilter<jukebox::event::SongStateChanged>>>
5055
m_songStateListener;
56+
std::optional<int> levelID = std::nullopt;
5157
};
5258

59+
std::optional<int> getLevelID() { return m_fields->levelID; }
60+
61+
void setLevelID(int levelID) {
62+
m_fields->levelID = levelID;
63+
64+
this->setVerifiedUI();
65+
}
66+
67+
// Set the disc to show the song is verified.
68+
// The function only works if there is a verified song.
69+
void setVerifiedUI() {
70+
if (!m_fields->levelID.has_value()) {
71+
return;
72+
}
73+
std::vector<int> songIDs;
74+
// m_songs size + SongInfoObject id
75+
songIDs.reserve(m_songs.size() + 1);
76+
for (auto const& kv : m_songs) {
77+
songIDs.push_back(kv.first);
78+
}
79+
80+
int id = m_songInfoObject->m_songID;
81+
if (m_isRobtopSong) {
82+
id++;
83+
id = -id;
84+
}
85+
songIDs.push_back(id);
86+
87+
bool isVerified =
88+
!NongManager::get()
89+
.getVerifiedNongsForLevel(m_fields->levelID.value(), songIDs)
90+
.empty();
91+
if (!isVerified) {
92+
return;
93+
}
94+
95+
if (m_fields->sprRays) {
96+
m_fields->sprRays->setVisible(true);
97+
}
98+
if (m_fields->btnDisc) {
99+
CCSprite* sprDiscGold =
100+
CCSprite::createWithSpriteFrameName("JB_PinDiscGold.png"_spr);
101+
if (m_isMusicLibrary) {
102+
sprDiscGold->setScale(0.5f);
103+
} else {
104+
sprDiscGold->setScale(0.7f);
105+
}
106+
m_fields->btnDisc->setSprite(sprDiscGold);
107+
}
108+
}
109+
53110
bool init(SongInfoObject* songInfo, CustomSongDelegate* songDelegate,
54111
bool showSongSelect, bool showPlayMusic, bool showDownload,
55112
bool isRobtopSong, bool unk, bool isMusicLibrary, int unkInt) {
@@ -107,7 +164,8 @@ class $modify(JBSongWidget, CustomSongWidget) {
107164

108165
std::optional optPath = nongs->active()->path();
109166

110-
if (auto found = m_songs.find(nongs->songID()); found != m_songs.end()) {
167+
if (auto found = m_songs.find(nongs->songID());
168+
found != m_songs.end()) {
111169
if (!optPath) {
112170
found->second = false;
113171
} else {
@@ -476,14 +534,13 @@ class $modify(JBSongWidget, CustomSongWidget) {
476534
float labelScale = label->getScale();
477535
m_fields->labelMenu->addChild(btn);
478536
m_fields->labelMenu->setAnchorPoint(m_songLabel->getAnchorPoint());
479-
m_fields->labelMenu->setContentSize(
480-
m_songLabel->getScaledContentSize());
537+
m_fields->labelMenu->setContentSize(m_songLabel->getContentSize());
538+
m_fields->labelMenu->setScale(m_songLabel->getScale());
481539
m_fields->labelMenu->setPosition(m_songLabel->getPosition());
482540
m_fields->labelMenu->setLayout(
483-
RowLayout::create()
484-
->setDefaultScaleLimits(0.1f, 1.0f)
485-
->setAxisAlignment(AxisAlignment::Start));
486-
m_fields->labelMenu->updateLayout();
541+
SimpleRowLayout::create()
542+
->setMainAxisScaling(AxisScaling::Scale)
543+
->setCrossAxisScaling(AxisScaling::Scale));
487544
m_songLabel->setVisible(false);
488545
this->addChild(m_fields->labelMenu);
489546
} else {
@@ -504,27 +561,48 @@ class $modify(JBSongWidget, CustomSongWidget) {
504561
m_fields->pinMenu = CCMenu::create();
505562
m_fields->pinMenu->setID("nong-menu"_spr);
506563

507-
CCSprite* spr =
564+
CCSprite* sprRays =
565+
CCSprite::createWithSpriteFrameName("JB_PinDiscRays.png"_spr);
566+
CCSprite* sprDisc =
508567
CCSprite::createWithSpriteFrameName("JB_PinDisc.png"_spr);
509568
if (m_isMusicLibrary) {
510-
spr->setScale(0.5f);
569+
sprDisc->setScale(0.5f);
570+
sprRays->setScale(0.5f * 1.15f);
511571
} else {
512-
spr->setScale(0.7f);
572+
sprDisc->setScale(0.7f);
573+
sprRays->setScale(0.7f * 1.15f);
513574
}
514-
spr->setID("nong-pin"_spr);
575+
sprDisc->setID("nong-pin"_spr);
515576

516-
CCMenuItemSpriteExtra* btn = CCMenuItemSpriteExtra::create(
517-
spr, this, menu_selector(JBSongWidget::addNongLayer));
518-
btn->setID("nong-button"_spr);
577+
CCMenuItemSpriteExtra* btnDisc = CCMenuItemSpriteExtra::create(
578+
sprDisc, this, menu_selector(JBSongWidget::addNongLayer));
579+
btnDisc->setID("nong-button"_spr);
580+
581+
sprRays->setID("nong-pin-rays"_spr);
582+
sprRays->setZOrder(-1);
583+
sprRays->setAnchorPoint({0.5f, 0.5f});
584+
sprRays->setVisible(false);
585+
586+
m_fields->sprRays = sprRays;
587+
m_fields->btnDisc = btnDisc;
588+
589+
m_fields->pinMenu->addChildAtPosition(sprRays, Anchor::Center);
590+
591+
static constexpr float rotationDuration = 80.0f;
592+
CCRepeatForever* rotateAction = CCRepeatForever::create(
593+
CCRotateBy::create(rotationDuration, 360));
594+
sprRays->runAction(rotateAction);
519595

520596
m_fields->pinMenu->setAnchorPoint({0.5f, 0.5f});
521597
m_fields->pinMenu->ignoreAnchorPointForPosition(false);
522-
m_fields->pinMenu->addChild(btn);
523-
m_fields->pinMenu->setContentSize(btn->getScaledContentSize());
524-
m_fields->pinMenu->setLayout(RowLayout::create());
598+
m_fields->pinMenu->addChildAtPosition(btnDisc, Anchor::Center);
599+
m_fields->pinMenu->setContentSize(btnDisc->getScaledContentSize());
600+
m_fields->pinMenu->setLayout(AnchorLayout::create());
525601

526602
m_fields->pinMenu->setPosition(pos);
527603
this->addChild(m_fields->pinMenu);
604+
605+
this->setVerifiedUI();
528606
}
529607
}
530608

@@ -554,7 +632,8 @@ class $modify(JBSongWidget, CustomSongWidget) {
554632
} else {
555633
ids.push_back(id);
556634
}
557-
auto layer = NongDropdownLayer::create(ids, this, id);
635+
auto layer =
636+
NongDropdownLayer::create(ids, this, id, this->getLevelID());
558637
// based robtroll
559638
layer->setZOrder(106);
560639
layer->show();
@@ -578,6 +657,8 @@ class $modify(JBLevelInfoLayer, LevelInfoLayer) {
578657
popup->m_scene = this;
579658
popup->show();
580659
}
660+
static_cast<JBSongWidget*>(this->m_songWidget)
661+
->setLevelID(m_level->m_levelID.value());
581662
return true;
582663
}
583664
};

jukebox/jukebox/managers/index_manager.cpp

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -363,13 +363,13 @@ Result<> IndexManager::downloadSong(int gdSongID, const std::string& uniqueID) {
363363
}
364364
}
365365

366-
// Look in indexes otherwise
367-
if (!m_nongsForId.contains(gdSongID)) {
368-
return Err("Can't download nong for id {}. No index songs found.",
369-
gdSongID);
370-
}
371-
366+
// If not uniqueID not found in local songs, search in indexes
372367
if (!found) {
368+
if (!m_nongsForId.contains(gdSongID)) {
369+
return Err("Can't download nong for id {}. No local or index songs found.",
370+
gdSongID);
371+
}
372+
373373
std::vector<IndexSongMetadata*> songs = m_nongsForId[gdSongID];
374374
for (IndexSongMetadata* s : songs) {
375375
if (s->uniqueID != uniqueID) {
@@ -544,9 +544,9 @@ void IndexManager::onDownloadFinish(
544544
}
545545

546546
ListenerResult IndexManager::onDownloadStart(event::StartDownload* e) {
547-
Result<> res = this->downloadSong(e->gdId(), e->song()->uniqueID);
547+
Result<> res = this->downloadSong(e->gdSongID(), e->uniqueID());
548548
if (res.isErr()) {
549-
event::SongDownloadFailed(e->gdId(), e->song()->uniqueID,
549+
event::SongDownloadFailed(e->gdSongID(), e->uniqueID(),
550550
res.unwrapErr())
551551
.post();
552552
}

jukebox/jukebox/managers/nong_manager.cpp

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
#include <memory>
55
#include <optional>
66
#include <string>
7+
#include <string_view>
78
#include <system_error>
89
#include <unordered_map>
910
#include <utility>
@@ -38,6 +39,38 @@ std::optional<Nongs*> NongManager::getNongs(int songID) {
3839
return m_manifest.m_nongs[songID].get();
3940
}
4041

42+
bool NongManager::isNongVerifiedForLevelSong(int levelID, int songID, std::string_view uniqueID) {
43+
// List the verified nongs for the given level and song
44+
std::vector<std::string> verifiedNongs = NongManager::get().getVerifiedNongsForLevel(
45+
levelID,
46+
{songID}
47+
);
48+
return std::find(verifiedNongs.begin(), verifiedNongs.end(), uniqueID) != verifiedNongs.end();
49+
}
50+
51+
std::vector<std::string> NongManager::getVerifiedNongsForLevel(int levelID, std::vector<int> songIDs) {
52+
std::vector<std::string> verifiedNongs;
53+
54+
for (const int songID : songIDs) {
55+
auto nongs = this->getNongs(songID);
56+
57+
if (!nongs.has_value()) {
58+
continue;
59+
}
60+
61+
// For each indexSong, check if it contains the given levelID in its verifiedLevelIDs field.
62+
for (auto indexSong : nongs.value()->indexSongs()) {
63+
auto& ids = indexSong->verifiedLevelIDs;
64+
65+
if (std::find(ids.begin(), ids.end(), levelID) != ids.end()) {
66+
verifiedNongs.push_back(indexSong->uniqueID);
67+
}
68+
}
69+
}
70+
71+
return verifiedNongs;
72+
}
73+
4174
int NongManager::getCurrentManifestVersion() { return m_manifest.m_version; }
4275

4376
int NongManager::getStoredIDCount() { return m_manifest.m_nongs.size(); }

jukebox/jukebox/managers/nong_manager.hpp

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
#include <filesystem>
44
#include <memory>
55
#include <optional>
6+
#include <string_view>
67

78
#include <Geode/Result.hpp>
89
#include <Geode/binding/SongInfoObject.hpp>
@@ -97,6 +98,34 @@ class NongManager {
9798
*/
9899
std::optional<Nongs*> getNongs(int songID);
99100

101+
/**
102+
* Returns all the uniqueIDs of nongs that are verified for the given level ID
103+
*
104+
* @param levelID the id of the level
105+
* @param songIDs list of all the song ids to check their nongs
106+
* @return List of all uniqueIDs of nongs that are verified for the given level ID
107+
*/
108+
std::vector<std::string> getVerifiedNongsForLevel(int levelID, std::vector<int> songIDs);
109+
110+
/**
111+
* Returns whether the nong is verified for the a song in a level
112+
*
113+
* @param levelID the id of the level
114+
* @param songID the id of a song in the level
115+
* @param uniqueID the id of the nong
116+
* @return Boolean for whether the nong is verified
117+
*/
118+
bool isNongVerifiedForLevelSong(int levelID, int songID, std::string_view uniqueID);
119+
120+
/**
121+
* Checks if the given level has a verified song for any of the given song IDs
122+
*
123+
* @param levelID the id of the level
124+
* @param songIDs list of all the song ids to check
125+
* @return Whether one of the songs has a verified nong for the level
126+
*/
127+
bool isNongVerified(int levelID, std::vector<int> songIDs);
128+
100129
/**
101130
* Formats a size in bytes to a x.xxMB string
102131
*

jukebox/jukebox/nong/index.hpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,7 @@ struct IndexSongMetadata final {
8888
std::optional<std::string> url;
8989
std::optional<std::string> ytId;
9090
std::vector<int> songIDs;
91+
std::vector<int> verifiedLevelIDs;
9192
int startOffset = 0;
9293
IndexMetadata* parentID;
9394
};

0 commit comments

Comments
 (0)