Add binary PTH to ASCII PTH tool

This commit is contained in:
Vsevolod Kremianskii 2021-03-31 15:24:00 +07:00
parent 9f955664fb
commit b6b66fdeec
4 changed files with 54 additions and 7 deletions

View file

@ -52,7 +52,8 @@ static const unordered_map<string, Operation> g_operations {
{ "to-rim", Operation::ToRIM },
{ "to-erf", Operation::ToERF },
{ "to-mod", Operation::ToMOD },
{ "to-pth", Operation::ToPTH }
{ "to-pth", Operation::ToPTH },
{ "to-ascii", Operation::ToASCII }
};
Program::Program(int argc, char **argv) : _argc(argc), _argv(argv) {
@ -96,7 +97,8 @@ void Program::initOptions() {
("to-rim", "create RIM archive from directory")
("to-erf", "create ERF archive from directory")
("to-mod", "create MOD archive from directory")
("to-pth", "convert ASCII PTH to PTH")
("to-pth", "convert ASCII PTH to binary PTH")
("to-ascii", "convert binary PTH to ASCII")
("target", po::value<string>(), "target name or path to input file");
}

View file

@ -21,9 +21,12 @@
#include <vector>
#include <boost/algorithm/string.hpp>
#include <boost/format.hpp>
#include "glm/vec3.hpp"
#include "../src/common/streamutil.h"
#include "../src/resource/format/gffreader.h"
#include "../src/resource/format/gffwriter.h"
using namespace std;
@ -36,9 +39,6 @@ namespace reone {
namespace tools {
static constexpr int kMaxNameLen = 64;
static constexpr int kBufferSize = 256;
struct PathPoint {
string name;
glm::vec3 position { 0.0f };
@ -48,6 +48,8 @@ struct PathPoint {
void PthTool::invoke(Operation operation, const fs::path &target, const fs::path &gamePath, const fs::path &destPath) {
if (operation == Operation::ToPTH) {
toPTH(target, destPath);
} else if (operation == Operation::ToASCII) {
toASCII(target, destPath);
}
}
@ -157,11 +159,52 @@ void PthTool::toPTH(const fs::path &path, const fs::path &destPath) {
writer.save(pthPath);
}
static string getPointName(int index) {
return str(boost::format("PathPoint%03d") % index);
}
void PthTool::toASCII(const fs::path &path, const fs::path &destPath) {
// Read binary PTH
GffReader reader;
reader.load(path);
shared_ptr<GffStruct> root(reader.root());
// Write ASCII PTH
string filename(path.filename().string());
int lastDotIdx = filename.find_last_of('.');
if (lastDotIdx != -1) {
filename = filename.substr(0, lastDotIdx);
}
fs::path asciiPath(destPath);
asciiPath.append(filename + "-ascii.pth");
auto ascii = make_shared<fs::ofstream>(asciiPath);
int pointIdx = 0;
StreamWriter writer(ascii);
for (auto &point : root->getList("Path_Points")) {
string name(getPointName(pointIdx++));
int conections = point->getInt("Conections");
int firstConection = point->getInt("First_Conection");
float x = point->getFloat("X");
float y = point->getFloat("Y");
writer.putString(str(boost::format("%s %f %f %f %d\n") % name % x % y % 0.0f % conections));
for (int i = 0; i < conections; ++i) {
shared_ptr<GffStruct> conection(root->getList("Path_Conections")[firstConection + i]);
int destination = conection->getInt("Destination");
string destName(getPointName(destination));
writer.putString(str(boost::format(" %s\n") % destName));
}
}
}
bool PthTool::supports(Operation operation, const fs::path &target) const {
return
!fs::is_directory(target) &&
target.extension() == ".pth" &&
operation == Operation::ToPTH;
(operation == Operation::ToPTH || operation == Operation::ToASCII);
}
} // namespace tools

View file

@ -159,6 +159,7 @@ class PthTool : public ITool {
private:
void toPTH(const boost::filesystem::path &path, const boost::filesystem::path &destPath);
void toASCII(const boost::filesystem::path &path, const boost::filesystem::path &destPath);
};
} // namespace tools

View file

@ -32,7 +32,8 @@ enum class Operation {
ToRIM,
ToERF,
ToMOD,
ToPTH
ToPTH,
ToASCII
};
} // namespace tools