diff --git a/README.md b/README.md new file mode 100644 index 0000000..1a456b8 --- /dev/null +++ b/README.md @@ -0,0 +1,3 @@ +# libBeatsaber + +a small Library to read and write beatsaber level. diff --git a/include/beatsaber-impl/beatlevelimpl.h b/include/beatsaber-impl/beatlevelimpl.h new file mode 100644 index 0000000..bddb1c0 --- /dev/null +++ b/include/beatsaber-impl/beatlevelimpl.h @@ -0,0 +1,41 @@ +#pragma once + +#include "beatlevel.h" + +#include + +using json = nlohmann::json; + +namespace Beatsaber { + +class BeatLevelImpl : public BeatLevel, protected std::enable_shared_from_this { +protected: + std::weak_ptr parent; + + Difficulty::Difficulty dif; + int32_t diffRank; + std::string filename; + + double njs; + double nso; + + const json& base; + +public: + BeatLevelImpl(std::weak_ptr p, const json& j); + virtual ~BeatLevelImpl(); + + virtual Difficulty::Difficulty getDifficulty() const override; + virtual int32_t getDifficultyRank() const override; + virtual std::string getFilename() const override; + virtual double getNoteJumpSpeed() const override; // in m + virtual double getNoteStartOffset() const override; + virtual std::string getCustomData() const override; + + //TODO: get level content + + virtual std::shared_ptr getBeatSet() const override; + virtual std::shared_ptr getBeatMap() const override; +}; + +} \ No newline at end of file diff --git a/include/beatsaber-impl/beatmapimpl.h b/include/beatsaber-impl/beatmapimpl.h index ee498dd..c944361 100644 --- a/include/beatsaber-impl/beatmapimpl.h +++ b/include/beatsaber-impl/beatmapimpl.h @@ -2,6 +2,7 @@ #include "beatmap.h" +#include #include #include "beatset.h" @@ -10,7 +11,7 @@ using json = nlohmann::json; namespace Beatsaber { -class BeatMapImpl : public BeatMap { +class BeatMapImpl : public BeatMap, protected std::enable_shared_from_this { protected: const std::string path; diff --git a/include/beatsaber-impl/beatsetimpl.h b/include/beatsaber-impl/beatsetimpl.h index ce33561..3e58549 100644 --- a/include/beatsaber-impl/beatsetimpl.h +++ b/include/beatsaber-impl/beatsetimpl.h @@ -6,18 +6,21 @@ using json = nlohmann::json; namespace Beatsaber { -class BeatSetImpl : public BeatSet { +class BeatSetImpl : public BeatSet, protected std::enable_shared_from_this { protected: + std::weak_ptr parent; BeatmapCharacteristic::BeatmapCharacteristic characteristic; + public: - BeatSetImpl(const json& j); + BeatSetImpl(std::weak_ptr p, const json& j); BeatSetImpl(const BeatSetImpl& c) = default; BeatSetImpl() = default; virtual ~BeatSetImpl(); - virtual BeatmapCharacteristic::BeatmapCharacteristic getCharacteristic() const; + virtual BeatmapCharacteristic::BeatmapCharacteristic getCharacteristic() const override; + virtual std::shared_ptr getBeatMap() const override; }; } \ No newline at end of file diff --git a/include/beatsaber/beatlevel.h b/include/beatsaber/beatlevel.h new file mode 100644 index 0000000..61c5a1e --- /dev/null +++ b/include/beatsaber/beatlevel.h @@ -0,0 +1,33 @@ +#pragma once + +#include +#include + +#include "difficulties.h" + +namespace Beatsaber { + +//fwd +class BeatSet; +class BeatMap; + +class BeatLevel { +public: + + virtual ~BeatLevel() {} + + virtual Difficulty::Difficulty getDifficulty() const = 0; + virtual int32_t getDifficultyRank() const = 0; + virtual std::string getFilename() const = 0; + virtual double getNoteJumpSpeed() const = 0; // in m + virtual double getNoteStartOffset() const = 0; + virtual std::string getCustomData() const = 0; + + //TODO: get level content + + virtual std::shared_ptr getBeatSet() const = 0; // parent + virtual std::shared_ptr getBeatMap() const = 0; // grandparent + +}; + +} \ No newline at end of file diff --git a/include/beatsaber/beatmap.h b/include/beatsaber/beatmap.h index e6c82cd..2d30e88 100644 --- a/include/beatsaber/beatmap.h +++ b/include/beatsaber/beatmap.h @@ -6,15 +6,12 @@ #include #include "beatmapcharacteristic.h" +#include "beatlevel.h" + #include "beatset.h" namespace Beatsaber { -class BeatLevel { -public: - -}; - class BeatMap { public: virtual ~BeatMap() {} diff --git a/include/beatsaber/beatset.h b/include/beatsaber/beatset.h index 0501a57..9168738 100644 --- a/include/beatsaber/beatset.h +++ b/include/beatsaber/beatset.h @@ -1,15 +1,21 @@ #pragma once +#include #include "beatmapcharacteristic.h" +#include "beatlevel.h" namespace Beatsaber { +//fwd decl. +class BeatMap; + class BeatSet { public: virtual ~BeatSet() {} virtual BeatmapCharacteristic::BeatmapCharacteristic getCharacteristic() const = 0; + virtual std::shared_ptr getBeatMap() const = 0; }; } \ No newline at end of file diff --git a/include/beatsaber/difficulties.h b/include/beatsaber/difficulties.h index 95ecc48..1dc3f13 100644 --- a/include/beatsaber/difficulties.h +++ b/include/beatsaber/difficulties.h @@ -12,5 +12,10 @@ namespace Beatsaber { EXPERT, EXPERTP, }; + + const std::string difficultyName[] {"None", "Easy", "Normal", "Hard", "Expert", "ExpertPlus"}; + const std::uint8_t difficultyNameSize = sizeof(difficultyName)/sizeof(std::string); + + Difficulty getByString(const std::string& str); } } \ No newline at end of file diff --git a/src/beatlevel.cpp b/src/beatlevel.cpp new file mode 100644 index 0000000..b5c6857 --- /dev/null +++ b/src/beatlevel.cpp @@ -0,0 +1,59 @@ +#include "beatlevelimpl.h" + +#include + +#include "beatset.h" + +namespace Beatsaber { + +BeatLevelImpl::BeatLevelImpl(std::weak_ptr p, const json& j) : parent(p), base(j) { + dif = Difficulty::getByString(j.value("_difficulty", "")); + diffRank = j.value("_difficultyRank", 0); + filename = j.value("_beatmapFilename", ""); + njs = j.value("_noteJumpMovementSpeed", -1); + nso = j.value("_noteJumpStartBeatOffset", 0); + + //load level content + if(!filename.empty()) { + + } +} + +BeatLevelImpl::~BeatLevelImpl() {} + +Difficulty::Difficulty BeatLevelImpl::getDifficulty() const { + return dif; +} + +int32_t BeatLevelImpl::getDifficultyRank() const { + return diffRank; +} + +std::string BeatLevelImpl::getFilename() const { + return filename; +} + +double BeatLevelImpl::getNoteJumpSpeed() const { + return njs; +} + +double BeatLevelImpl::getNoteStartOffset() const { + return nso; +} + +std::string BeatLevelImpl::getCustomData() const { + if(base.contains("_customData")) { + return base["_customData"].dump(); + } + return ""; +} + +std::shared_ptr BeatLevelImpl::getBeatSet() const { + return parent.lock(); +} + +std::shared_ptr BeatLevelImpl::getBeatMap() const { + return parent.lock()->getBeatMap(); +} + +} \ No newline at end of file diff --git a/src/beatmap.cpp b/src/beatmap.cpp index cef2930..a8916d6 100644 --- a/src/beatmap.cpp +++ b/src/beatmap.cpp @@ -24,7 +24,7 @@ bool BeatMapImpl::load() { //load all the beatsets for(const json& jsonbeatset : beatsets) { - beatSets.push_back(std::make_shared(jsonbeatset)); + beatSets.push_back(std::make_shared(shared_from_this(), jsonbeatset)); } } @@ -98,7 +98,10 @@ std::string BeatMapImpl::get360EnvName() const { } std::string BeatMapImpl::getCustomData() const { - return infobase["_customData"].dump(); + if(infobase.contains("_customData")) { + return infobase["_customData"].dump(); + } + return ""; } const std::vector>& BeatMapImpl::getBeatSets() const { diff --git a/src/beatset.cpp b/src/beatset.cpp index 036847a..61f3a91 100644 --- a/src/beatset.cpp +++ b/src/beatset.cpp @@ -4,7 +4,7 @@ namespace Beatsaber { -BeatSetImpl::BeatSetImpl(const json& j) : characteristic(BeatmapCharacteristic::getByString(j["_beatmapCharacteristicName"])) { +BeatSetImpl::BeatSetImpl(std::weak_ptr p, const json& j) : parent(p), characteristic(BeatmapCharacteristic::getByString(j["_beatmapCharacteristicName"])) { } BeatSetImpl::~BeatSetImpl() {} @@ -13,4 +13,8 @@ BeatmapCharacteristic::BeatmapCharacteristic BeatSetImpl::getCharacteristic() co return characteristic; } +std::shared_ptr BeatSetImpl::getBeatMap() const { + return parent.lock(); +} + } \ No newline at end of file diff --git a/src/enums.cpp b/src/enums.cpp index 0f5c2dd..8fe0a05 100644 --- a/src/enums.cpp +++ b/src/enums.cpp @@ -1,4 +1,5 @@ #include "beatmapcharacteristic.h" +#include "difficulties.h" namespace Beatsaber { namespace BeatmapCharacteristic { @@ -12,5 +13,16 @@ BeatmapCharacteristic getByString(const std::string& str) { return BeatmapCharacteristic::NONE; } +} + +namespace Difficulty { +Difficulty getByString(const std::string& str) { + for(uint8_t i = 0; i < difficultyNameSize; ++i) { + if(str == difficultyName[i]) { //TODO equals ignore Case + return (Difficulty) i; + } + } + return Difficulty::NONE; +} } } \ No newline at end of file diff --git a/tests/main.cpp b/tests/main.cpp index 0b179c5..371c6d2 100644 --- a/tests/main.cpp +++ b/tests/main.cpp @@ -4,8 +4,12 @@ #include "beatmap.h" //tests +int difficulties_test(); +int characteristics_test(); -test_t tests[] = {NULL}; +test_t tests[] = { + difficulties_test, characteristics_test, + NULL}; int main(int argc, char** argv) { diff --git a/tests/test.h b/tests/test.h index 890d25b..fb492f1 100644 --- a/tests/test.h +++ b/tests/test.h @@ -6,6 +6,7 @@ #define TESTDATA "./tests/data/" #define ASSERT(BED, ERR) if(!(BED)) { std::cout << __FILE__ << ":" << __LINE__ << " " << ERR << std::endl; return TESTFAILED; } -// #define ASSERT(BED) ASSERT(BED, "") +#define CMPASSERTE(A, B, ERR) if( !((A) == (B))) { std::cout << __FILE__ << ":" << __LINE__ << " is: \"" << (A) << "\" should: \"" << (B) << "\""<< std::endl; return TESTFAILED; } +#define CMPASSERT(A, B) CMPASSERTE(A, B, "") typedef int (*test_t)(); diff --git a/tests/testenums.cpp b/tests/testenums.cpp new file mode 100644 index 0000000..dfd5c31 --- /dev/null +++ b/tests/testenums.cpp @@ -0,0 +1,38 @@ +#include "test.h" + +#include "difficulties.h" +#include "beatmapcharacteristic.h" + +int difficulties_test() { + + using d = Beatsaber::Difficulty::Difficulty; + using namespace Beatsaber::Difficulty; + + CMPASSERT(d::EASY, getByString("Easy")); + CMPASSERT(d::NORMAL, getByString("Normal")); + + CMPASSERT(d::NONE, getByString("")); + CMPASSERT(d::NONE, getByString("abc")); + + CMPASSERT(d::HARD, getByString("Hard")); + CMPASSERT(d::EXPERTP, getByString("ExpertPlus")); + + return TESTGOOD; +} + +int characteristics_test() { + + using c = Beatsaber::BeatmapCharacteristic::BeatmapCharacteristic; + using namespace Beatsaber::BeatmapCharacteristic; + + CMPASSERT(c::NONE, getByString("")); + CMPASSERT(c::NONE, getByString("abc")); + + CMPASSERT(c::STANDARD, getByString("Standard")); + CMPASSERT(c::ONESABER, getByString("OneSaber")); + CMPASSERT(c::NOARROWS, getByString("NoArrows")); + CMPASSERT(c::DEGREE90, getByString("90Degree")); + CMPASSERT(c::DEGREE360, getByString("360Degree")); + + return TESTGOOD; +} \ No newline at end of file