Compare commits
2 Commits
be3296acb9
...
fd6f908671
Author | SHA1 | Date |
---|---|---|
mrbesen | fd6f908671 | |
mrbesen | 37edb342fa |
31
Makefile
31
Makefile
|
@ -7,7 +7,7 @@
|
||||||
|
|
||||||
NAME = libBeatsaber.a
|
NAME = libBeatsaber.a
|
||||||
NAMETEST = test
|
NAMETEST = test
|
||||||
CFLAGS = -std=c++17 -O2 -pipe -Wall -Wextra -Wno-unused-parameter -Wpedantic -rdynamic
|
CFLAGS = -std=c++17 -O2 -pipe -Wall -Wextra -Wno-unused-parameter -Wpedantic -rdynamic -g
|
||||||
CXX = g++
|
CXX = g++
|
||||||
SRCF = src/
|
SRCF = src/
|
||||||
BUILDDIR = build/
|
BUILDDIR = build/
|
||||||
|
@ -20,25 +20,38 @@ INCLUDES = $(addprefix -I, $(INCFS))
|
||||||
LDFLAGS =
|
LDFLAGS =
|
||||||
|
|
||||||
SRCFILES = $(shell find $(SRCF) -name "*.cpp")
|
SRCFILES = $(shell find $(SRCF) -name "*.cpp")
|
||||||
OBJFILES = $(patsubst $(SRCF)%, $(BUILDDIR)%, $(patsubst %.cpp, %.o, $(SRCFILES))) $(LOGO)
|
OBJFILES = $(patsubst $(SRCF)%, $(BUILDDIR)%, $(patsubst %.cpp, %.o, $(SRCFILES)))
|
||||||
DEPFILES = $(wildcard $(DEPF)*.d)
|
DEPFILES = $(wildcard $(DEPF)*.d)
|
||||||
|
|
||||||
SOURCEDIRS = $(shell find $(SRCF) -type d -printf "%p/\n")
|
SOURCEDIRS = $(shell find $(SRCF) -type d -printf "%p/\n")
|
||||||
BUILDDIRS = $(patsubst $(SRCF)%, $(BUILDDIR)%, $(SOURCEDIRS))
|
BUILDDIRS = $(patsubst $(SRCF)%, $(BUILDDIR)%, $(SOURCEDIRS))
|
||||||
|
|
||||||
OBJFILESTEST = $(OBJFILES)
|
|
||||||
|
|
||||||
INCLUDES += $(addprefix -I, $(SOURCEDIRS))
|
INCLUDES += $(addprefix -I, $(SOURCEDIRS))
|
||||||
|
|
||||||
|
# FEATURES
|
||||||
|
|
||||||
|
# zipFile support
|
||||||
|
DEFINES += -DBEATSABERZIPSUPPORT=1
|
||||||
|
|
||||||
|
# link zipios dynamic
|
||||||
|
LDFLAGS += -lzipios
|
||||||
|
|
||||||
|
# OR link zipios static (path to static lib)
|
||||||
|
#OBJFILES += /usr/local/lib/libzipios.a
|
||||||
|
#LDFLAGS += -lz #libzlib is still required dynamic
|
||||||
|
|
||||||
|
|
||||||
|
OBJFILESTEST = $(OBJFILES)
|
||||||
|
|
||||||
all: $(NAME) runtest
|
all: $(NAME) runtest
|
||||||
|
|
||||||
$(NAME): | $(BUILDDIRS) $(DEPF) $(OBJFILES)
|
$(NAME): $(OBJFILES) | $(BUILDDIRS) $(DEPF)
|
||||||
@$(AR) rvs $@ $(filter %.o, $^)
|
@$(AR) rvs $@ $(filter %.o, $^)
|
||||||
|
|
||||||
$(BUILDDIR)%.o: $(SRCF)%.cpp
|
$(BUILDDIR)%.o: $(SRCF)%.cpp | $(BUILDDIRS) $(DEPF)
|
||||||
@echo "Compiling: $@"
|
@echo "Compiling: $@"
|
||||||
@$(CXX) $(CFLAGS) $(INCLUDES) $< -MM -MT $@ > $(DEPF)$(subst /,_,$*).d
|
@$(CXX) $(CFLAGS) $(DEFINES) $(INCLUDES) $< -MM -MT $@ > $(DEPF)$(subst /,_,$*).d
|
||||||
@$(CXX) -c -o $@ $(CFLAGS) $(INCLUDES) $<
|
@$(CXX) -c -o $@ $(CFLAGS) $(DEFINES) $(INCLUDES) $<
|
||||||
|
|
||||||
%/:
|
%/:
|
||||||
mkdir -p $@
|
mkdir -p $@
|
||||||
|
@ -51,7 +64,7 @@ clean:
|
||||||
|
|
||||||
$(NAMETEST): $(BUILDDIRS) $(DEPF) $(TESTF)*.cpp $(OBJFILESTEST) $(NAME)
|
$(NAMETEST): $(BUILDDIRS) $(DEPF) $(TESTF)*.cpp $(OBJFILESTEST) $(NAME)
|
||||||
@echo "Compiling tests"
|
@echo "Compiling tests"
|
||||||
@$(CXX) -o $@ $(filter %.o, $^) $(filter %.cpp, $^) $(filter %.a, $^) $(CFLAGS) $(INCLUDES) $(LDFLAGS)
|
@$(CXX) -o $@ $(filter %.o, $^) $(filter %.cpp, $^) $(filter %.a, $^) $(CFLAGS) $(DEFINES) $(INCLUDES) $(LDFLAGS)
|
||||||
|
|
||||||
runtest: $(NAMETEST)
|
runtest: $(NAMETEST)
|
||||||
@echo "Running tests"
|
@echo "Running tests"
|
||||||
|
|
|
@ -0,0 +1,3 @@
|
||||||
|
# libBeatsaber
|
||||||
|
|
||||||
|
a small Library to read and write beatsaber level.
|
|
@ -0,0 +1,43 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "beatlevel.h"
|
||||||
|
|
||||||
|
#include <nlohmann/json_fwd.hpp>
|
||||||
|
|
||||||
|
using json = nlohmann::json;
|
||||||
|
|
||||||
|
namespace Beatsaber {
|
||||||
|
|
||||||
|
class BeatLevelImpl : public BeatLevel, public std::enable_shared_from_this<BeatLevelImpl> {
|
||||||
|
protected:
|
||||||
|
std::weak_ptr<BeatSet> parent;
|
||||||
|
|
||||||
|
Difficulty::Difficulty dif;
|
||||||
|
int32_t diffRank;
|
||||||
|
std::string filename;
|
||||||
|
|
||||||
|
double njs;
|
||||||
|
double nso;
|
||||||
|
|
||||||
|
const json& base;
|
||||||
|
|
||||||
|
public:
|
||||||
|
BeatLevelImpl(std::weak_ptr<BeatSet> 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 void printDebug() const override;
|
||||||
|
|
||||||
|
virtual std::shared_ptr<BeatSet> getBeatSet() const override;
|
||||||
|
virtual std::shared_ptr<BeatMap> getBeatMap() const override;
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
|
@ -2,6 +2,7 @@
|
||||||
|
|
||||||
#include "beatmap.h"
|
#include "beatmap.h"
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
#include <nlohmann/json.hpp>
|
#include <nlohmann/json.hpp>
|
||||||
|
|
||||||
#include "beatset.h"
|
#include "beatset.h"
|
||||||
|
@ -10,7 +11,7 @@ using json = nlohmann::json;
|
||||||
|
|
||||||
namespace Beatsaber {
|
namespace Beatsaber {
|
||||||
|
|
||||||
class BeatMapImpl : public BeatMap {
|
class BeatMapImpl : public BeatMap, public std::enable_shared_from_this<BeatMapImpl> {
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
const std::string path;
|
const std::string path;
|
||||||
|
@ -49,8 +50,8 @@ public:
|
||||||
|
|
||||||
virtual void printDebug() const override;
|
virtual void printDebug() const override;
|
||||||
|
|
||||||
friend std::unique_ptr<BeatMap> BeatMap::loadFromFolder(const std::string& folderPath);
|
friend std::shared_ptr<BeatMap> BeatMap::loadFromFolder(const std::string& folderPath);
|
||||||
friend std::unique_ptr<BeatMap> BeatMap::loadFromZip(const std::string& zipPath);
|
friend std::shared_ptr<BeatMap> BeatMap::loadFromZip(const std::string& zipPath);
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,18 +6,24 @@ using json = nlohmann::json;
|
||||||
|
|
||||||
namespace Beatsaber {
|
namespace Beatsaber {
|
||||||
|
|
||||||
class BeatSetImpl : public BeatSet {
|
class BeatSetImpl : public BeatSet, public std::enable_shared_from_this<BeatSetImpl> {
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
|
std::weak_ptr<BeatMap> parent;
|
||||||
BeatmapCharacteristic::BeatmapCharacteristic characteristic;
|
BeatmapCharacteristic::BeatmapCharacteristic characteristic;
|
||||||
|
|
||||||
|
std::vector<std::shared_ptr<BeatLevel>> level;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
BeatSetImpl(const json& j);
|
BeatSetImpl(std::weak_ptr<BeatMap> p, const json& j);
|
||||||
BeatSetImpl(const BeatSetImpl& c) = default;
|
BeatSetImpl(const BeatSetImpl& c) = default;
|
||||||
BeatSetImpl() = default;
|
BeatSetImpl() = default;
|
||||||
virtual ~BeatSetImpl();
|
virtual ~BeatSetImpl();
|
||||||
|
|
||||||
virtual BeatmapCharacteristic::BeatmapCharacteristic getCharacteristic() const;
|
virtual void printDebug() const override;
|
||||||
|
|
||||||
|
virtual BeatmapCharacteristic::BeatmapCharacteristic getCharacteristic() const override;
|
||||||
|
virtual std::shared_ptr<BeatMap> getBeatMap() const override;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
|
@ -0,0 +1,20 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
|
#include <string>
|
||||||
|
#include <istream>
|
||||||
|
|
||||||
|
|
||||||
|
// this classes form a abstraction to read from folders and zipfiles the same way. Maybe add other sources too?
|
||||||
|
|
||||||
|
namespace Beatsaber {
|
||||||
|
|
||||||
|
//Interface
|
||||||
|
class FileReader {
|
||||||
|
public:
|
||||||
|
virtual ~FileReader() {}
|
||||||
|
|
||||||
|
virtual std::shared_ptr<std::istream> getFileStream(const std::string& filename) = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,38 @@
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "filereader.h"
|
||||||
|
|
||||||
|
#if BEATSABERZIPSUPPORT == 1
|
||||||
|
#include <zipios/zipfile.hpp>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
namespace Beatsaber {
|
||||||
|
|
||||||
|
//implementation for folders
|
||||||
|
class FolderReader : public FileReader {
|
||||||
|
protected:
|
||||||
|
std::string path;
|
||||||
|
|
||||||
|
public:
|
||||||
|
FolderReader(const std::string& path);
|
||||||
|
virtual ~FolderReader();
|
||||||
|
|
||||||
|
virtual std::shared_ptr<std::istream> getFileStream(const std::string& filename) override;
|
||||||
|
};
|
||||||
|
|
||||||
|
#if BEATSABERZIPSUPPORT == 1
|
||||||
|
//implementation for zipfiles
|
||||||
|
class ZipReader : public FileReader {
|
||||||
|
protected:
|
||||||
|
zipios::ZipFile file;
|
||||||
|
|
||||||
|
public:
|
||||||
|
ZipReader(const std::string& path);
|
||||||
|
virtual ~ZipReader();
|
||||||
|
|
||||||
|
virtual std::shared_ptr<std::istream> getFileStream(const std::string& filename) override;
|
||||||
|
};
|
||||||
|
#endif
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,35 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
|
#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 void printDebug() const = 0;
|
||||||
|
|
||||||
|
virtual std::shared_ptr<BeatSet> getBeatSet() const = 0; // parent
|
||||||
|
virtual std::shared_ptr<BeatMap> getBeatMap() const = 0; // grandparent
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
|
@ -6,15 +6,12 @@
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#include "beatmapcharacteristic.h"
|
#include "beatmapcharacteristic.h"
|
||||||
|
#include "beatlevel.h"
|
||||||
|
|
||||||
#include "beatset.h"
|
#include "beatset.h"
|
||||||
|
|
||||||
namespace Beatsaber {
|
namespace Beatsaber {
|
||||||
|
|
||||||
class BeatLevel {
|
|
||||||
public:
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
class BeatMap {
|
class BeatMap {
|
||||||
public:
|
public:
|
||||||
virtual ~BeatMap() {}
|
virtual ~BeatMap() {}
|
||||||
|
@ -43,8 +40,8 @@ public:
|
||||||
|
|
||||||
virtual void printDebug() const = 0;
|
virtual void printDebug() const = 0;
|
||||||
|
|
||||||
static std::unique_ptr<BeatMap> loadFromFolder(const std::string& folderPath);
|
static std::shared_ptr<BeatMap> loadFromFolder(const std::string& folderPath);
|
||||||
static std::unique_ptr<BeatMap> loadFromZip(const std::string& zipPath);
|
static std::shared_ptr<BeatMap> loadFromZip(const std::string& zipPath);
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -20,5 +20,7 @@ namespace Beatsaber {
|
||||||
const std::uint8_t characteristicsNameSize = sizeof(characteristicsName)/sizeof(std::string);
|
const std::uint8_t characteristicsNameSize = sizeof(characteristicsName)/sizeof(std::string);
|
||||||
|
|
||||||
BeatmapCharacteristic getByString(const std::string& str);
|
BeatmapCharacteristic getByString(const std::string& str);
|
||||||
|
|
||||||
|
const std::string& toString(BeatmapCharacteristic c);
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,15 +1,23 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
#include "beatmapcharacteristic.h"
|
#include "beatmapcharacteristic.h"
|
||||||
|
#include "beatlevel.h"
|
||||||
|
|
||||||
namespace Beatsaber {
|
namespace Beatsaber {
|
||||||
|
|
||||||
|
//fwd decl.
|
||||||
|
class BeatMap;
|
||||||
|
|
||||||
class BeatSet {
|
class BeatSet {
|
||||||
public:
|
public:
|
||||||
virtual ~BeatSet() {}
|
virtual ~BeatSet() {}
|
||||||
|
|
||||||
|
virtual void printDebug() const = 0;
|
||||||
|
|
||||||
virtual BeatmapCharacteristic::BeatmapCharacteristic getCharacteristic() const = 0;
|
virtual BeatmapCharacteristic::BeatmapCharacteristic getCharacteristic() const = 0;
|
||||||
|
virtual std::shared_ptr<BeatMap> getBeatMap() const = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
|
@ -12,5 +12,13 @@ namespace Beatsaber {
|
||||||
EXPERT,
|
EXPERT,
|
||||||
EXPERTP,
|
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);
|
||||||
|
|
||||||
|
const std::string& toString(Difficulty d);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
|
@ -0,0 +1,68 @@
|
||||||
|
#include "beatlevelimpl.h"
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
|
#include <nlohmann/json.hpp>
|
||||||
|
|
||||||
|
#include "beatset.h"
|
||||||
|
|
||||||
|
namespace Beatsaber {
|
||||||
|
|
||||||
|
BeatLevelImpl::BeatLevelImpl(std::weak_ptr<BeatSet> 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 "";
|
||||||
|
}
|
||||||
|
|
||||||
|
void BeatLevelImpl::printDebug() const {
|
||||||
|
std::cout <<
|
||||||
|
" Difficulty: " << Difficulty::toString(dif) << " (" << diffRank << ")"
|
||||||
|
<< "\n Filename: " << getFilename()
|
||||||
|
<< "\n njs: " << getNoteJumpSpeed() << " nso: " << getNoteStartOffset()
|
||||||
|
<< std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::shared_ptr<BeatSet> BeatLevelImpl::getBeatSet() const {
|
||||||
|
return parent.lock();
|
||||||
|
}
|
||||||
|
|
||||||
|
std::shared_ptr<BeatMap> BeatLevelImpl::getBeatMap() const {
|
||||||
|
return parent.lock()->getBeatMap();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -16,7 +16,6 @@ bool BeatMapImpl::load() {
|
||||||
try {
|
try {
|
||||||
info >> infobase;
|
info >> infobase;
|
||||||
|
|
||||||
|
|
||||||
//load the beatset
|
//load the beatset
|
||||||
const json& beatsets = infobase["_difficultyBeatmapSets"];
|
const json& beatsets = infobase["_difficultyBeatmapSets"];
|
||||||
if(beatsets.is_array()) {
|
if(beatsets.is_array()) {
|
||||||
|
@ -24,12 +23,14 @@ bool BeatMapImpl::load() {
|
||||||
|
|
||||||
//load all the beatsets
|
//load all the beatsets
|
||||||
for(const json& jsonbeatset : beatsets) {
|
for(const json& jsonbeatset : beatsets) {
|
||||||
beatSets.push_back(std::make_shared<BeatSetImpl>(jsonbeatset));
|
beatSets.push_back(std::make_shared<BeatSetImpl>(weak_from_this(), jsonbeatset));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
} catch(...) {} //catch any json errors
|
} catch(const nlohmann::detail::exception& e) { //catch any json errors
|
||||||
|
std::cout << "Could not Read BeatMap: " << e.what() << std::endl;
|
||||||
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -98,7 +99,10 @@ std::string BeatMapImpl::get360EnvName() const {
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string BeatMapImpl::getCustomData() const {
|
std::string BeatMapImpl::getCustomData() const {
|
||||||
return infobase["_customData"].dump();
|
if(infobase.contains("_customData")) {
|
||||||
|
return infobase["_customData"].dump();
|
||||||
|
}
|
||||||
|
return "";
|
||||||
}
|
}
|
||||||
|
|
||||||
const std::vector<std::shared_ptr<BeatSet>>& BeatMapImpl::getBeatSets() const {
|
const std::vector<std::shared_ptr<BeatSet>>& BeatMapImpl::getBeatSets() const {
|
||||||
|
@ -129,30 +133,40 @@ std::shared_ptr<BeatSet> BeatMapImpl::getBeatSet(BeatmapCharacteristic::BeatmapC
|
||||||
|
|
||||||
void BeatMapImpl::printDebug() const {
|
void BeatMapImpl::printDebug() const {
|
||||||
std::cout << "SongName: " << getSongName() << " - " << getSongAuthorName() << " (" << getSubName() << ")"
|
std::cout << "SongName: " << getSongName() << " - " << getSongAuthorName() << " (" << getSubName() << ")"
|
||||||
<< "\nMapper: " << getMapperName()
|
<< "\n Mapper: " << getMapperName()
|
||||||
<< "\nVersion: " << getVersion()
|
<< "\n Version: " << getVersion()
|
||||||
<< "\nBPM: " << getBPM() << " offset: " << getTimeOffset()
|
<< "\n BPM: " << getBPM() << " offset: " << getTimeOffset()
|
||||||
<< "\nSchuffle " << getSchuffle() << " period: " << getSchufflePeriod()
|
<< "\n Schuffle " << getSchuffle() << " period: " << getSchufflePeriod()
|
||||||
<< "\nPreviewStart: " << getPreviewStart() << " duration: " << getPreviewDuration()
|
<< "\n PreviewStart: " << getPreviewStart() << " duration: " << getPreviewDuration()
|
||||||
<< "\nSongFile: " << getSongFilename()
|
<< "\n SongFile: " << getSongFilename()
|
||||||
<< "\nImageFile: " << getImageFilename()
|
<< "\n ImageFile: " << getImageFilename()
|
||||||
<< "\nEnvName: " << getEnvName() << " 360Env: " << get360EnvName()
|
<< "\n EnvName: " << getEnvName() << " 360Env: " << get360EnvName()
|
||||||
<< "\ncustomData: " << getCustomData()
|
<< "\n customData: " << getCustomData()
|
||||||
<< "\nBeatSetCount: " << getBeatSetCount()
|
<< "\n BeatSetCount: " << getBeatSetCount()
|
||||||
<< std::endl;
|
<< std::endl;
|
||||||
|
|
||||||
|
for(auto it : beatSets) {
|
||||||
|
it->printDebug();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
std::unique_ptr<BeatMap> BeatMap::loadFromFolder(const std::string& folderPath) {
|
std::shared_ptr<BeatMap> BeatMap::loadFromFolder(const std::string& folderPath) {
|
||||||
auto map = std::make_unique<BeatMapImpl>(folderPath, false);
|
auto map = std::make_shared<BeatMapImpl>(folderPath, false);
|
||||||
if(!map->load()) return nullptr;
|
if(!map->load()) return nullptr;
|
||||||
return map;
|
return map;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::unique_ptr<BeatMap> BeatMap::loadFromZip(const std::string& zipPath) {
|
std::shared_ptr<BeatMap> BeatMap::loadFromZip(const std::string& zipPath) {
|
||||||
auto map = std::make_unique<BeatMapImpl>(zipPath, true);
|
#if BEATSABERZIPSUPPORT == 1
|
||||||
|
auto map = std::make_shared<BeatMapImpl>(zipPath, true);
|
||||||
if(!map->load()) return nullptr;
|
if(!map->load()) return nullptr;
|
||||||
return map;
|
return map;
|
||||||
|
#else
|
||||||
|
// Zip not supported
|
||||||
|
std::cerr << "Zip not supported" << std::endl;
|
||||||
|
return nullptr;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
|
@ -1,16 +1,47 @@
|
||||||
#include "beatsetimpl.h"
|
#include "beatsetimpl.h"
|
||||||
|
|
||||||
|
#include <iostream> //debug print
|
||||||
#include <nlohmann/json.hpp>
|
#include <nlohmann/json.hpp>
|
||||||
|
|
||||||
|
#include "beatlevelimpl.h"
|
||||||
|
|
||||||
namespace Beatsaber {
|
namespace Beatsaber {
|
||||||
|
|
||||||
BeatSetImpl::BeatSetImpl(const json& j) : characteristic(BeatmapCharacteristic::getByString(j["_beatmapCharacteristicName"])) {
|
BeatSetImpl::BeatSetImpl(std::weak_ptr<BeatMap> p, const json& j) : parent(p) {
|
||||||
|
try {
|
||||||
|
characteristic = BeatmapCharacteristic::getByString(j["_beatmapCharacteristicName"]);
|
||||||
|
|
||||||
|
//load level
|
||||||
|
const json& arr = j["_difficultyBeatmaps"];
|
||||||
|
if(arr.is_array()) {
|
||||||
|
level.reserve(arr.size());
|
||||||
|
std::cout << "Try to load: " << arr.size() << std::endl;
|
||||||
|
for(const json& beat : arr) {
|
||||||
|
level.push_back(std::make_shared<BeatLevelImpl>(weak_from_this(), beat));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch(std::exception& e) {
|
||||||
|
std::cout << "Could not read BeatSet: " << e.what() << std::endl;
|
||||||
|
characteristic = BeatmapCharacteristic::NONE;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
BeatSetImpl::~BeatSetImpl() {}
|
BeatSetImpl::~BeatSetImpl() {}
|
||||||
|
|
||||||
|
void BeatSetImpl::printDebug() const {
|
||||||
|
std::cout << " Characteristic: " << BeatmapCharacteristic::toString(characteristic) << std::endl;
|
||||||
|
|
||||||
|
for(auto it : level) {
|
||||||
|
it->printDebug();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
BeatmapCharacteristic::BeatmapCharacteristic BeatSetImpl::getCharacteristic() const {
|
BeatmapCharacteristic::BeatmapCharacteristic BeatSetImpl::getCharacteristic() const {
|
||||||
return characteristic;
|
return characteristic;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::shared_ptr<BeatMap> BeatSetImpl::getBeatMap() const {
|
||||||
|
return parent.lock();
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
|
@ -1,4 +1,5 @@
|
||||||
#include "beatmapcharacteristic.h"
|
#include "beatmapcharacteristic.h"
|
||||||
|
#include "difficulties.h"
|
||||||
|
|
||||||
namespace Beatsaber {
|
namespace Beatsaber {
|
||||||
namespace BeatmapCharacteristic {
|
namespace BeatmapCharacteristic {
|
||||||
|
@ -12,5 +13,29 @@ BeatmapCharacteristic getByString(const std::string& str) {
|
||||||
return BeatmapCharacteristic::NONE;
|
return BeatmapCharacteristic::NONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const std::string& toString(BeatmapCharacteristic c) {
|
||||||
|
uint8_t ic = (uint8_t) c;
|
||||||
|
if(ic >= characteristicsNameSize) return characteristicsName[0]; //none
|
||||||
|
return characteristicsName[ic];
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
const std::string& toString(Difficulty d) {
|
||||||
|
uint8_t id = (uint8_t) d;
|
||||||
|
if(id >= difficultyNameSize) return difficultyName[0]; //none
|
||||||
|
return difficultyName[id];
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -0,0 +1,34 @@
|
||||||
|
#include "filereaderimpl.h"
|
||||||
|
|
||||||
|
#include <fstream>
|
||||||
|
|
||||||
|
namespace Beatsaber {
|
||||||
|
|
||||||
|
|
||||||
|
FolderReader::FolderReader(const std::string& path) : path(path) {
|
||||||
|
// make path end with /
|
||||||
|
if(path.rfind('/') != path.size()-1)
|
||||||
|
this->path += "/";
|
||||||
|
}
|
||||||
|
FolderReader::~FolderReader() {}
|
||||||
|
|
||||||
|
std::shared_ptr<std::istream> FolderReader::getFileStream(const std::string& filename) {
|
||||||
|
std::shared_ptr<std::istream> stream = std::make_shared<std::ifstream>(path + filename);
|
||||||
|
return stream;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#if BEATSABERZIPSUPPORT == 1
|
||||||
|
ZipReader::ZipReader(const std::string& path) : file(path) {}
|
||||||
|
|
||||||
|
ZipReader::~ZipReader() {
|
||||||
|
file.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
std::shared_ptr<std::istream> ZipReader::getFileStream(const std::string& filename) {
|
||||||
|
return file.getInputStream(filename);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
}
|
|
@ -4,8 +4,12 @@
|
||||||
#include "beatmap.h"
|
#include "beatmap.h"
|
||||||
|
|
||||||
//tests
|
//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) {
|
int main(int argc, char** argv) {
|
||||||
|
|
||||||
|
@ -26,7 +30,7 @@ int main(int argc, char** argv) {
|
||||||
printf("\033[1;93m%d\033[0;1m/%d failed\n", failcount, testcount);
|
printf("\033[1;93m%d\033[0;1m/%d failed\n", failcount, testcount);
|
||||||
|
|
||||||
//simple read test
|
//simple read test
|
||||||
std::unique_ptr<Beatsaber::BeatMap> bmap = Beatsaber::BeatMap::loadFromFolder("/media/satassd/steam/steamapps/common/Beat Saber/Beat Saber_Data/CustomLevels/1dd (Portal - Still Alive (Uppermost Remix) - kryptikos)");
|
std::shared_ptr<Beatsaber::BeatMap> bmap = Beatsaber::BeatMap::loadFromFolder("/media/satassd/steam/steamapps/common/Beat Saber/Beat Saber_Data/CustomLevels/1dd (Portal - Still Alive (Uppermost Remix) - kryptikos)");
|
||||||
if(!bmap) std::cout << "Could not load File" << std::endl;
|
if(!bmap) std::cout << "Could not load File" << std::endl;
|
||||||
else bmap->printDebug();
|
else bmap->printDebug();
|
||||||
|
|
||||||
|
|
|
@ -6,6 +6,7 @@
|
||||||
#define TESTDATA "./tests/data/"
|
#define TESTDATA "./tests/data/"
|
||||||
|
|
||||||
#define ASSERT(BED, ERR) if(!(BED)) { std::cout << __FILE__ << ":" << __LINE__ << " " << ERR << std::endl; return TESTFAILED; }
|
#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)();
|
typedef int (*test_t)();
|
||||||
|
|
|
@ -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;
|
||||||
|
}
|
Loading…
Reference in New Issue