feat: finish BMapInspector framework
This commit is contained in:
@@ -193,7 +193,7 @@ PenaltyBreakTemplateDeclaration: 10
|
||||
PenaltyExcessCharacter: 50
|
||||
PenaltyIndentedWhitespace: 0
|
||||
PenaltyReturnTypeOnItsOwnLine: 300
|
||||
PointerAlignment: Right
|
||||
PointerAlignment: Left
|
||||
PPIndentWidth: -1
|
||||
QualifierAlignment: Leave
|
||||
ReferenceAlignment: Pointer
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
#include "Utils.hpp"
|
||||
#include "Cli.hpp"
|
||||
#include "Reporter.hpp"
|
||||
#include "Ruleset.hpp"
|
||||
#include "Cli.hpp"
|
||||
#include "Map.hpp"
|
||||
#include "Rule.hpp"
|
||||
#include <VTAll.hpp>
|
||||
#include <yycc.hpp>
|
||||
#include <yycc/carton/termcolor.hpp>
|
||||
@@ -24,7 +25,7 @@ static void PrintSplash() {
|
||||
static std::optional<BMapInspector::Cli::Args> AcceptArgs() {
|
||||
auto request = BMapInspector::Cli::parse();
|
||||
if (request.has_value()) {
|
||||
return request.value();
|
||||
return std::move(request.value());
|
||||
} else {
|
||||
using BMapInspector::Cli::Error;
|
||||
|
||||
@@ -62,23 +63,51 @@ static std::optional<BMapInspector::Cli::Args> AcceptArgs() {
|
||||
}
|
||||
}
|
||||
|
||||
static std::optional<BMapInspector::Ruleset::RuleContext> LoadVirtools(BMapInspector::Cli::Args& args) {
|
||||
return std::nullopt;
|
||||
static std::optional<BMapInspector::Map::Level> LoadLevel(BMapInspector::Cli::Args& args) {
|
||||
auto level = BMapInspector::Map::load(args);
|
||||
if (level.has_value()) {
|
||||
return std::move(level.value());
|
||||
} else {
|
||||
using BMapInspector::Map::Error;
|
||||
|
||||
std::u8string err_words;
|
||||
switch (level.error()) {
|
||||
case Error::BadTempDir:
|
||||
err_words = u8"Can not set temporary directory for loading.";
|
||||
break;
|
||||
case Error::BadBallance:
|
||||
err_words = u8"Can not find Ballance texture directory.";
|
||||
break;
|
||||
case Error::BadEncoding:
|
||||
err_words = u8"Can not set encoding with your given name.";
|
||||
break;
|
||||
case Error::BadMap:
|
||||
err_words = u8"Can not load your given map file.";
|
||||
break;
|
||||
default:
|
||||
err_words = u8"Unknown error.";
|
||||
break;
|
||||
}
|
||||
|
||||
termcolor::cprintln(err_words, Color::Red);
|
||||
termcolor::cprintln(u8"Please carefully check your map file and parameters for loading this map file.", Color::Red);
|
||||
return std::nullopt;
|
||||
}
|
||||
}
|
||||
|
||||
static void CheckRules(BMapInspector::Ruleset::RuleContext& ctx) {
|
||||
static void CheckRules(BMapInspector::Cli::Args& args, BMapInspector::Map::Level& level) {
|
||||
// Create reporter
|
||||
BMapInspector::Reporter::Reporter reporter;
|
||||
|
||||
// Get rule collection
|
||||
BMapInspector::Ruleset::RuleCollection rule_collection;
|
||||
BMapInspector::Rule::Ruleset ruleset;
|
||||
// Show rule infos
|
||||
std::cout << strop::printf(u8"Total %" PRIuSIZET " rule(s) are loaded.", rule_collection.GetRuleCount()) << std::endl
|
||||
std::cout << strop::printf(u8"Total %" PRIuSIZET " rule(s) are loaded.", ruleset.GetRuleCount()) << std::endl
|
||||
<< u8"Check may take few minutes. Please do not close this console..." << std::endl;
|
||||
|
||||
// Check rules one by one
|
||||
for (auto* rule : rule_collection.GetRules()) {
|
||||
rule->Check(reporter, ctx);
|
||||
for (auto* rule : ruleset.GetRules()) {
|
||||
rule->Check(reporter, level);
|
||||
}
|
||||
|
||||
// Show report conclusion
|
||||
@@ -91,6 +120,9 @@ static void CheckRules(BMapInspector::Ruleset::RuleContext& ctx) {
|
||||
// Print report in detail
|
||||
using BMapInspector::Utils::ReportLevel;
|
||||
for (const auto& report : reporter.GetReports()) {
|
||||
// Filter report first
|
||||
if (!BMapInspector::Utils::FilterReportLevel(report.level, args.level)) continue;
|
||||
// Okey, output this report.
|
||||
switch (report.level) {
|
||||
case ReportLevel::Error:
|
||||
termcolor::cprintln(strop::printf(u8"[ERROR] [RULE: %s] %s", report.rule.c_str(), report.content.c_str()), Color::Red);
|
||||
@@ -111,9 +143,9 @@ int main(int argc, char* argv[]) {
|
||||
PrintSplash();
|
||||
std::cout << std::endl;
|
||||
|
||||
auto ctx = LoadVirtools(args.value());
|
||||
if (ctx.has_value()) {
|
||||
CheckRules(ctx.value());
|
||||
auto level = LoadLevel(args.value());
|
||||
if (level.has_value()) {
|
||||
CheckRules(args.value(), level.value());
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
|
||||
@@ -7,7 +7,8 @@ PRIVATE
|
||||
Utils.cpp
|
||||
Reporter.cpp
|
||||
Cli.cpp
|
||||
Ruleset.cpp
|
||||
Map.cpp
|
||||
Rule.cpp
|
||||
)
|
||||
# Setup headers
|
||||
target_sources(BMapInspector
|
||||
@@ -17,7 +18,8 @@ FILES
|
||||
Utils.hpp
|
||||
Reporter.hpp
|
||||
Cli.hpp
|
||||
Ruleset.hpp
|
||||
Map.hpp
|
||||
Rule.hpp
|
||||
)
|
||||
# Setup header infomation
|
||||
target_include_directories(BMapInspector
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
#pragma once
|
||||
#include "Utils.hpp"
|
||||
#include "Reporter.hpp"
|
||||
#include <yycc.hpp>
|
||||
#include <yycc/macro/class_copy_move.hpp>
|
||||
#include <string>
|
||||
@@ -17,13 +16,13 @@ namespace BMapInspector::Cli {
|
||||
};
|
||||
|
||||
enum class Error {
|
||||
BadParse, ///< Error occurs when executing parser.
|
||||
NoFile, ///< User do not specify file path for loading.
|
||||
BadFile, ///< User specified file path is bad.
|
||||
NoBallance, ///< User do not specify Ballance directory for loading.
|
||||
BadParse, ///< Error occurs when executing parser.
|
||||
NoFile, ///< User do not specify file path for loading.
|
||||
BadFile, ///< User specified file path is bad.
|
||||
NoBallance, ///< User do not specify Ballance directory for loading.
|
||||
BadBallance, ///< User specified Ballance directory is bad.
|
||||
BadEncoding, ///< User given encoding value is bad.
|
||||
BadLevel, ///< User given level name is bad.
|
||||
BadLevel, ///< User given level name is bad.
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
|
||||
158
Ballance/BMapInspector/Map.cpp
Normal file
158
Ballance/BMapInspector/Map.cpp
Normal file
@@ -0,0 +1,158 @@
|
||||
#include "Map.hpp"
|
||||
#include <VTAll.hpp>
|
||||
#include <filesystem>
|
||||
#include <stdexcept>
|
||||
|
||||
namespace C = LibCmo::CK2;
|
||||
namespace O = LibCmo::CK2::ObjImpls;
|
||||
|
||||
namespace BMapInspector::Map {
|
||||
|
||||
#pragma region Level
|
||||
|
||||
Level::Level(const Cli::Args& args) : m_Context(nullptr), m_LoadStatus() {
|
||||
// Create contexy
|
||||
this->m_Context = new C::CKContext();
|
||||
// Callback for eat all output.
|
||||
this->m_Context->SetOutputCallback([](LibCmo::CKSTRING strl) -> void {});
|
||||
// Set temp folder
|
||||
auto pm = m_Context->GetPathManager();
|
||||
auto temp_dir = std::filesystem::temp_directory_path();
|
||||
auto our_temp_dir = temp_dir / u8"88797AB5-915E-39AD-4800-BF1B0F59E207";
|
||||
std::filesystem::create_directories(our_temp_dir);
|
||||
if (!pm->SetTempFolder(our_temp_dir.u8string().c_str())) {
|
||||
this->m_LoadStatus = std::unexpected(Error::BadTempDir);
|
||||
return;
|
||||
}
|
||||
// Set ballance textures directory
|
||||
auto ballance_dir = std::filesystem::path(args.ballance_path);
|
||||
auto textures_dir = ballance_dir / u8"Textures";
|
||||
if (!pm->AddPath(textures_dir.u8string().c_str())) {
|
||||
this->m_LoadStatus = std::unexpected(Error::BadBallance);
|
||||
return;
|
||||
}
|
||||
// Set encoding
|
||||
LibCmo::XContainer::XArray<LibCmo::XContainer::XString> encs;
|
||||
encs.emplace_back(args.encoding);
|
||||
this->m_Context->SetEncoding(encs);
|
||||
if (!this->m_Context->IsValidEncoding()) {
|
||||
this->m_LoadStatus = std::unexpected(Error::BadEncoding);
|
||||
return;
|
||||
}
|
||||
// set default texture save mode is external
|
||||
this->m_Context->SetGlobalImagesSaveOptions(C::CK_TEXTURE_SAVEOPTIONS::CKTEXTURE_EXTERNAL);
|
||||
// set default file write mode is whole compressed
|
||||
this->m_Context->SetFileWriteMode(C::CK_FILE_WRITEMODE::CKFILE_WHOLECOMPRESSED);
|
||||
|
||||
// Create temp ckfile and load
|
||||
C::CKFileReader reader(m_Context);
|
||||
auto err = reader.DeepLoad(args.file_path.c_str());
|
||||
if (err != C::CKERROR::CKERR_OK) {
|
||||
// failed. clear document and return
|
||||
this->m_Context->ClearAll();
|
||||
this->m_LoadStatus = std::unexpected(Error::BadMap);
|
||||
return;
|
||||
}
|
||||
|
||||
// Fill our list
|
||||
for (const auto& fileobj : reader.GetFileObjects()) {
|
||||
auto ptr = fileobj.ObjPtr;
|
||||
if (ptr == nullptr) continue;
|
||||
|
||||
switch (fileobj.ObjectCid) {
|
||||
case LibCmo::CK2::CK_CLASSID::CKCID_GROUP:
|
||||
m_ObjGroups.emplace_back(static_cast<O::CKGroup*>(ptr));
|
||||
break;
|
||||
case LibCmo::CK2::CK_CLASSID::CKCID_3DOBJECT:
|
||||
m_Obj3dObjects.emplace_back(static_cast<O::CK3dObject*>(ptr));
|
||||
break;
|
||||
case LibCmo::CK2::CK_CLASSID::CKCID_MESH:
|
||||
m_ObjMeshes.emplace_back(static_cast<O::CKMesh*>(ptr));
|
||||
break;
|
||||
case LibCmo::CK2::CK_CLASSID::CKCID_MATERIAL:
|
||||
m_ObjMaterials.emplace_back(static_cast<O::CKMaterial*>(ptr));
|
||||
break;
|
||||
case LibCmo::CK2::CK_CLASSID::CKCID_TEXTURE:
|
||||
m_ObjTextures.emplace_back(static_cast<O::CKTexture*>(ptr));
|
||||
break;
|
||||
case LibCmo::CK2::CK_CLASSID::CKCID_TARGETLIGHT:
|
||||
m_ObjTargetLights.emplace_back(static_cast<O::CKTargetLight*>(ptr));
|
||||
break;
|
||||
default:
|
||||
break; // skip unknow objects
|
||||
}
|
||||
}
|
||||
// Okey
|
||||
this->m_LoadStatus = {};
|
||||
}
|
||||
|
||||
Level::~Level() {
|
||||
if (this->m_Context != nullptr) {
|
||||
delete this->m_Context;
|
||||
}
|
||||
}
|
||||
|
||||
YYCC_IMPL_MOVE_CTOR(Level, rhs) : m_Context(rhs.m_Context) {
|
||||
rhs.m_Context = nullptr;
|
||||
}
|
||||
|
||||
YYCC_IMPL_MOVE_OPER(Level, rhs) {
|
||||
this->m_Context = rhs.m_Context;
|
||||
rhs.m_Context = nullptr;
|
||||
return *this;
|
||||
}
|
||||
|
||||
#define CHECK_STATUS(this) \
|
||||
if (!this->m_LoadStatus.has_value()) throw std::logic_error("can not fetch anything from not loaded level");
|
||||
|
||||
Result<void> Level::GetLoadStatus() const {
|
||||
return this->m_LoadStatus;
|
||||
}
|
||||
|
||||
C::CKContext* Level::GetCKContext() const {
|
||||
CHECK_STATUS(this)
|
||||
return this->m_Context;
|
||||
}
|
||||
|
||||
const std::vector<O::CKGroup*>& Level::GetGroups() const {
|
||||
CHECK_STATUS(this)
|
||||
return this->m_ObjGroups;
|
||||
}
|
||||
|
||||
const std::vector<O::CK3dObject*>& Level::Get3dObjects() const {
|
||||
CHECK_STATUS(this)
|
||||
return this->m_Obj3dObjects;
|
||||
}
|
||||
|
||||
const std::vector<O::CKMesh*>& Level::GetMeshes() const {
|
||||
CHECK_STATUS(this)
|
||||
return this->m_ObjMeshes;
|
||||
}
|
||||
|
||||
const std::vector<O::CKMaterial*>& Level::GetMaterials() const {
|
||||
CHECK_STATUS(this)
|
||||
return this->m_ObjMaterials;
|
||||
}
|
||||
|
||||
const std::vector<O::CKTexture*>& Level::GetTextures() const {
|
||||
CHECK_STATUS(this)
|
||||
return this->m_ObjTextures;
|
||||
}
|
||||
|
||||
const std::vector<O::CKTargetLight*>& Level::GetTargetLights() const {
|
||||
CHECK_STATUS(this)
|
||||
return this->m_ObjTargetLights;
|
||||
}
|
||||
|
||||
#undef CHECK_STATUS
|
||||
|
||||
#pragma endregion
|
||||
|
||||
Result<Level> load(const Cli::Args& args) {
|
||||
Level rv(args);
|
||||
auto status = rv.GetLoadStatus();
|
||||
if (status.has_value()) return rv;
|
||||
else return std::unexpected(status.error());
|
||||
}
|
||||
|
||||
} // namespace BMapInspector::Map
|
||||
68
Ballance/BMapInspector/Map.hpp
Normal file
68
Ballance/BMapInspector/Map.hpp
Normal file
@@ -0,0 +1,68 @@
|
||||
#pragma once
|
||||
#include "Cli.hpp"
|
||||
#include <yycc.hpp>
|
||||
#include <yycc/macro/class_copy_move.hpp>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <optional>
|
||||
#include <expected>
|
||||
|
||||
namespace LibCmo::CK2 {
|
||||
class CKContext;
|
||||
namespace ObjImpls {
|
||||
class CKGroup;
|
||||
class CK3dObject;
|
||||
class CKMesh;
|
||||
class CKMaterial;
|
||||
class CKTexture;
|
||||
class CKTargetLight;
|
||||
} // namespace ObjImpls
|
||||
} // namespace LibCmo::CK2
|
||||
|
||||
namespace BMapInspector::Map {
|
||||
|
||||
enum class Error {
|
||||
BadTempDir, ///< Fail to set temporary directory.
|
||||
BadBallance, ///< Fail to set Ballance texture directory.
|
||||
BadEncoding, ///< Fail to set encoding for loading map.
|
||||
BadMap, ///< Can not load given map.
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
using Result = std::expected<T, Error>;
|
||||
|
||||
class Level {
|
||||
public:
|
||||
Level(const Cli::Args& args);
|
||||
~Level();
|
||||
YYCC_DELETE_COPY(Level)
|
||||
YYCC_DECL_MOVE(Level)
|
||||
|
||||
public:
|
||||
Result<void> GetLoadStatus() const;
|
||||
LibCmo::CK2::CKContext* GetCKContext() const;
|
||||
|
||||
private:
|
||||
LibCmo::CK2::CKContext* m_Context;
|
||||
Result<void> m_LoadStatus; ///< Nothing or error occurs when loading user given map.
|
||||
|
||||
public:
|
||||
const std::vector<LibCmo::CK2::ObjImpls::CKGroup*>& GetGroups() const;
|
||||
const std::vector<LibCmo::CK2::ObjImpls::CK3dObject*>& Get3dObjects() const;
|
||||
const std::vector<LibCmo::CK2::ObjImpls::CKMesh*>& GetMeshes() const;
|
||||
const std::vector<LibCmo::CK2::ObjImpls::CKMaterial*>& GetMaterials() const;
|
||||
const std::vector<LibCmo::CK2::ObjImpls::CKTexture*>& GetTextures() const;
|
||||
const std::vector<LibCmo::CK2::ObjImpls::CKTargetLight*>& GetTargetLights() const;
|
||||
|
||||
private:
|
||||
std::vector<LibCmo::CK2::ObjImpls::CKGroup*> m_ObjGroups;
|
||||
std::vector<LibCmo::CK2::ObjImpls::CK3dObject*> m_Obj3dObjects;
|
||||
std::vector<LibCmo::CK2::ObjImpls::CKMesh*> m_ObjMeshes;
|
||||
std::vector<LibCmo::CK2::ObjImpls::CKMaterial*> m_ObjMaterials;
|
||||
std::vector<LibCmo::CK2::ObjImpls::CKTexture*> m_ObjTextures;
|
||||
std::vector<LibCmo::CK2::ObjImpls::CKTargetLight*> m_ObjTargetLights;
|
||||
};
|
||||
|
||||
Result<Level> load(const Cli::Args& args);
|
||||
|
||||
} // namespace BMapInspector::Map
|
||||
31
Ballance/BMapInspector/Rule.cpp
Normal file
31
Ballance/BMapInspector/Rule.cpp
Normal file
@@ -0,0 +1,31 @@
|
||||
#include "Rule.hpp"
|
||||
|
||||
namespace BMapInspector::Rule {
|
||||
|
||||
#pragma region IRule
|
||||
|
||||
IRule::IRule() {}
|
||||
|
||||
IRule::~IRule() {}
|
||||
|
||||
#pragma endregion
|
||||
|
||||
#pragma region Ruleset
|
||||
|
||||
Ruleset::Ruleset() : rules() {
|
||||
// TODO: create instance for each rules.
|
||||
}
|
||||
|
||||
Ruleset::~Ruleset() {}
|
||||
|
||||
size_t Ruleset::GetRuleCount() const {
|
||||
return this->rules.size();
|
||||
}
|
||||
|
||||
const std::vector<IRule*>& Ruleset::GetRules() const {
|
||||
return this->rules;
|
||||
}
|
||||
|
||||
#pragma endregion
|
||||
|
||||
} // namespace BMapInspector::Ruleset
|
||||
@@ -1,6 +1,7 @@
|
||||
#pragma once
|
||||
#include "Utils.hpp"
|
||||
#include "Reporter.hpp"
|
||||
#include "Map.hpp"
|
||||
#include <VTAll.hpp>
|
||||
#include <yycc.hpp>
|
||||
#include <yycc/macro/class_copy_move.hpp>
|
||||
@@ -8,21 +9,7 @@
|
||||
#include <string_view>
|
||||
#include <vector>
|
||||
|
||||
namespace BMapInspector::Ruleset {
|
||||
|
||||
class RuleContext {
|
||||
public:
|
||||
RuleContext();
|
||||
~RuleContext();
|
||||
YYCC_DELETE_COPY(RuleContext)
|
||||
YYCC_DECL_MOVE(RuleContext)
|
||||
|
||||
public:
|
||||
LibCmo::CK2::CKContext *GetCKContext();
|
||||
|
||||
private:
|
||||
LibCmo::CK2::CKContext *m_Ctx;
|
||||
};
|
||||
namespace BMapInspector::Rule {
|
||||
|
||||
class IRule {
|
||||
public:
|
||||
@@ -32,14 +19,14 @@ namespace BMapInspector::Ruleset {
|
||||
|
||||
public:
|
||||
virtual std::u8string_view GetRuleName() const = 0;
|
||||
virtual void Check(Reporter::Reporter& reporter, RuleContext& ctx) const = 0;
|
||||
virtual void Check(Reporter::Reporter& reporter, Map::Level& ctx) const = 0;
|
||||
};
|
||||
|
||||
class RuleCollection {
|
||||
class Ruleset {
|
||||
public:
|
||||
RuleCollection();
|
||||
~RuleCollection();
|
||||
YYCC_DELETE_COPY_MOVE(RuleCollection)
|
||||
Ruleset();
|
||||
~Ruleset();
|
||||
YYCC_DELETE_COPY_MOVE(Ruleset)
|
||||
|
||||
public:
|
||||
size_t GetRuleCount() const;
|
||||
@@ -1,53 +0,0 @@
|
||||
#include "Ruleset.hpp"
|
||||
|
||||
namespace BMapInspector::Ruleset {
|
||||
|
||||
#pragma region Rule Context
|
||||
|
||||
RuleContext::RuleContext() : m_Ctx(nullptr) {}
|
||||
|
||||
RuleContext::~RuleContext() {}
|
||||
|
||||
LibCmo::CK2::CKContext* RuleContext::GetCKContext() {
|
||||
return this->m_Ctx;
|
||||
}
|
||||
|
||||
YYCC_IMPL_MOVE_CTOR(RuleContext, rhs) : m_Ctx(rhs.m_Ctx) {
|
||||
rhs.m_Ctx = nullptr;
|
||||
}
|
||||
|
||||
YYCC_IMPL_MOVE_OPER(RuleContext, rhs) {
|
||||
this->m_Ctx = rhs.m_Ctx;
|
||||
rhs.m_Ctx = nullptr;
|
||||
return *this;
|
||||
}
|
||||
|
||||
#pragma endregion
|
||||
|
||||
#pragma region IRule
|
||||
|
||||
IRule::IRule() {}
|
||||
|
||||
IRule::~IRule() {}
|
||||
|
||||
#pragma endregion
|
||||
|
||||
#pragma region Rule Collection
|
||||
|
||||
RuleCollection::RuleCollection() : rules() {
|
||||
// TODO: create instance for each rules.
|
||||
}
|
||||
|
||||
RuleCollection::~RuleCollection() {}
|
||||
|
||||
size_t RuleCollection::GetRuleCount() const {
|
||||
return this->rules.size();
|
||||
}
|
||||
|
||||
const std::vector<IRule*>& RuleCollection::GetRules() const {
|
||||
return this->rules;
|
||||
}
|
||||
|
||||
#pragma endregion
|
||||
|
||||
} // namespace BMapInspector::Ruleset
|
||||
Reference in New Issue
Block a user