2
0
mirror of https://github.com/AxioDL/metaforce.git synced 2025-08-14 16:19:12 +00:00

Massive fmtlib refactor

This commit is contained in:
Jack Andersen 2019-07-19 18:22:58 -10:00
parent b483acb8d3
commit 6988f86672
37 changed files with 656 additions and 842 deletions

View File

@ -55,9 +55,9 @@ protected:
bool continuePrompt() { bool continuePrompt() {
if (!m_info.yes) { if (!m_info.yes) {
if (XTERM_COLOR) if (XTERM_COLOR)
hecl::Printf(_SYS_STR("\n" BLUE BOLD "Continue?" NORMAL " (Y/n) ")); fmt::print(fmt(_SYS_STR("\n" BLUE BOLD "Continue?" NORMAL " (Y/n) ")));
else else
hecl::Printf(_SYS_STR("\nContinue? (Y/n) ")); fmt::print(fmt(_SYS_STR("\nContinue? (Y/n) ")));
fflush(stdout); fflush(stdout);
int ch; int ch;
@ -73,7 +73,7 @@ protected:
#endif #endif
{ {
if (ch == 'n' || ch == 'N') { if (ch == 'n' || ch == 'N') {
hecl::Printf(_SYS_STR("\n")); fmt::print(fmt(_SYS_STR("\n")));
return false; return false;
} }
if (ch == 'y' || ch == 'Y' || ch == '\r' || ch == '\n') if (ch == 'y' || ch == 'Y' || ch == '\r' || ch == '\n')
@ -83,7 +83,7 @@ protected:
tcsetattr(0, TCSANOW, &tioOld); tcsetattr(0, TCSANOW, &tioOld);
#endif #endif
} }
hecl::Printf(_SYS_STR("\n")); fmt::print(fmt(_SYS_STR("\n")));
return true; return true;
} }
@ -175,27 +175,27 @@ public:
#endif #endif
} }
void print(const hecl::SystemChar* str) { hecl::FPrintf(m_sout, _SYS_STR("%s"), str); } void print(const hecl::SystemChar* str) { fmt::print(m_sout, fmt(_SYS_STR("{}")), str); }
void printBold(const hecl::SystemChar* str) { void printBold(const hecl::SystemChar* str) {
if (XTERM_COLOR) if (XTERM_COLOR)
hecl::FPrintf(m_sout, _SYS_STR("" BOLD "%s" NORMAL ""), str); fmt::print(m_sout, fmt(_SYS_STR("" BOLD "{}" NORMAL "")), str);
else else
hecl::FPrintf(m_sout, _SYS_STR("%s"), str); fmt::print(m_sout, fmt(_SYS_STR("{}")), str);
} }
void secHead(const hecl::SystemChar* headName) { void secHead(const hecl::SystemChar* headName) {
if (XTERM_COLOR) if (XTERM_COLOR)
hecl::FPrintf(m_sout, _SYS_STR("" BOLD "%s" NORMAL "\n"), headName); fmt::print(m_sout, fmt(_SYS_STR("" BOLD "{}" NORMAL "\n")), headName);
else else
hecl::FPrintf(m_sout, _SYS_STR("%s\n"), headName); fmt::print(m_sout, fmt(_SYS_STR("{}\n")), headName);
} }
void optionHead(const hecl::SystemChar* flag, const hecl::SystemChar* synopsis) { void optionHead(const hecl::SystemChar* flag, const hecl::SystemChar* synopsis) {
if (XTERM_COLOR) if (XTERM_COLOR)
hecl::FPrintf(m_sout, _SYS_STR("" BOLD "%s" NORMAL " (%s)\n"), flag, synopsis); fmt::print(m_sout, fmt(_SYS_STR("" BOLD "{}" NORMAL " ({})\n")), flag, synopsis);
else else
hecl::FPrintf(m_sout, _SYS_STR("%s (%s)\n"), flag, synopsis); fmt::print(m_sout, fmt(_SYS_STR("{} ({})\n")), flag, synopsis);
} }
void beginWrap() { m_wrapBuffer.clear(); } void beginWrap() { m_wrapBuffer.clear(); }
@ -213,7 +213,7 @@ public:
void endWrap() { void endWrap() {
_wrapBuf(m_wrapBuffer); _wrapBuf(m_wrapBuffer);
m_wrapBuffer += _SYS_STR('\n'); m_wrapBuffer += _SYS_STR('\n');
hecl::FPrintf(m_sout, _SYS_STR("%s"), m_wrapBuffer.c_str()); fmt::print(m_sout, fmt(_SYS_STR("{}")), m_wrapBuffer);
m_wrapBuffer.clear(); m_wrapBuffer.clear();
} }
}; };

View File

@ -38,7 +38,7 @@ public:
} }
} }
if (!m_spec) if (!m_spec)
LogModule.report(logvisor::Fatal, "unable to find data spec '%s'", specName.c_str()); LogModule.report(logvisor::Fatal, fmt("unable to find data spec '{}'"), specName);
continue; continue;
} else if (arg.size() >= 2 && arg[0] == _SYS_STR('-') && arg[1] == _SYS_STR('-')) } else if (arg.size() >= 2 && arg[0] == _SYS_STR('-') && arg[1] == _SYS_STR('-'))
continue; continue;
@ -51,18 +51,18 @@ public:
m_useProj = m_fallbackProj.get(); m_useProj = m_fallbackProj.get();
} else if (m_fallbackProj->getProjectRootPath() != root) } else if (m_fallbackProj->getProjectRootPath() != root)
LogModule.report(logvisor::Fatal, LogModule.report(logvisor::Fatal,
_SYS_STR("hecl cook can only process multiple items in the same project; ") fmt(_SYS_STR("hecl cook can only process multiple items in the same project; ")
_SYS_STR("'%s' and '%s' are different projects"), _SYS_STR("'{}' and '{}' are different projects")),
m_fallbackProj->getProjectRootPath().getAbsolutePath().data(), m_fallbackProj->getProjectRootPath().getAbsolutePath(),
root.getAbsolutePath().data()); root.getAbsolutePath());
m_selectedItems.emplace_back(*m_useProj, subPath); m_selectedItems.emplace_back(*m_useProj, subPath);
} }
} }
} }
if (!m_useProj) if (!m_useProj)
LogModule.report(logvisor::Fatal, LogModule.report(logvisor::Fatal,
"hecl cook must be ran within a project directory or " fmt("hecl cook must be ran within a project directory or "
"provided a path within a project"); "provided a path within a project"));
/* Default case: recursive at root */ /* Default case: recursive at root */
if (m_selectedItems.empty()) { if (m_selectedItems.empty()) {

View File

@ -29,7 +29,7 @@ class ToolExtract final : public ToolBase {
public: public:
ToolExtract(const ToolPassInfo& info) : ToolBase(info) { ToolExtract(const ToolPassInfo& info) : ToolBase(info) {
if (!m_info.args.size()) if (!m_info.args.size())
LogModule.report(logvisor::Fatal, "hecl extract needs a source path as its first argument"); LogModule.report(logvisor::Fatal, fmt("hecl extract needs a source path as its first argument"));
if (!info.project) { if (!info.project) {
hecl::SystemString rootDir; hecl::SystemString rootDir;
@ -47,7 +47,7 @@ public:
baseFile.assign(baseFile.begin(), baseFile.begin() + dotPos); baseFile.assign(baseFile.begin(), baseFile.begin() + dotPos);
if (baseFile.empty()) if (baseFile.empty())
LogModule.report(logvisor::Fatal, "hecl extract must be ran within a project directory"); LogModule.report(logvisor::Fatal, fmt("hecl extract must be ran within a project directory"));
rootDir = info.cwd + baseFile; rootDir = info.cwd + baseFile;
} else { } else {
@ -62,8 +62,8 @@ public:
newProjRoot.makeDir(); newProjRoot.makeDir();
m_fallbackProj.reset(new hecl::Database::Project(newProjRoot)); m_fallbackProj.reset(new hecl::Database::Project(newProjRoot));
if (logvisor::ErrorCount > ErrorRef) if (logvisor::ErrorCount > ErrorRef)
LogModule.report(logvisor::Fatal, "unable to init project at '%s'", rootDir.c_str()); LogModule.report(logvisor::Fatal, fmt("unable to init project at '{}'"), rootDir);
LogModule.report(logvisor::Info, _SYS_STR("initialized project at '%s/.hecl'"), rootDir.c_str()); LogModule.report(logvisor::Info, fmt(_SYS_STR("initialized project at '{}/.hecl'")), rootDir);
m_useProj = m_fallbackProj.get(); m_useProj = m_fallbackProj.get();
} else } else
m_useProj = info.project; m_useProj = info.project;
@ -116,15 +116,15 @@ public:
static void _recursivePrint(int level, hecl::Database::IDataSpec::ExtractReport& rep) { static void _recursivePrint(int level, hecl::Database::IDataSpec::ExtractReport& rep) {
for (int l = 0; l < level; ++l) for (int l = 0; l < level; ++l)
hecl::Printf(_SYS_STR(" ")); fmt::print(fmt(_SYS_STR(" ")));
if (XTERM_COLOR) if (XTERM_COLOR)
hecl::Printf(_SYS_STR("" BOLD "%s" NORMAL ""), rep.name.c_str()); fmt::print(fmt(_SYS_STR("" BOLD "{}" NORMAL "")), rep.name);
else else
hecl::Printf(_SYS_STR("%s"), rep.name.c_str()); fmt::print(fmt(_SYS_STR("{}")), rep.name);
if (rep.desc.size()) if (rep.desc.size())
hecl::Printf(_SYS_STR(" [%s]"), rep.desc.c_str()); fmt::print(fmt(_SYS_STR(" [{}]")), rep.desc);
hecl::Printf(_SYS_STR("\n")); fmt::print(fmt(_SYS_STR("\n")));
for (hecl::Database::IDataSpec::ExtractReport& child : rep.childOpts) for (hecl::Database::IDataSpec::ExtractReport& child : rep.childOpts)
_recursivePrint(level + 1, child); _recursivePrint(level + 1, child);
} }
@ -132,32 +132,32 @@ public:
int run() { int run() {
if (m_specPasses.empty()) { if (m_specPasses.empty()) {
if (XTERM_COLOR) if (XTERM_COLOR)
hecl::Printf(_SYS_STR("" RED BOLD "NOTHING TO EXTRACT" NORMAL "\n")); fmt::print(fmt(_SYS_STR("" RED BOLD "NOTHING TO EXTRACT" NORMAL "\n")));
else else
hecl::Printf(_SYS_STR("NOTHING TO EXTRACT\n")); fmt::print(fmt(_SYS_STR("NOTHING TO EXTRACT\n")));
return 1; return 1;
} }
if (XTERM_COLOR) if (XTERM_COLOR)
hecl::Printf(_SYS_STR("" GREEN BOLD "ABOUT TO EXTRACT:" NORMAL "\n")); fmt::print(fmt(_SYS_STR("" GREEN BOLD "ABOUT TO EXTRACT:" NORMAL "\n")));
else else
hecl::Printf(_SYS_STR("ABOUT TO EXTRACT:\n")); fmt::print(fmt(_SYS_STR("ABOUT TO EXTRACT:\n")));
for (hecl::Database::IDataSpec::ExtractReport& rep : m_reps) { for (hecl::Database::IDataSpec::ExtractReport& rep : m_reps) {
_recursivePrint(0, rep); _recursivePrint(0, rep);
hecl::Printf(_SYS_STR("\n")); fmt::print(fmt(_SYS_STR("\n")));
} }
fflush(stdout); fflush(stdout);
if (continuePrompt()) { if (continuePrompt()) {
for (SpecExtractPass& ds : m_specPasses) { for (SpecExtractPass& ds : m_specPasses) {
if (XTERM_COLOR) if (XTERM_COLOR)
hecl::Printf(_SYS_STR("" MAGENTA BOLD "Using DataSpec %s:" NORMAL "\n"), ds.m_entry->m_name.data()); fmt::print(fmt(_SYS_STR("" MAGENTA BOLD "Using DataSpec {}:" NORMAL "\n")), ds.m_entry->m_name);
else else
hecl::Printf(_SYS_STR("Using DataSpec %s:\n"), ds.m_entry->m_name.data()); fmt::print(fmt(_SYS_STR("Using DataSpec {}:\n")), ds.m_entry->m_name);
ds.m_instance->doExtract(m_einfo, {true}); ds.m_instance->doExtract(m_einfo, {true});
hecl::Printf(_SYS_STR("\n\n")); fmt::print(fmt(_SYS_STR("\n\n")));
} }
} }

View File

@ -9,7 +9,7 @@ class ToolHelp final : public ToolBase {
public: public:
ToolHelp(const ToolPassInfo& info) : ToolBase(info) { ToolHelp(const ToolPassInfo& info) : ToolBase(info) {
if (m_info.args.empty()) { if (m_info.args.empty()) {
LogModule.report(logvisor::Error, "help requires a tool name argument"); LogModule.report(logvisor::Error, fmt("help requires a tool name argument"));
return; return;
} }
m_good = true; m_good = true;
@ -64,7 +64,7 @@ public:
else if (toolName == _SYS_STR("help")) else if (toolName == _SYS_STR("help"))
helpFunc = ToolHelp::Help; helpFunc = ToolHelp::Help;
else { else {
LogModule.report(logvisor::Error, _SYS_STR("unrecognized tool '%s' - can't help"), toolName.c_str()); LogModule.report(logvisor::Error, fmt(_SYS_STR("unrecognized tool '{}' - can't help")), toolName);
return; return;
} }

View File

@ -17,7 +17,7 @@ class ToolImage final : public ToolBase {
public: public:
ToolImage(const ToolPassInfo& info) : ToolBase(info), m_useProj(info.project) { ToolImage(const ToolPassInfo& info) : ToolBase(info), m_useProj(info.project) {
if (!info.project) if (!info.project)
LogModule.report(logvisor::Fatal, "hecl image must be ran within a project directory"); LogModule.report(logvisor::Fatal, fmt("hecl image must be ran within a project directory"));
/* Scan args */ /* Scan args */
if (info.args.size()) { if (info.args.size()) {
@ -40,8 +40,8 @@ public:
} }
if (!m_useProj) if (!m_useProj)
LogModule.report(logvisor::Fatal, LogModule.report(logvisor::Fatal,
"hecl image must be ran within a project directory or " fmt("hecl image must be ran within a project directory or "
"provided a path within a project"); "provided a path within a project"));
} }
~ToolImage() {} ~ToolImage() {}
@ -75,29 +75,29 @@ public:
int run() { int run() {
if (XTERM_COLOR) if (XTERM_COLOR)
hecl::Printf(_SYS_STR("" GREEN BOLD "ABOUT TO IMAGE:" NORMAL "\n")); fmt::print(fmt(_SYS_STR("" GREEN BOLD "ABOUT TO IMAGE:" NORMAL "\n")));
else else
hecl::Printf(_SYS_STR("ABOUT TO IMAGE:\n")); fmt::print(fmt(_SYS_STR("ABOUT TO IMAGE:\n")));
hecl::Printf(_SYS_STR(" %s\n"), m_useProj->getProjectRootPath().getAbsolutePath().data()); fmt::print(fmt(_SYS_STR(" {}\n")), m_useProj->getProjectRootPath().getAbsolutePath());
fflush(stdout); fflush(stdout);
if (continuePrompt()) { if (continuePrompt()) {
hecl::ProjectPath outPath(m_useProj->getProjectWorkingPath(), _SYS_STR("out")); hecl::ProjectPath outPath(m_useProj->getProjectWorkingPath(), _SYS_STR("out"));
if (!outPath.isDirectory()) { if (!outPath.isDirectory()) {
LogModule.report(logvisor::Error, _SYS_STR("%s is not a directory"), outPath.getAbsolutePath().data()); LogModule.report(logvisor::Error, fmt(_SYS_STR("{} is not a directory")), outPath.getAbsolutePath());
return 1; return 1;
} }
hecl::ProjectPath bootBinPath(outPath, _SYS_STR("sys/boot.bin")); hecl::ProjectPath bootBinPath(outPath, _SYS_STR("sys/boot.bin"));
if (!bootBinPath.isFile()) { if (!bootBinPath.isFile()) {
LogModule.report(logvisor::Error, _SYS_STR("%s is not a file"), bootBinPath.getAbsolutePath().data()); LogModule.report(logvisor::Error, fmt(_SYS_STR("{} is not a file")), bootBinPath.getAbsolutePath());
return 1; return 1;
} }
athena::io::FileReader r(bootBinPath.getAbsolutePath()); athena::io::FileReader r(bootBinPath.getAbsolutePath());
if (r.hasError()) { if (r.hasError()) {
LogModule.report(logvisor::Error, _SYS_STR("unable to open %s"), bootBinPath.getAbsolutePath().data()); LogModule.report(logvisor::Error, fmt(_SYS_STR("unable to open {}")), bootBinPath.getAbsolutePath());
return 1; return 1;
} }
std::string id = r.readString(6); std::string id = r.readString(6);
@ -113,7 +113,7 @@ public:
fileOut += _SYS_STR(".gcm"); fileOut += _SYS_STR(".gcm");
if (nod::DiscBuilderGCN::CalculateTotalSizeRequired(outPath.getAbsolutePath()) == UINT64_MAX) if (nod::DiscBuilderGCN::CalculateTotalSizeRequired(outPath.getAbsolutePath()) == UINT64_MAX)
return 1; return 1;
LogModule.report(logvisor::Info, _SYS_STR("Generating %s as GameCube image"), fileOut.c_str()); LogModule.report(logvisor::Info, fmt(_SYS_STR("Generating {} as GameCube image")), fileOut);
nod::DiscBuilderGCN db(fileOut, progFunc); nod::DiscBuilderGCN db(fileOut, progFunc);
if (db.buildFromDirectory(outPath.getAbsolutePath()) != nod::EBuildResult::Success) if (db.buildFromDirectory(outPath.getAbsolutePath()) != nod::EBuildResult::Success)
return 1; return 1;
@ -122,7 +122,7 @@ public:
bool dualLayer; bool dualLayer;
if (nod::DiscBuilderWii::CalculateTotalSizeRequired(outPath.getAbsolutePath(), dualLayer) == UINT64_MAX) if (nod::DiscBuilderWii::CalculateTotalSizeRequired(outPath.getAbsolutePath(), dualLayer) == UINT64_MAX)
return 1; return 1;
LogModule.report(logvisor::Info, _SYS_STR("Generating %s as %s-layer Wii image"), fileOut.c_str(), LogModule.report(logvisor::Info, fmt(_SYS_STR("Generating {} as {}-layer Wii image")), fileOut,
dualLayer ? _SYS_STR("dual") : _SYS_STR("single")); dualLayer ? _SYS_STR("dual") : _SYS_STR("single"));
nod::DiscBuilderWii db(fileOut, dualLayer, progFunc); nod::DiscBuilderWii db(fileOut, dualLayer, progFunc);
if (db.buildFromDirectory(outPath.getAbsolutePath()) != nod::EBuildResult::Success) if (db.buildFromDirectory(outPath.getAbsolutePath()) != nod::EBuildResult::Success)

View File

@ -18,18 +18,18 @@ public:
if (hecl::Stat(dir->c_str(), &theStat)) { if (hecl::Stat(dir->c_str(), &theStat)) {
hecl::MakeDir(dir->c_str()); hecl::MakeDir(dir->c_str());
if (hecl::Stat(dir->c_str(), &theStat)) { if (hecl::Stat(dir->c_str(), &theStat)) {
LogModule.report(logvisor::Fatal, _SYS_STR("unable to stat '%s'"), dir->c_str()); LogModule.report(logvisor::Fatal, fmt(_SYS_STR("unable to stat '{}'")), *dir);
return; return;
} }
} }
if (!S_ISDIR(theStat.st_mode)) { if (!S_ISDIR(theStat.st_mode)) {
LogModule.report(logvisor::Fatal, _SYS_STR("'%s' is not a directory"), dir->c_str()); LogModule.report(logvisor::Fatal, fmt(_SYS_STR("'{}' is not a directory")), *dir);
return; return;
} }
hecl::SystemString testPath = *dir + _SYS_STR("/.hecl/beacon"); hecl::SystemString testPath = *dir + _SYS_STR("/.hecl/beacon");
if (!hecl::Stat(testPath.c_str(), &theStat)) { if (!hecl::Stat(testPath.c_str(), &theStat)) {
LogModule.report(logvisor::Fatal, _SYS_STR("project already exists at '%s'"), dir->c_str()); LogModule.report(logvisor::Fatal, fmt(_SYS_STR("project already exists at '{}'")), *dir);
return; return;
} }
@ -43,7 +43,7 @@ public:
hecl::Database::Project proj((hecl::ProjectRootPath(*m_dir))); hecl::Database::Project proj((hecl::ProjectRootPath(*m_dir)));
if (logvisor::ErrorCount > ErrorRef) if (logvisor::ErrorCount > ErrorRef)
return 1; return 1;
LogModule.report(logvisor::Info, _SYS_STR("initialized project at '%s/.hecl'"), m_dir->c_str()); LogModule.report(logvisor::Info, fmt(_SYS_STR("initialized project at '{}/.hecl'")), *m_dir);
return 0; return 0;
} }

View File

@ -61,7 +61,7 @@ class ToolPackage final : public ToolBase {
public: public:
ToolPackage(const ToolPassInfo& info) : ToolBase(info), m_useProj(info.project) { ToolPackage(const ToolPassInfo& info) : ToolBase(info), m_useProj(info.project) {
if (!info.project) if (!info.project)
LogModule.report(logvisor::Fatal, "hecl package must be ran within a project directory"); LogModule.report(logvisor::Fatal, fmt("hecl package must be ran within a project directory"));
/* Scan args */ /* Scan args */
if (info.args.size()) { if (info.args.size()) {
@ -82,7 +82,7 @@ public:
} }
} }
if (!m_spec) if (!m_spec)
LogModule.report(logvisor::Fatal, "unable to find data spec '%s'", specName.c_str()); LogModule.report(logvisor::Fatal, fmt("unable to find data spec '{}'"), specName);
continue; continue;
} else if (arg.size() >= 2 && arg[0] == _SYS_STR('-') && arg[1] == _SYS_STR('-')) } else if (arg.size() >= 2 && arg[0] == _SYS_STR('-') && arg[1] == _SYS_STR('-'))
continue; continue;
@ -96,10 +96,10 @@ public:
m_useProj = m_fallbackProj.get(); m_useProj = m_fallbackProj.get();
} else if (m_fallbackProj->getProjectRootPath() != root) } else if (m_fallbackProj->getProjectRootPath() != root)
LogModule.report(logvisor::Fatal, LogModule.report(logvisor::Fatal,
_SYS_STR("hecl package can only process multiple items in the same project; ") fmt(_SYS_STR("hecl package can only process multiple items in the same project; ")
_SYS_STR("'%s' and '%s' are different projects"), _SYS_STR("'{}' and '{}' are different projects")),
m_fallbackProj->getProjectRootPath().getAbsolutePath().data(), m_fallbackProj->getProjectRootPath().getAbsolutePath(),
root.getAbsolutePath().data()); root.getAbsolutePath());
FindSelectedItems({*m_useProj, subPath}, true); FindSelectedItems({*m_useProj, subPath}, true);
} }
@ -107,8 +107,8 @@ public:
} }
if (!m_useProj) if (!m_useProj)
LogModule.report(logvisor::Fatal, LogModule.report(logvisor::Fatal,
"hecl package must be ran within a project directory or " fmt("hecl package must be ran within a project directory or "
"provided a path within a project"); "provided a path within a project"));
/* Default case: recursive at root */ /* Default case: recursive at root */
if (m_selectedItems.empty()) if (m_selectedItems.empty())
@ -160,12 +160,12 @@ public:
int run() { int run() {
if (XTERM_COLOR) if (XTERM_COLOR)
hecl::Printf(_SYS_STR("" GREEN BOLD "ABOUT TO PACKAGE:" NORMAL "\n")); fmt::print(fmt(_SYS_STR("" GREEN BOLD "ABOUT TO PACKAGE:" NORMAL "\n")));
else else
hecl::Printf(_SYS_STR("ABOUT TO PACKAGE:\n")); fmt::print(fmt(_SYS_STR("ABOUT TO PACKAGE:\n")));
for (auto& item : m_selectedItems) for (auto& item : m_selectedItems)
hecl::Printf(_SYS_STR(" %s\n"), item.getRelativePath().data()); fmt::print(fmt(_SYS_STR(" {}\n")), item.getRelativePath());
fflush(stdout); fflush(stdout);
if (continuePrompt()) { if (continuePrompt()) {
@ -173,7 +173,7 @@ public:
hecl::ClientProcess cp(&printer); hecl::ClientProcess cp(&printer);
for (const hecl::ProjectPath& path : m_selectedItems) { for (const hecl::ProjectPath& path : m_selectedItems) {
if (!m_useProj->packagePath(path, printer, m_fast, m_spec, &cp)) if (!m_useProj->packagePath(path, printer, m_fast, m_spec, &cp))
LogModule.report(logvisor::Error, _SYS_STR("Unable to package %s"), path.getAbsolutePath().data()); LogModule.report(logvisor::Error, fmt(_SYS_STR("Unable to package {}")), path.getAbsolutePath());
} }
cp.waitUntilComplete(); cp.waitUntilComplete();
} }

View File

@ -13,7 +13,7 @@ public:
return; return;
if (!info.project) if (!info.project)
LogModule.report(logvisor::Fatal, "hecl spec must be ran within a project directory"); LogModule.report(logvisor::Fatal, fmt("hecl spec must be ran within a project directory"));
const auto& specs = info.project->getDataSpecs(); const auto& specs = info.project->getDataSpecs();
hecl::SystemString firstArg = info.args.front(); hecl::SystemString firstArg = info.args.front();
@ -27,7 +27,7 @@ public:
return; return;
if (info.args.size() < 2) if (info.args.size() < 2)
LogModule.report(logvisor::Fatal, "Speclist argument required"); LogModule.report(logvisor::Fatal, fmt("Speclist argument required"));
auto it = info.args.begin(); auto it = info.args.begin();
++it; ++it;
@ -41,7 +41,7 @@ public:
} }
} }
if (!found) if (!found)
LogModule.report(logvisor::Fatal, _SYS_STR("'%s' is not found in the dataspec registry"), it->c_str()); LogModule.report(logvisor::Fatal, fmt(_SYS_STR("'{}' is not found in the dataspec registry")), *it);
} }
} }
@ -77,10 +77,10 @@ public:
if (!m_info.project) { if (!m_info.project) {
for (const hecl::Database::DataSpecEntry* spec : hecl::Database::DATA_SPEC_REGISTRY) { for (const hecl::Database::DataSpecEntry* spec : hecl::Database::DATA_SPEC_REGISTRY) {
if (XTERM_COLOR) if (XTERM_COLOR)
hecl::Printf(_SYS_STR("" BOLD CYAN "%s" NORMAL "\n"), spec->m_name.data()); fmt::print(fmt(_SYS_STR("" BOLD CYAN "{}" NORMAL "\n")), spec->m_name);
else else
hecl::Printf(_SYS_STR("%s\n"), spec->m_name.data()); fmt::print(fmt(_SYS_STR("{}\n")), spec->m_name);
hecl::Printf(_SYS_STR(" %s\n"), spec->m_desc.data()); fmt::print(fmt(_SYS_STR(" {}\n")), spec->m_desc);
} }
return 0; return 0;
} }
@ -89,16 +89,16 @@ public:
if (mode == MLIST) { if (mode == MLIST) {
for (auto& spec : specs) { for (auto& spec : specs) {
if (XTERM_COLOR) if (XTERM_COLOR)
hecl::Printf(_SYS_STR("" BOLD CYAN "%s" NORMAL ""), spec.spec.m_name.data()); fmt::print(fmt(_SYS_STR("" BOLD CYAN "{}" NORMAL "")), spec.spec.m_name);
else else
hecl::Printf(_SYS_STR("%s"), spec.spec.m_name.data()); fmt::print(fmt(_SYS_STR("{}")), spec.spec.m_name);
if (spec.active) { if (spec.active) {
if (XTERM_COLOR) if (XTERM_COLOR)
hecl::Printf(_SYS_STR(" " BOLD GREEN "[ENABLED]" NORMAL "")); fmt::print(fmt(_SYS_STR(" " BOLD GREEN "[ENABLED]" NORMAL "")));
else else
hecl::Printf(_SYS_STR(" [ENABLED]")); fmt::print(fmt(_SYS_STR(" [ENABLED]")));
} }
hecl::Printf(_SYS_STR("\n %s\n"), spec.spec.m_desc.data()); fmt::print(fmt(_SYS_STR("\n {}\n")), spec.spec.m_desc);
} }
return 0; return 0;
} }

View File

@ -45,20 +45,20 @@ bool XTERM_COLOR = false;
/* Main usage message */ /* Main usage message */
static void printHelp(const hecl::SystemChar* pname) { static void printHelp(const hecl::SystemChar* pname) {
if (XTERM_COLOR) if (XTERM_COLOR)
hecl::Printf(_SYS_STR("" BOLD "HECL" NORMAL "")); fmt::print(fmt(_SYS_STR("" BOLD "HECL" NORMAL "")));
else else
hecl::Printf(_SYS_STR("HECL")); fmt::print(fmt(_SYS_STR("HECL")));
#if HECL_HAS_NOD #if HECL_HAS_NOD
#define TOOL_LIST "extract|init|cook|package|image|help" #define TOOL_LIST "extract|init|cook|package|image|help"
#else #else
#define TOOL_LIST "extract|init|cook|package|help" #define TOOL_LIST "extract|init|cook|package|help"
#endif #endif
#if HECL_GIT #if HECL_GIT
hecl::Printf(_SYS_STR(" Commit " HECL_GIT_S " " HECL_BRANCH_S "\nUsage: %s " TOOL_LIST "\n"), pname); fmt::print(fmt(_SYS_STR(" Commit " HECL_GIT_S " " HECL_BRANCH_S "\nUsage: {} " TOOL_LIST "\n")), pname);
#elif HECL_VER #elif HECL_VER
hecl::Printf(_SYS_STR(" Version " HECL_VER_S "\nUsage: %s " TOOL_LIST "\n"), pname); fmt::print(fmt(_SYS_STR(" Version " HECL_VER_S "\nUsage: {} " TOOL_LIST "\n")), pname);
#else #else
hecl::Printf(_SYS_STR("\nUsage: %s " TOOL_LIST "\n"), pname); fmt::print(fmt(_SYS_STR("\nUsage: {} " TOOL_LIST "\n")), pname);
#endif #endif
} }
@ -77,11 +77,9 @@ static void SIGINTHandler(int sig) {
} }
static logvisor::Module AthenaLog("Athena"); static logvisor::Module AthenaLog("Athena");
static void AthenaExc(athena::error::Level level, const char* file, const char*, int line, const char* fmt, ...) { static void AthenaExc(athena::error::Level level, const char* file, const char*, int line,
va_list ap; fmt::string_view fmt, fmt::format_args args) {
va_start(ap, fmt); AthenaLog.vreport(logvisor::Level(level), fmt, args);
AthenaLog.report(logvisor::Level(level), fmt, ap);
va_end(ap);
} }
static hecl::SystemChar cwdbuf[1024]; static hecl::SystemChar cwdbuf[1024];
@ -96,7 +94,7 @@ int main(int argc, const char** argv)
#endif #endif
{ {
if (argc > 1 && !hecl::StrCmp(argv[1], _SYS_STR("--dlpackage"))) { if (argc > 1 && !hecl::StrCmp(argv[1], _SYS_STR("--dlpackage"))) {
printf("%s\n", HECL_DLPACKAGE); fmt::print(fmt("{}\n"), HECL_DLPACKAGE);
return 100; return 100;
} }
@ -278,7 +276,7 @@ int main(int argc, const char** argv)
else { else {
FILE* fp = hecl::Fopen(argv[1], _SYS_STR("rb")); FILE* fp = hecl::Fopen(argv[1], _SYS_STR("rb"));
if (!fp) if (!fp)
LogModule.report(logvisor::Error, _SYS_STR("unrecognized tool '%s'"), toolName.c_str()); LogModule.report(logvisor::Error, fmt(_SYS_STR("unrecognized tool '{}'")), toolName);
else { else {
/* Shortcut-case: implicit extract */ /* Shortcut-case: implicit extract */
fclose(fp); fclose(fp);
@ -295,8 +293,7 @@ int main(int argc, const char** argv)
} }
if (info.verbosityLevel) if (info.verbosityLevel)
LogModule.report(logvisor::Info, _SYS_STR("Constructed tool '%s' %d\n"), tool->toolName().c_str(), LogModule.report(logvisor::Info, fmt(_SYS_STR("Constructed tool '{}' {}\n")), tool->toolName(), info.verbosityLevel);
info.verbosityLevel);
/* Run tool */ /* Run tool */
ErrorRef = logvisor::ErrorCount; ErrorRef = logvisor::ErrorCount;

2
hecl/extern/athena vendored

@ -1 +1 @@
Subproject commit f3852eb0d2643a9b1d1358c3a89c0002b2cadb90 Subproject commit 478d75f1cb6ff25fbbd0d22357b6de395c3ab662

2
hecl/extern/boo vendored

@ -1 +1 @@
Subproject commit b2bf7549f510ce12ee7b834e0a5c3562846d6303 Subproject commit deefc8e99520ffacd0d70c27a6beeb1047a0c131

View File

@ -30,6 +30,7 @@
#include "athena/MemoryWriter.hpp" #include "athena/MemoryWriter.hpp"
#include <optional> #include <optional>
#include "Token.hpp" #include "Token.hpp"
#include <fmt/ostream.h>
namespace hecl::blender { namespace hecl::blender {
using namespace std::literals; using namespace std::literals;
@ -86,11 +87,8 @@ public:
} }
~PyOutStream() { close(); } ~PyOutStream() { close(); }
void close(); void close();
#if __GNUC__ template <typename S, typename... Args, typename Char = fmt::char_t<S>>
__attribute__((__format__(__printf__, 2, 3))) void format(const S& format, Args&&... args);
#endif
void
format(const char* fmt, ...);
void linkBlend(const char* target, const char* objName, bool link = true); void linkBlend(const char* target, const char* objName, bool link = true);
void linkBackground(const char* target, const char* sceneName = nullptr); void linkBackground(const char* target, const char* sceneName = nullptr);
void AABBToBMesh(const atVec3f& min, const atVec3f& max); void AABBToBMesh(const atVec3f& min, const atVec3f& max);
@ -713,6 +711,7 @@ class Connection {
uint32_t _writeStr(const char* str, uint32_t len, int wpipe); uint32_t _writeStr(const char* str, uint32_t len, int wpipe);
uint32_t _writeStr(const char* str, uint32_t len) { return _writeStr(str, len, m_writepipe[1]); } uint32_t _writeStr(const char* str, uint32_t len) { return _writeStr(str, len, m_writepipe[1]); }
uint32_t _writeStr(const char* str) { return _writeStr(str, strlen(str)); } uint32_t _writeStr(const char* str) { return _writeStr(str, strlen(str)); }
uint32_t _writeStr(const std::string& str) { return _writeStr(str.c_str(), str.size()); }
size_t _readBuf(void* buf, size_t len); size_t _readBuf(void* buf, size_t len);
size_t _writeBuf(const void* buf, size_t len); size_t _writeBuf(const void* buf, size_t len);
void _closePipe(); void _closePipe();
@ -738,14 +737,14 @@ public:
PyOutStream beginPythonOut(bool deleteOnError = false) { PyOutStream beginPythonOut(bool deleteOnError = false) {
bool expect = false; bool expect = false;
if (!m_lock.compare_exchange_strong(expect, true)) if (!m_lock.compare_exchange_strong(expect, true))
BlenderLog.report(logvisor::Fatal, "lock already held for blender::Connection::beginPythonOut()"); BlenderLog.report(logvisor::Fatal, fmt("lock already held for blender::Connection::beginPythonOut()"));
return PyOutStream(this, deleteOnError); return PyOutStream(this, deleteOnError);
} }
DataStream beginData() { DataStream beginData() {
bool expect = false; bool expect = false;
if (!m_lock.compare_exchange_strong(expect, true)) if (!m_lock.compare_exchange_strong(expect, true))
BlenderLog.report(logvisor::Fatal, "lock already held for blender::Connection::beginDataIn()"); BlenderLog.report(logvisor::Fatal, fmt("lock already held for blender::Connection::beginDataIn()"));
return DataStream(this); return DataStream(this);
} }
@ -760,6 +759,14 @@ public:
static void Shutdown(); static void Shutdown();
}; };
template <typename S, typename... Args, typename Char>
void PyOutStream::format(const S& format, Args&&... args)
{
if (!m_parent || !m_parent->m_lock)
BlenderLog.report(logvisor::Fatal, fmt("lock not held for PyOutStream::format()"));
fmt::print(*this, format, std::forward<Args>(args)...);
}
class HMDLBuffers { class HMDLBuffers {
public: public:
struct Surface; struct Surface;

View File

@ -77,12 +77,12 @@ struct Evaluation {
#ifdef _LIBCPP_VERSION #ifdef _LIBCPP_VERSION
using StageBinaryData = std::shared_ptr<uint8_t>; using StageBinaryData = std::shared_ptr<uint8_t>;
static inline StageBinaryData MakeStageBinaryData(size_t sz) { inline StageBinaryData MakeStageBinaryData(size_t sz) {
return StageBinaryData(new uint8_t[sz], std::default_delete<uint8_t[]>{}); return StageBinaryData(new uint8_t[sz], std::default_delete<uint8_t[]>{});
} }
#else #else
using StageBinaryData = std::shared_ptr<uint8_t[]>; using StageBinaryData = std::shared_ptr<uint8_t[]>;
static inline StageBinaryData MakeStageBinaryData(size_t sz) { return StageBinaryData(new uint8_t[sz]); } inline StageBinaryData MakeStageBinaryData(size_t sz) { return StageBinaryData(new uint8_t[sz]); }
#endif #endif
template <typename P, typename S> template <typename P, typename S>

View File

@ -26,13 +26,13 @@ class Console {
Console* m_con; Console* m_con;
LogVisorAdapter(Console* con) : m_con(con) {} LogVisorAdapter(Console* con) : m_con(con) {}
~LogVisorAdapter() {} ~LogVisorAdapter() = default;
void report(const char* modName, logvisor::Level severity, const char* format, va_list ap); void report(const char* modName, logvisor::Level severity, fmt::string_view format, fmt::format_args args);
void report(const char* modName, logvisor::Level severity, const wchar_t* format, va_list ap); void report(const char* modName, logvisor::Level severity, fmt::wstring_view format, fmt::wformat_args args);
void reportSource(const char* modName, logvisor::Level severity, const char* file, unsigned linenum, void reportSource(const char* modName, logvisor::Level severity, const char* file, unsigned linenum,
const char* format, va_list ap); fmt::string_view format, fmt::format_args args);
void reportSource(const char* modName, logvisor::Level severity, const char* file, unsigned linenum, void reportSource(const char* modName, logvisor::Level severity, const char* file, unsigned linenum,
const wchar_t* format, va_list ap); fmt::wstring_view format, fmt::wformat_args args);
}; };
public: public:
@ -80,8 +80,13 @@ public:
void listCommands(Console* con, const std::vector<std::string>& args); void listCommands(Console* con, const std::vector<std::string>& args);
bool commandExists(std::string_view cmd); bool commandExists(std::string_view cmd);
void report(Level level, const char* fmt, va_list list); void vreport(Level level, fmt::string_view format, fmt::format_args args);
void report(Level level, const char* fmt, ...); template <typename S, typename... Args, typename Char = fmt::char_t<S>>
void report(Level level, const S& format, Args&&... args) {
vreport(level, fmt::to_string_view<Char>(format),
fmt::basic_format_args<fmt::buffer_context<Char>>(
fmt::internal::make_args_checked<Args...>(format, args...)));
}
void init(boo::IWindow* ctx); void init(boo::IWindow* ctx);
void proc(); void proc();

View File

@ -94,7 +94,7 @@ public:
virtual bool canExtract(const ExtractPassInfo& info, std::vector<ExtractReport>& reps) { virtual bool canExtract(const ExtractPassInfo& info, std::vector<ExtractReport>& reps) {
(void)info; (void)info;
(void)reps; (void)reps;
LogModule.report(logvisor::Error, "not implemented"); LogModule.report(logvisor::Error, fmt("not implemented"));
return false; return false;
} }
virtual void doExtract(const ExtractPassInfo& info, const MultiProgressPrinter& progress) { virtual void doExtract(const ExtractPassInfo& info, const MultiProgressPrinter& progress) {
@ -104,7 +104,7 @@ public:
virtual bool canCook(const ProjectPath& path, blender::Token& btok) { virtual bool canCook(const ProjectPath& path, blender::Token& btok) {
(void)path; (void)path;
LogModule.report(logvisor::Error, "not implemented"); LogModule.report(logvisor::Error, fmt("not implemented"));
return false; return false;
} }
virtual const DataSpecEntry* overrideDataSpec(const ProjectPath& path, virtual const DataSpecEntry* overrideDataSpec(const ProjectPath& path,

View File

@ -37,9 +37,9 @@ public:
bool operator!=(uint32_t other) const { return num != other; } bool operator!=(uint32_t other) const { return num != other; }
std::string toString() const { return std::string(fcc, 4); } std::string toString() const { return std::string(fcc, 4); }
uint32_t toUint32() const { return num; } uint32_t toUint32() const { return num; }
operator uint32_t() const { return num; }
const char* getChars() const { return fcc; } const char* getChars() const { return fcc; }
char* getChars() { return fcc; } char* getChars() { return fcc; }
bool IsValid() const { return num != 0; }
}; };
#define FOURCC(chars) FourCC(SBIG(chars)) #define FOURCC(chars) FourCC(SBIG(chars))
@ -84,3 +84,6 @@ struct hash<hecl::FourCC> {
size_t operator()(const hecl::FourCC& val) const noexcept { return val.toUint32(); } size_t operator()(const hecl::FourCC& val) const noexcept { return val.toUint32(); }
}; };
} // namespace std } // namespace std
FMT_CUSTOM_FORMATTER(hecl::FourCC, fmt("{:.4s}"), obj.getChars())
FMT_CUSTOM_FORMATTER(hecl::DNAFourCC, fmt("{:.4s}"), obj.getChars())

View File

@ -34,9 +34,6 @@ static inline void ToUpper(SystemString& str) { std::transform(str.begin(), str.
#ifndef _SYS_STR #ifndef _SYS_STR
#define _SYS_STR(val) L##val #define _SYS_STR(val) L##val
#endif #endif
#ifndef FMT_CSTR_SYS
#define FMT_CSTR_SYS "S"
#endif
typedef struct _stat Sstat; typedef struct _stat Sstat;
#else #else
typedef char SystemChar; typedef char SystemChar;
@ -48,9 +45,6 @@ static inline void ToUpper(SystemString& str) { std::transform(str.begin(), str.
#ifndef _SYS_STR #ifndef _SYS_STR
#define _SYS_STR(val) val #define _SYS_STR(val) val
#endif #endif
#ifndef FMT_CSTR_SYS
#define FMT_CSTR_SYS "s"
#endif
typedef struct stat Sstat; typedef struct stat Sstat;
#endif #endif

View File

@ -154,7 +154,7 @@ inline std::string operator+(std::string_view lhs, const SystemStringConv& rhs)
void SanitizePath(std::string& path); void SanitizePath(std::string& path);
void SanitizePath(std::wstring& path); void SanitizePath(std::wstring& path);
static inline void Unlink(const SystemChar* file) { inline void Unlink(const SystemChar* file) {
#if _WIN32 #if _WIN32
_wunlink(file); _wunlink(file);
#else #else
@ -162,31 +162,31 @@ static inline void Unlink(const SystemChar* file) {
#endif #endif
} }
static inline void MakeDir(const char* dir) { inline void MakeDir(const char* dir) {
#if _WIN32 #if _WIN32
HRESULT err; HRESULT err;
if (!CreateDirectoryA(dir, NULL)) if (!CreateDirectoryA(dir, NULL))
if ((err = GetLastError()) != ERROR_ALREADY_EXISTS) if ((err = GetLastError()) != ERROR_ALREADY_EXISTS)
LogModule.report(logvisor::Fatal, "MakeDir(%s)", dir); LogModule.report(logvisor::Fatal, fmt("MakeDir(%s)"), dir);
#else #else
if (mkdir(dir, 0755)) if (mkdir(dir, 0755))
if (errno != EEXIST) if (errno != EEXIST)
LogModule.report(logvisor::Fatal, "MakeDir(%s): %s", dir, strerror(errno)); LogModule.report(logvisor::Fatal, fmt("MakeDir({}): {}"), dir, strerror(errno));
#endif #endif
} }
#if _WIN32 #if _WIN32
static inline void MakeDir(const wchar_t* dir) { inline void MakeDir(const wchar_t* dir) {
HRESULT err; HRESULT err;
if (!CreateDirectoryW(dir, NULL)) if (!CreateDirectoryW(dir, NULL))
if ((err = GetLastError()) != ERROR_ALREADY_EXISTS) if ((err = GetLastError()) != ERROR_ALREADY_EXISTS)
LogModule.report(logvisor::Fatal, _SYS_STR("MakeDir(%s)"), dir); LogModule.report(logvisor::Fatal, fmt(_SYS_STR("MakeDir(%s)")), dir);
} }
#endif #endif
int RecursiveMakeDir(const SystemChar* dir); int RecursiveMakeDir(const SystemChar* dir);
static inline const SystemChar* GetEnv(const SystemChar* name) { inline const SystemChar* GetEnv(const SystemChar* name) {
#if WINDOWS_STORE #if WINDOWS_STORE
return nullptr; return nullptr;
#else #else
@ -198,7 +198,7 @@ static inline const SystemChar* GetEnv(const SystemChar* name) {
#endif #endif
} }
static inline SystemChar* Getcwd(SystemChar* buf, int maxlen) { inline SystemChar* Getcwd(SystemChar* buf, int maxlen) {
#if HECL_UCS2 #if HECL_UCS2
return _wgetcwd(buf, maxlen); return _wgetcwd(buf, maxlen);
#else #else
@ -208,7 +208,7 @@ static inline SystemChar* Getcwd(SystemChar* buf, int maxlen) {
SystemString GetcwdStr(); SystemString GetcwdStr();
static inline bool IsAbsolute(SystemStringView path) { inline bool IsAbsolute(SystemStringView path) {
#if _WIN32 #if _WIN32
if (path.size() && (path[0] == _SYS_STR('\\') || path[0] == _SYS_STR('/'))) if (path.size() && (path[0] == _SYS_STR('\\') || path[0] == _SYS_STR('/')))
return true; return true;
@ -228,7 +228,7 @@ int RunProcess(const SystemChar* path, const SystemChar* const args[]);
#endif #endif
enum class FileLockType { None = 0, Read, Write }; enum class FileLockType { None = 0, Read, Write };
static inline FILE* Fopen(const SystemChar* path, const SystemChar* mode, FileLockType lock = FileLockType::None) { inline FILE* Fopen(const SystemChar* path, const SystemChar* mode, FileLockType lock = FileLockType::None) {
#if HECL_UCS2 #if HECL_UCS2
FILE* fp = _wfopen(path, mode); FILE* fp = _wfopen(path, mode);
if (!fp) if (!fp)
@ -246,14 +246,14 @@ static inline FILE* Fopen(const SystemChar* path, const SystemChar* mode, FileLo
&ov); &ov);
#else #else
if (flock(fileno(fp), ((lock == FileLockType::Write) ? LOCK_EX : LOCK_SH) | LOCK_NB)) if (flock(fileno(fp), ((lock == FileLockType::Write) ? LOCK_EX : LOCK_SH) | LOCK_NB))
LogModule.report(logvisor::Error, "flock %s: %s", path, strerror(errno)); LogModule.report(logvisor::Error, fmt("flock {}: {}"), path, strerror(errno));
#endif #endif
} }
return fp; return fp;
} }
static inline int FSeek(FILE* fp, int64_t offset, int whence) { inline int FSeek(FILE* fp, int64_t offset, int whence) {
#if _WIN32 #if _WIN32
return _fseeki64(fp, offset, whence); return _fseeki64(fp, offset, whence);
#elif __APPLE__ || __FreeBSD__ #elif __APPLE__ || __FreeBSD__
@ -263,7 +263,7 @@ static inline int FSeek(FILE* fp, int64_t offset, int whence) {
#endif #endif
} }
static inline int64_t FTell(FILE* fp) { inline int64_t FTell(FILE* fp) {
#if _WIN32 #if _WIN32
return _ftelli64(fp); return _ftelli64(fp);
#elif __APPLE__ || __FreeBSD__ #elif __APPLE__ || __FreeBSD__
@ -273,7 +273,7 @@ static inline int64_t FTell(FILE* fp) {
#endif #endif
} }
static inline int Rename(const SystemChar* oldpath, const SystemChar* newpath) { inline int Rename(const SystemChar* oldpath, const SystemChar* newpath) {
#if HECL_UCS2 #if HECL_UCS2
// return _wrename(oldpath, newpath); // return _wrename(oldpath, newpath);
return MoveFileExW(oldpath, newpath, MOVEFILE_REPLACE_EXISTING | MOVEFILE_WRITE_THROUGH) == 0; return MoveFileExW(oldpath, newpath, MOVEFILE_REPLACE_EXISTING | MOVEFILE_WRITE_THROUGH) == 0;
@ -282,7 +282,7 @@ static inline int Rename(const SystemChar* oldpath, const SystemChar* newpath) {
#endif #endif
} }
static inline int Stat(const SystemChar* path, Sstat* statOut) { inline int Stat(const SystemChar* path, Sstat* statOut) {
#if HECL_UCS2 #if HECL_UCS2
size_t pos; size_t pos;
for (pos = 0; pos < 3 && path[pos] != L'\0'; ++pos) {} for (pos = 0; pos < 3 && path[pos] != L'\0'; ++pos) {}
@ -296,52 +296,7 @@ static inline int Stat(const SystemChar* path, Sstat* statOut) {
#endif #endif
} }
#if __GNUC__ inline int StrCmp(const SystemChar* str1, const SystemChar* str2) {
__attribute__((__format__(__printf__, 1, 2)))
#endif
static inline void
Printf(const SystemChar* format, ...) {
va_list va;
va_start(va, format);
#if HECL_UCS2
vwprintf(format, va);
#else
vprintf(format, va);
#endif
va_end(va);
}
#if __GNUC__
__attribute__((__format__(__printf__, 2, 3)))
#endif
static inline void
FPrintf(FILE* fp, const SystemChar* format, ...) {
va_list va;
va_start(va, format);
#if HECL_UCS2
vfwprintf(fp, format, va);
#else
vfprintf(fp, format, va);
#endif
va_end(va);
}
#if __GNUC__
__attribute__((__format__(__printf__, 3, 4)))
#endif
static inline void
SNPrintf(SystemChar* str, size_t maxlen, const SystemChar* format, ...) {
va_list va;
va_start(va, format);
#if HECL_UCS2
_vsnwprintf(str, maxlen, format, va);
#else
vsnprintf(str, maxlen, format, va);
#endif
va_end(va);
}
static inline int StrCmp(const SystemChar* str1, const SystemChar* str2) {
if (!str1 || !str2) if (!str1 || !str2)
return str1 != str2; return str1 != str2;
#if HECL_UCS2 #if HECL_UCS2
@ -351,7 +306,7 @@ static inline int StrCmp(const SystemChar* str1, const SystemChar* str2) {
#endif #endif
} }
static inline int StrNCmp(const SystemChar* str1, const SystemChar* str2, size_t count) { inline int StrNCmp(const SystemChar* str1, const SystemChar* str2, size_t count) {
if (!str1 || !str2) if (!str1 || !str2)
return str1 != str2; return str1 != str2;
#if HECL_UCS2 #if HECL_UCS2
@ -361,7 +316,7 @@ static inline int StrNCmp(const SystemChar* str1, const SystemChar* str2, size_t
#endif #endif
} }
static inline int StrCaseCmp(const SystemChar* str1, const SystemChar* str2) { inline int StrCaseCmp(const SystemChar* str1, const SystemChar* str2) {
if (!str1 || !str2) if (!str1 || !str2)
return str1 != str2; return str1 != str2;
#if HECL_UCS2 #if HECL_UCS2
@ -371,7 +326,7 @@ static inline int StrCaseCmp(const SystemChar* str1, const SystemChar* str2) {
#endif #endif
} }
static inline unsigned long StrToUl(const SystemChar* str, SystemChar** endPtr, int base) { inline unsigned long StrToUl(const SystemChar* str, SystemChar** endPtr, int base) {
#if HECL_UCS2 #if HECL_UCS2
return wcstoul(str, endPtr, base); return wcstoul(str, endPtr, base);
#else #else
@ -379,46 +334,28 @@ static inline unsigned long StrToUl(const SystemChar* str, SystemChar** endPtr,
#endif #endif
} }
#define FORMAT_BUF_SZ 1024 inline bool CheckFreeSpace(const SystemChar* path, size_t reqSz) {
#if __GNUC__
__attribute__((__format__(__printf__, 1, 2)))
#endif
SystemString
SysFormat(const SystemChar* format, ...);
#if __GNUC__
__attribute__((__format__(__printf__, 1, 2)))
#endif
std::string
Format(const char* format, ...);
std::wstring WideFormat(const wchar_t* format, ...);
std::u16string Char16Format(const wchar_t* format, ...);
static inline bool CheckFreeSpace(const SystemChar* path, size_t reqSz) {
#if _WIN32 #if _WIN32
ULARGE_INTEGER freeBytes; ULARGE_INTEGER freeBytes;
wchar_t buf[1024]; wchar_t buf[1024];
wchar_t* end; wchar_t* end;
DWORD ret = GetFullPathNameW(path, 1024, buf, &end); DWORD ret = GetFullPathNameW(path, 1024, buf, &end);
if (!ret || ret > 1024) if (!ret || ret > 1024)
LogModule.report(logvisor::Fatal, _SYS_STR("GetFullPathNameW %s"), path); LogModule.report(logvisor::Fatal, fmt(_SYS_STR("GetFullPathNameW %s")), path);
if (end) if (end)
end[0] = L'\0'; end[0] = L'\0';
if (!GetDiskFreeSpaceExW(buf, &freeBytes, nullptr, nullptr)) if (!GetDiskFreeSpaceExW(buf, &freeBytes, nullptr, nullptr))
LogModule.report(logvisor::Fatal, _SYS_STR("GetDiskFreeSpaceExW %s: %d"), path, GetLastError()); LogModule.report(logvisor::Fatal, fmt(_SYS_STR("GetDiskFreeSpaceExW %s: %d")), path, GetLastError());
return reqSz < freeBytes.QuadPart; return reqSz < freeBytes.QuadPart;
#else #else
struct statvfs svfs; struct statvfs svfs;
if (statvfs(path, &svfs)) if (statvfs(path, &svfs))
LogModule.report(logvisor::Fatal, "statvfs %s: %s", path, strerror(errno)); LogModule.report(logvisor::Fatal, fmt("statvfs {}: {}"), path, strerror(errno));
return reqSz < svfs.f_frsize * svfs.f_bavail; return reqSz < svfs.f_frsize * svfs.f_bavail;
#endif #endif
} }
static inline bool PathRelative(const SystemChar* path) { inline bool PathRelative(const SystemChar* path) {
if (!path || !path[0]) if (!path || !path[0])
return false; return false;
#if _WIN32 && !WINDOWS_STORE #if _WIN32 && !WINDOWS_STORE
@ -428,7 +365,7 @@ static inline bool PathRelative(const SystemChar* path) {
#endif #endif
} }
static inline int ConsoleWidth(bool* ok = nullptr) { inline int ConsoleWidth(bool* ok = nullptr) {
int retval = 80; int retval = 80;
#if _WIN32 #if _WIN32
#if !WINDOWS_STORE #if !WINDOWS_STORE
@ -640,8 +577,7 @@ public:
return SystemString(beginIt, absPathForward.cend()); return SystemString(beginIt, absPathForward.cend());
} }
} }
LogModule.report(logvisor::Fatal, "unable to resolve '%s' as project relative '%s'", absPath.data(), LogModule.report(logvisor::Fatal, fmt("unable to resolve '{}' as project relative '{}'"), absPath, m_projRoot);
m_projRoot.c_str());
return SystemString(); return SystemString();
} }
@ -813,7 +749,7 @@ public:
*/ */
ProjectPath getParentPath() const { ProjectPath getParentPath() const {
if (m_relPath == _SYS_STR(".")) if (m_relPath == _SYS_STR("."))
LogModule.report(logvisor::Fatal, "attempted to resolve parent of root project path"); LogModule.report(logvisor::Fatal, fmt("attempted to resolve parent of root project path"));
size_t pos = m_relPath.rfind(_SYS_STR('/')); size_t pos = m_relPath.rfind(_SYS_STR('/'));
if (pos == SystemString::npos) if (pos == SystemString::npos)
return ProjectPath(*m_proj, _SYS_STR("")); return ProjectPath(*m_proj, _SYS_STR(""));
@ -1082,7 +1018,7 @@ public:
*/ */
Database::Project& getProject() const { Database::Project& getProject() const {
if (!m_proj) if (!m_proj)
LogModule.report(logvisor::Fatal, "ProjectPath::getProject() called on unqualified path"); LogModule.report(logvisor::Fatal, fmt("ProjectPath::getProject() called on unqualified path"));
return *m_proj; return *m_proj;
} }
@ -1214,7 +1150,7 @@ bool IsPathYAML(const hecl::ProjectPath& path);
/* Type-sensitive byte swappers */ /* Type-sensitive byte swappers */
template <typename T> template <typename T>
static inline T bswap16(T val) { constexpr T bswap16(T val) {
#if __GNUC__ #if __GNUC__
return __builtin_bswap16(val); return __builtin_bswap16(val);
#elif _WIN32 #elif _WIN32
@ -1225,7 +1161,7 @@ static inline T bswap16(T val) {
} }
template <typename T> template <typename T>
static inline T bswap32(T val) { constexpr T bswap32(T val) {
#if __GNUC__ #if __GNUC__
return __builtin_bswap32(val); return __builtin_bswap32(val);
#elif _WIN32 #elif _WIN32
@ -1238,7 +1174,7 @@ static inline T bswap32(T val) {
} }
template <typename T> template <typename T>
static inline T bswap64(T val) { constexpr T bswap64(T val) {
#if __GNUC__ #if __GNUC__
return __builtin_bswap64(val); return __builtin_bswap64(val);
#elif _WIN32 #elif _WIN32
@ -1252,18 +1188,18 @@ static inline T bswap64(T val) {
} }
#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ #if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
static inline int16_t SBig(int16_t val) { return bswap16(val); } constexpr int16_t SBig(int16_t val) { return bswap16(val); }
static inline uint16_t SBig(uint16_t val) { return bswap16(val); } constexpr uint16_t SBig(uint16_t val) { return bswap16(val); }
static inline int32_t SBig(int32_t val) { return bswap32(val); } constexpr int32_t SBig(int32_t val) { return bswap32(val); }
static inline uint32_t SBig(uint32_t val) { return bswap32(val); } constexpr uint32_t SBig(uint32_t val) { return bswap32(val); }
static inline int64_t SBig(int64_t val) { return bswap64(val); } constexpr int64_t SBig(int64_t val) { return bswap64(val); }
static inline uint64_t SBig(uint64_t val) { return bswap64(val); } constexpr uint64_t SBig(uint64_t val) { return bswap64(val); }
inline float SBig(float val) { constexpr float SBig(float val) {
union { float f; atInt32 i; } uval1 = {val}; union { float f; atInt32 i; } uval1 = {val};
union { atInt32 i; float f; } uval2 = {bswap32(uval1.i)}; union { atInt32 i; float f; } uval2 = {bswap32(uval1.i)};
return uval2.f; return uval2.f;
} }
inline double SBig(double val) { constexpr double SBig(double val) {
union { double f; atInt64 i; } uval1 = {val}; union { double f; atInt64 i; } uval1 = {val};
union { atInt64 i; double f; } uval2 = {bswap64(uval1.i)}; union { atInt64 i; double f; } uval2 = {bswap64(uval1.i)};
return uval2.f; return uval2.f;
@ -1272,29 +1208,29 @@ inline double SBig(double val) {
#define SBIG(q) (((q)&0x000000FF) << 24 | ((q)&0x0000FF00) << 8 | ((q)&0x00FF0000) >> 8 | ((q)&0xFF000000) >> 24) #define SBIG(q) (((q)&0x000000FF) << 24 | ((q)&0x0000FF00) << 8 | ((q)&0x00FF0000) >> 8 | ((q)&0xFF000000) >> 24)
#endif #endif
static inline int16_t SLittle(int16_t val) { return val; } constexpr int16_t SLittle(int16_t val) { return val; }
static inline uint16_t SLittle(uint16_t val) { return val; } constexpr uint16_t SLittle(uint16_t val) { return val; }
static inline int32_t SLittle(int32_t val) { return val; } constexpr int32_t SLittle(int32_t val) { return val; }
static inline uint32_t SLittle(uint32_t val) { return val; } constexpr uint32_t SLittle(uint32_t val) { return val; }
static inline int64_t SLittle(int64_t val) { return val; } constexpr int64_t SLittle(int64_t val) { return val; }
static inline uint64_t SLittle(uint64_t val) { return val; } constexpr uint64_t SLittle(uint64_t val) { return val; }
static inline float SLittle(float val) { return val; } constexpr float SLittle(float val) { return val; }
static inline double SLittle(double val) { return val; } constexpr double SLittle(double val) { return val; }
#ifndef SLITTLE #ifndef SLITTLE
#define SLITTLE(q) (q) #define SLITTLE(q) (q)
#endif #endif
#else #else
static inline int16_t SLittle(int16_t val) { return bswap16(val); } constexpr int16_t SLittle(int16_t val) { return bswap16(val); }
static inline uint16_t SLittle(uint16_t val) { return bswap16(val); } constexpr uint16_t SLittle(uint16_t val) { return bswap16(val); }
static inline int32_t SLittle(int32_t val) { return bswap32(val); } constexpr int32_t SLittle(int32_t val) { return bswap32(val); }
static inline uint32_t SLittle(uint32_t val) { return bswap32(val); } constexpr uint32_t SLittle(uint32_t val) { return bswap32(val); }
static inline int64_t SLittle(int64_t val) { return bswap64(val); } constexpr int64_t SLittle(int64_t val) { return bswap64(val); }
static inline uint64_t SLittle(uint64_t val) { return bswap64(val); } constexpr uint64_t SLittle(uint64_t val) { return bswap64(val); }
static inline float SLittle(float val) { constexpr float SLittle(float val) {
int32_t ival = bswap32(*((int32_t*)(&val))); int32_t ival = bswap32(*((int32_t*)(&val)));
return *((float*)(&ival)); return *((float*)(&ival));
} }
static inline double SLittle(double val) { constexpr double SLittle(double val) {
int64_t ival = bswap64(*((int64_t*)(&val))); int64_t ival = bswap64(*((int64_t*)(&val)));
return *((double*)(&ival)); return *((double*)(&ival));
} }
@ -1302,14 +1238,14 @@ static inline double SLittle(double val) {
#define SLITTLE(q) (((q)&0x000000FF) << 24 | ((q)&0x0000FF00) << 8 | ((q)&0x00FF0000) >> 8 | ((q)&0xFF000000) >> 24) #define SLITTLE(q) (((q)&0x000000FF) << 24 | ((q)&0x0000FF00) << 8 | ((q)&0x00FF0000) >> 8 | ((q)&0xFF000000) >> 24)
#endif #endif
static inline int16_t SBig(int16_t val) { return val; } constexpr int16_t SBig(int16_t val) { return val; }
static inline uint16_t SBig(uint16_t val) { return val; } constexpr uint16_t SBig(uint16_t val) { return val; }
static inline int32_t SBig(int32_t val) { return val; } constexpr int32_t SBig(int32_t val) { return val; }
static inline uint32_t SBig(uint32_t val) { return val; } constexpr uint32_t SBig(uint32_t val) { return val; }
static inline int64_t SBig(int64_t val) { return val; } constexpr int64_t SBig(int64_t val) { return val; }
static inline uint64_t SBig(uint64_t val) { return val; } constexpr uint64_t SBig(uint64_t val) { return val; }
static inline float SBig(float val) { return val; } constexpr float SBig(float val) { return val; }
static inline double SBig(double val) { return val; } constexpr double SBig(double val) { return val; }
#ifndef SBIG #ifndef SBIG
#define SBIG(q) (q) #define SBIG(q) (q)
#endif #endif
@ -1332,3 +1268,6 @@ struct hash<hecl::Hash> {
size_t operator()(const hecl::Hash& val) const noexcept { return val.valSizeT(); } size_t operator()(const hecl::Hash& val) const noexcept { return val.valSizeT(); }
}; };
} // namespace std } // namespace std
FMT_CUSTOM_FORMATTER(hecl::SystemUTF8Conv, fmt("{}"), obj.str())
FMT_CUSTOM_FORMATTER(hecl::SystemStringConv, fmt("{}"), obj.sys_str())

View File

@ -34,15 +34,3 @@ inline void* memmem(const void* haystack, size_t hlen, const void* needle, size_
return NULL; return NULL;
} }
#endif #endif
inline int asprintf(char** buf, const char* format, ...) {
va_list ap;
va_start(ap, format);
int len = vsnprintf(nullptr, 0, format, ap);
va_end(ap);
*buf = (char*)malloc(len + 1);
va_start(ap, format);
vsnprintf(*buf, len + 1, format, ap);
va_end(ap);
return len;
}

View File

@ -62,7 +62,7 @@ extern "C" size_t HECL_STARTUP_SZ;
static void InstallBlendershell(const SystemChar* path) { static void InstallBlendershell(const SystemChar* path) {
FILE* fp = hecl::Fopen(path, _SYS_STR("w")); FILE* fp = hecl::Fopen(path, _SYS_STR("w"));
if (!fp) if (!fp)
BlenderLog.report(logvisor::Fatal, _SYS_STR("unable to open %s for writing"), path); BlenderLog.report(logvisor::Fatal, fmt(_SYS_STR("unable to open {} for writing")), path);
fwrite(HECL_BLENDERSHELL, 1, HECL_BLENDERSHELL_SZ, fp); fwrite(HECL_BLENDERSHELL, 1, HECL_BLENDERSHELL_SZ, fp);
fclose(fp); fclose(fp);
} }
@ -70,7 +70,7 @@ static void InstallBlendershell(const SystemChar* path) {
static void InstallAddon(const SystemChar* path) { static void InstallAddon(const SystemChar* path) {
FILE* fp = hecl::Fopen(path, _SYS_STR("wb")); FILE* fp = hecl::Fopen(path, _SYS_STR("wb"));
if (!fp) if (!fp)
BlenderLog.report(logvisor::Fatal, _SYS_STR("Unable to install blender addon at '%s'"), path); BlenderLog.report(logvisor::Fatal, fmt(_SYS_STR("Unable to install blender addon at '{}'")), path);
fwrite(HECL_ADDON, 1, HECL_ADDON_SZ, fp); fwrite(HECL_ADDON, 1, HECL_ADDON_SZ, fp);
fclose(fp); fclose(fp);
} }
@ -109,20 +109,20 @@ uint32_t Connection::_readStr(char* buf, uint32_t bufSz) {
uint32_t readLen; uint32_t readLen;
int ret = Read(m_readpipe[0], &readLen, 4); int ret = Read(m_readpipe[0], &readLen, 4);
if (ret < 4) { if (ret < 4) {
BlenderLog.report(logvisor::Error, "Pipe error %d %s", ret, strerror(errno)); BlenderLog.report(logvisor::Error, fmt("Pipe error {} {}"), ret, strerror(errno));
_blenderDied(); _blenderDied();
return 0; return 0;
} }
if (readLen >= bufSz) { if (readLen >= bufSz) {
BlenderLog.report(logvisor::Fatal, "Pipe buffer overrun [%d/%d]", readLen, bufSz); BlenderLog.report(logvisor::Fatal, fmt("Pipe buffer overrun [{}/{}]"), readLen, bufSz);
*buf = '\0'; *buf = '\0';
return 0; return 0;
} }
ret = Read(m_readpipe[0], buf, readLen); ret = Read(m_readpipe[0], buf, readLen);
if (ret < 0) { if (ret < 0) {
BlenderLog.report(logvisor::Fatal, strerror(errno)); BlenderLog.report(logvisor::Fatal, fmt("{}"), strerror(errno));
return 0; return 0;
} else if (readLen >= 9) { } else if (readLen >= 9) {
if (!memcmp(buf, "EXCEPTION", std::min(readLen, uint32_t(9)))) { if (!memcmp(buf, "EXCEPTION", std::min(readLen, uint32_t(9)))) {
@ -209,10 +209,10 @@ void Connection::_blenderDied() {
std::unique_ptr<char[]> buf(new char[len + 1]); std::unique_ptr<char[]> buf(new char[len + 1]);
memset(buf.get(), 0, len + 1); memset(buf.get(), 0, len + 1);
fread(buf.get(), 1, len, errFp); fread(buf.get(), 1, len, errFp);
BlenderLog.report(logvisor::Fatal, "\n%.*s", int(len), buf.get()); BlenderLog.report(logvisor::Fatal, fmt("\n{:.{}s}"), buf.get(), len);
} }
} }
BlenderLog.report(logvisor::Fatal, "Blender Exception"); BlenderLog.report(logvisor::Fatal, fmt("Blender Exception"));
} }
static std::atomic_bool BlenderFirstInit(false); static std::atomic_bool BlenderFirstInit(false);
@ -229,7 +229,7 @@ static bool RegFileExists(const hecl::SystemChar* path) {
Connection::Connection(int verbosityLevel) { Connection::Connection(int verbosityLevel) {
#if !WINDOWS_STORE #if !WINDOWS_STORE
if (hecl::VerbosityLevel >= 1) if (hecl::VerbosityLevel >= 1)
BlenderLog.report(logvisor::Info, "Establishing BlenderConnection..."); BlenderLog.report(logvisor::Info, fmt("Establishing BlenderConnection..."));
/* Put hecl_blendershell.py in temp dir */ /* Put hecl_blendershell.py in temp dir */
const SystemChar* TMPDIR = GetTmpDir(); const SystemChar* TMPDIR = GetTmpDir();
@ -263,20 +263,20 @@ Connection::Connection(int verbosityLevel) {
SECURITY_ATTRIBUTES sattrs = {sizeof(SECURITY_ATTRIBUTES), NULL, TRUE}; SECURITY_ATTRIBUTES sattrs = {sizeof(SECURITY_ATTRIBUTES), NULL, TRUE};
HANDLE consoleOutReadTmp, consoleOutWrite, consoleErrWrite, consoleOutRead; HANDLE consoleOutReadTmp, consoleOutWrite, consoleErrWrite, consoleOutRead;
if (!CreatePipe(&consoleOutReadTmp, &consoleOutWrite, &sattrs, 1024)) if (!CreatePipe(&consoleOutReadTmp, &consoleOutWrite, &sattrs, 1024))
BlenderLog.report(logvisor::Fatal, "Error with CreatePipe"); BlenderLog.report(logvisor::Fatal, fmt("Error with CreatePipe"));
if (!DuplicateHandle(GetCurrentProcess(), consoleOutWrite, GetCurrentProcess(), &consoleErrWrite, 0, TRUE, if (!DuplicateHandle(GetCurrentProcess(), consoleOutWrite, GetCurrentProcess(), &consoleErrWrite, 0, TRUE,
DUPLICATE_SAME_ACCESS)) DUPLICATE_SAME_ACCESS))
BlenderLog.report(logvisor::Fatal, "Error with DuplicateHandle"); BlenderLog.report(logvisor::Fatal, fmt("Error with DuplicateHandle"));
if (!DuplicateHandle(GetCurrentProcess(), consoleOutReadTmp, GetCurrentProcess(), if (!DuplicateHandle(GetCurrentProcess(), consoleOutReadTmp, GetCurrentProcess(),
&consoleOutRead, // Address of new handle. &consoleOutRead, // Address of new handle.
0, FALSE, // Make it uninheritable. 0, FALSE, // Make it uninheritable.
DUPLICATE_SAME_ACCESS)) DUPLICATE_SAME_ACCESS))
BlenderLog.report(logvisor::Fatal, "Error with DupliateHandle"); BlenderLog.report(logvisor::Fatal, fmt("Error with DupliateHandle"));
if (!CloseHandle(consoleOutReadTmp)) if (!CloseHandle(consoleOutReadTmp))
BlenderLog.report(logvisor::Fatal, "Error with CloseHandle"); BlenderLog.report(logvisor::Fatal, fmt("Error with CloseHandle"));
#else #else
pipe(m_readpipe); pipe(m_readpipe);
pipe(m_writepipe); pipe(m_writepipe);
@ -359,13 +359,13 @@ Connection::Connection(int verbosityLevel) {
if (err == ERROR_BROKEN_PIPE) if (err == ERROR_BROKEN_PIPE)
break; // pipe done - normal exit path. break; // pipe done - normal exit path.
else else
BlenderLog.report(logvisor::Error, "Error with ReadFile: %08X", err); // Something bad happened. BlenderLog.report(logvisor::Error, fmt("Error with ReadFile: %08X"), err); // Something bad happened.
} }
// Display the character read on the screen. // Display the character read on the screen.
auto lk = logvisor::LockLog(); auto lk = logvisor::LockLog();
if (!WriteConsoleA(GetStdHandle(STD_OUTPUT_HANDLE), lpBuffer, nBytesRead, &nCharsWritten, NULL)) { if (!WriteConsoleA(GetStdHandle(STD_OUTPUT_HANDLE), lpBuffer, nBytesRead, &nCharsWritten, NULL)) {
// BlenderLog.report(logvisor::Error, "Error with WriteConsole: %08X", GetLastError()); // BlenderLog.report(logvisor::Error, fmt("Error with WriteConsole: %08X"), GetLastError());
} }
} }
@ -390,21 +390,18 @@ Connection::Connection(int verbosityLevel) {
close(devNull); close(devNull);
} }
char errbuf[256]; std::string errbuf;
char readfds[32]; std::string readfds = fmt::format(fmt("{}"), m_writepipe[0]);
snprintf(readfds, 32, "%d", m_writepipe[0]); std::string writefds = fmt::format(fmt("{}"), m_readpipe[1]);
char writefds[32]; std::string vLevel = fmt::format(fmt("{}"), verbosityLevel);
snprintf(writefds, 32, "%d", m_readpipe[1]);
char vLevel[32];
snprintf(vLevel, 32, "%d", verbosityLevel);
/* Try user-specified blender first */ /* Try user-specified blender first */
if (blenderBin) { if (blenderBin) {
execlp(blenderBin, blenderBin, "--background", "-P", blenderShellPath.c_str(), "--", readfds, writefds, vLevel, execlp(blenderBin, blenderBin, "--background", "-P", blenderShellPath.c_str(), "--",
blenderAddonPath.c_str(), NULL); readfds.c_str(), writefds.c_str(), vLevel.c_str(), blenderAddonPath.c_str(), NULL);
if (errno != ENOENT) { if (errno != ENOENT) {
snprintf(errbuf, 256, "NOLAUNCH %s", strerror(errno)); errbuf = fmt::format(fmt("NOLAUNCH {}"), strerror(errno));
_writeStr(errbuf, strlen(errbuf), m_readpipe[1]); _writeStr(errbuf.c_str(), errbuf.size(), m_readpipe[1]);
exit(1); exit(1);
} }
} }
@ -418,21 +415,21 @@ Connection::Connection(int verbosityLevel) {
steamBlender += "/blender"; steamBlender += "/blender";
#endif #endif
blenderBin = steamBlender.c_str(); blenderBin = steamBlender.c_str();
execlp(blenderBin, blenderBin, "--background", "-P", blenderShellPath.c_str(), "--", readfds, writefds, vLevel, execlp(blenderBin, blenderBin, "--background", "-P", blenderShellPath.c_str(), "--",
blenderAddonPath.c_str(), NULL); readfds.c_str(), writefds.c_str(), vLevel.c_str(), blenderAddonPath.c_str(), NULL);
if (errno != ENOENT) { if (errno != ENOENT) {
snprintf(errbuf, 256, "NOLAUNCH %s", strerror(errno)); errbuf = fmt::format(fmt("NOLAUNCH {}"), strerror(errno));
_writeStr(errbuf, strlen(errbuf), m_readpipe[1]); _writeStr(errbuf.c_str(), errbuf.size(), m_readpipe[1]);
exit(1); exit(1);
} }
} }
/* Otherwise default blender */ /* Otherwise default blender */
execlp(DEFAULT_BLENDER_BIN, DEFAULT_BLENDER_BIN, "--background", "-P", blenderShellPath.c_str(), "--", readfds, execlp(DEFAULT_BLENDER_BIN, DEFAULT_BLENDER_BIN, "--background", "-P", blenderShellPath.c_str(), "--",
writefds, vLevel, blenderAddonPath.c_str(), NULL); readfds.c_str(), writefds.c_str(), vLevel.c_str(), blenderAddonPath.c_str(), NULL);
if (errno != ENOENT) { if (errno != ENOENT) {
snprintf(errbuf, 256, "NOLAUNCH %s", strerror(errno)); errbuf = fmt::format(fmt("NOLAUNCH {}"), strerror(errno));
_writeStr(errbuf, strlen(errbuf), m_readpipe[1]); _writeStr(errbuf.c_str(), errbuf.size(), m_readpipe[1]);
exit(1); exit(1);
} }
@ -448,10 +445,10 @@ Connection::Connection(int verbosityLevel) {
/* Stash error path and unlink existing file */ /* Stash error path and unlink existing file */
#if _WIN32 #if _WIN32
m_errPath = hecl::SystemString(TMPDIR) + m_errPath = hecl::SystemString(TMPDIR) +
hecl::SysFormat(_SYS_STR("/hecl_%016llX.derp"), (unsigned long long)m_pinfo.dwProcessId); fmt::format(fmt(_SYS_STR("/hecl_{:016X}.derp")), (unsigned long long)m_pinfo.dwProcessId);
#else #else
m_errPath = m_errPath =
hecl::SystemString(TMPDIR) + hecl::SysFormat(_SYS_STR("/hecl_%016llX.derp"), (unsigned long long)m_blenderProc); hecl::SystemString(TMPDIR) + fmt::format(fmt(_SYS_STR("/hecl_{:016X}.derp")), (unsigned long long)m_blenderProc);
#endif #endif
hecl::Unlink(m_errPath.c_str()); hecl::Unlink(m_errPath.c_str());
@ -461,24 +458,24 @@ Connection::Connection(int verbosityLevel) {
if (!strncmp(lineBuf, "NOLAUNCH", 8)) { if (!strncmp(lineBuf, "NOLAUNCH", 8)) {
_closePipe(); _closePipe();
BlenderLog.report(logvisor::Fatal, "Unable to launch blender: %s", lineBuf + 9); BlenderLog.report(logvisor::Fatal, fmt("Unable to launch blender: {}"), lineBuf + 9);
} else if (!strncmp(lineBuf, "NOBLENDER", 9)) { } else if (!strncmp(lineBuf, "NOBLENDER", 9)) {
_closePipe(); _closePipe();
if (blenderBin) if (blenderBin)
BlenderLog.report(logvisor::Fatal, _SYS_STR("Unable to find blender at '%s' or '%s'"), blenderBin, BlenderLog.report(logvisor::Fatal, fmt(_SYS_STR("Unable to find blender at '{}' or '{}'")), blenderBin,
DEFAULT_BLENDER_BIN); DEFAULT_BLENDER_BIN);
else else
BlenderLog.report(logvisor::Fatal, _SYS_STR("Unable to find blender at '%s'"), DEFAULT_BLENDER_BIN); BlenderLog.report(logvisor::Fatal, fmt(_SYS_STR("Unable to find blender at '{}'")), DEFAULT_BLENDER_BIN);
} else if (!strcmp(lineBuf, "NOT280")) { } else if (!strcmp(lineBuf, "NOT280")) {
_closePipe(); _closePipe();
BlenderLog.report(logvisor::Fatal, _SYS_STR("Installed blender version must be >= 2.80")); BlenderLog.report(logvisor::Fatal, fmt(_SYS_STR("Installed blender version must be >= 2.80")));
} else if (!strcmp(lineBuf, "NOADDON")) { } else if (!strcmp(lineBuf, "NOADDON")) {
_closePipe(); _closePipe();
if (blenderAddonPath != _SYS_STR("SKIPINSTALL")) if (blenderAddonPath != _SYS_STR("SKIPINSTALL"))
InstallAddon(blenderAddonPath.c_str()); InstallAddon(blenderAddonPath.c_str());
++installAttempt; ++installAttempt;
if (installAttempt >= 2) if (installAttempt >= 2)
BlenderLog.report(logvisor::Fatal, _SYS_STR("unable to install blender addon using '%s'"), BlenderLog.report(logvisor::Fatal, fmt(_SYS_STR("unable to install blender addon using '{}'")),
blenderAddonPath.c_str()); blenderAddonPath.c_str());
continue; continue;
} else if (!strcmp(lineBuf, "ADDONINSTALLED")) { } else if (!strcmp(lineBuf, "ADDONINSTALLED")) {
@ -487,14 +484,14 @@ Connection::Connection(int verbosityLevel) {
continue; continue;
} else if (strcmp(lineBuf, "READY")) { } else if (strcmp(lineBuf, "READY")) {
_closePipe(); _closePipe();
BlenderLog.report(logvisor::Fatal, "read '%s' from blender; expected 'READY'", lineBuf); BlenderLog.report(logvisor::Fatal, fmt("read '{}' from blender; expected 'READY'"), lineBuf);
} }
_writeStr("ACK"); _writeStr("ACK");
break; break;
} }
#else #else
BlenderLog.report(logvisor::Fatal, "BlenderConnection not available on UWP"); BlenderLog.report(logvisor::Fatal, fmt("BlenderConnection not available on UWP"));
#endif #endif
} }
@ -510,13 +507,13 @@ void Boolean::read(Connection& conn) { conn._readBuf(&val, 1); }
std::streambuf::int_type PyOutStream::StreamBuf::overflow(int_type ch) { std::streambuf::int_type PyOutStream::StreamBuf::overflow(int_type ch) {
if (!m_parent.m_parent || !m_parent.m_parent->m_lock) if (!m_parent.m_parent || !m_parent.m_parent->m_lock)
BlenderLog.report(logvisor::Fatal, "lock not held for PyOutStream writing"); BlenderLog.report(logvisor::Fatal, fmt("lock not held for PyOutStream writing"));
if (ch != traits_type::eof() && ch != '\n' && ch != '\0') { if (ch != traits_type::eof() && ch != '\n' && ch != '\0') {
m_lineBuf += char_type(ch); m_lineBuf += char_type(ch);
return ch; return ch;
} }
// printf("FLUSHING %s\n", m_lineBuf.c_str()); // printf("FLUSHING %s\n", m_lineBuf.c_str());
m_parent.m_parent->_writeStr(m_lineBuf.c_str()); m_parent.m_parent->_writeStr(m_lineBuf);
char readBuf[16]; char readBuf[16];
m_parent.m_parent->_readStr(readBuf, 16); m_parent.m_parent->_readStr(readBuf, 16);
if (strcmp(readBuf, "OK")) { if (strcmp(readBuf, "OK")) {
@ -533,10 +530,10 @@ static const char* BlendTypeStrs[] = {"NONE", "MESH", "CMESH", "ACTOR"
bool Connection::createBlend(const ProjectPath& path, BlendType type) { bool Connection::createBlend(const ProjectPath& path, BlendType type) {
if (m_lock) { if (m_lock) {
BlenderLog.report(logvisor::Fatal, "BlenderConnection::createBlend() musn't be called with stream active"); BlenderLog.report(logvisor::Fatal, fmt("BlenderConnection::createBlend() musn't be called with stream active"));
return false; return false;
} }
_writeStr(("CREATE \""s + path.getAbsolutePathUTF8().data() + "\" " + BlendTypeStrs[int(type)]).c_str()); _writeStr(fmt::format(fmt("CREATE \"{}\" {}"), path.getAbsolutePathUTF8(), BlendTypeStrs[int(type)]));
char lineBuf[256]; char lineBuf[256];
_readStr(lineBuf, sizeof(lineBuf)); _readStr(lineBuf, sizeof(lineBuf));
if (!strcmp(lineBuf, "FINISHED")) { if (!strcmp(lineBuf, "FINISHED")) {
@ -551,12 +548,12 @@ bool Connection::createBlend(const ProjectPath& path, BlendType type) {
bool Connection::openBlend(const ProjectPath& path, bool force) { bool Connection::openBlend(const ProjectPath& path, bool force) {
if (m_lock) { if (m_lock) {
BlenderLog.report(logvisor::Fatal, "BlenderConnection::openBlend() musn't be called with stream active"); BlenderLog.report(logvisor::Fatal, fmt("BlenderConnection::openBlend() musn't be called with stream active"));
return false; return false;
} }
if (!force && path == m_loadedBlend) if (!force && path == m_loadedBlend)
return true; return true;
_writeStr(("OPEN \""s + path.getAbsolutePathUTF8().data() + "\"").c_str()); _writeStr(fmt::format(fmt("OPEN \"{}\""), path.getAbsolutePathUTF8()));
char lineBuf[256]; char lineBuf[256];
_readStr(lineBuf, sizeof(lineBuf)); _readStr(lineBuf, sizeof(lineBuf));
if (!strcmp(lineBuf, "FINISHED")) { if (!strcmp(lineBuf, "FINISHED")) {
@ -586,7 +583,7 @@ bool Connection::openBlend(const ProjectPath& path, bool force) {
bool Connection::saveBlend() { bool Connection::saveBlend() {
if (m_lock) { if (m_lock) {
BlenderLog.report(logvisor::Fatal, "BlenderConnection::saveBlend() musn't be called with stream active"); BlenderLog.report(logvisor::Fatal, fmt("BlenderConnection::saveBlend() musn't be called with stream active"));
return false; return false;
} }
_writeStr("SAVE"); _writeStr("SAVE");
@ -600,7 +597,7 @@ bool Connection::saveBlend() {
void Connection::deleteBlend() { void Connection::deleteBlend() {
if (m_loadedBlend) { if (m_loadedBlend) {
hecl::Unlink(m_loadedBlend.getAbsolutePath().data()); hecl::Unlink(m_loadedBlend.getAbsolutePath().data());
BlenderLog.report(logvisor::Info, _SYS_STR("Deleted '%s'"), m_loadedBlend.getAbsolutePath().data()); BlenderLog.report(logvisor::Info, fmt(_SYS_STR("Deleted '{}'")), m_loadedBlend.getAbsolutePath());
m_loadedBlend = ProjectPath(); m_loadedBlend = ProjectPath();
} }
} }
@ -612,7 +609,7 @@ PyOutStream::PyOutStream(Connection* parent, bool deleteOnError)
char readBuf[16]; char readBuf[16];
m_parent->_readStr(readBuf, 16); m_parent->_readStr(readBuf, 16);
if (strcmp(readBuf, "READY")) if (strcmp(readBuf, "READY"))
BlenderLog.report(logvisor::Fatal, "unable to open PyOutStream with blender"); BlenderLog.report(logvisor::Fatal, fmt("unable to open PyOutStream with blender"));
} }
void PyOutStream::close() { void PyOutStream::close() {
@ -621,85 +618,62 @@ void PyOutStream::close() {
char readBuf[16]; char readBuf[16];
m_parent->_readStr(readBuf, 16); m_parent->_readStr(readBuf, 16);
if (strcmp(readBuf, "DONE")) if (strcmp(readBuf, "DONE"))
BlenderLog.report(logvisor::Fatal, "unable to close PyOutStream with blender"); BlenderLog.report(logvisor::Fatal, fmt("unable to close PyOutStream with blender"));
m_parent->m_pyStreamActive = false; m_parent->m_pyStreamActive = false;
m_parent->m_lock = false; m_parent->m_lock = false;
} }
} }
#if __GNUC__
__attribute__((__format__ (__printf__, 2, 3)))
#endif
void PyOutStream::format(const char* fmt, ...)
{
if (!m_parent || !m_parent->m_lock)
BlenderLog.report(logvisor::Fatal, "lock not held for PyOutStream::format()");
va_list ap;
va_start(ap, fmt);
char* result = nullptr;
#ifdef _WIN32
int length = _vscprintf(fmt, ap);
result = (char*)malloc(length);
vsnprintf(result, length, fmt, ap);
#else
int length = vasprintf(&result, fmt, ap);
#endif
va_end(ap);
if (length > 0)
this->write(result, length);
free(result);
}
void PyOutStream::linkBlend(const char* target, const char* objName, bool link) { void PyOutStream::linkBlend(const char* target, const char* objName, bool link) {
format( format(fmt(
"if '%s' not in bpy.data.scenes:\n" "if '{}' not in bpy.data.scenes:\n"
" with bpy.data.libraries.load('''%s''', link=%s, relative=True) as (data_from, data_to):\n" " with bpy.data.libraries.load('''{}''', link={}, relative=True) as (data_from, data_to):\n"
" data_to.scenes = data_from.scenes\n" " data_to.scenes = data_from.scenes\n"
" obj_scene = None\n" " obj_scene = None\n"
" for scene in data_to.scenes:\n" " for scene in data_to.scenes:\n"
" if scene.name == '%s':\n" " if scene.name == '{}':\n"
" obj_scene = scene\n" " obj_scene = scene\n"
" break\n" " break\n"
" if not obj_scene:\n" " if not obj_scene:\n"
" raise RuntimeError('''unable to find %s in %s. try deleting it and restart the extract.''')\n" " raise RuntimeError('''unable to find {} in {}. try deleting it and restart the extract.''')\n"
" obj = None\n" " obj = None\n"
" for object in obj_scene.objects:\n" " for object in obj_scene.objects:\n"
" if object.name == obj_scene.name:\n" " if object.name == obj_scene.name:\n"
" obj = object\n" " obj = object\n"
"else:\n" "else:\n"
" obj = bpy.data.objects['%s']\n" " obj = bpy.data.objects['{}']\n"
"\n", "\n"),
objName, target, link ? "True" : "False", objName, objName, target, objName); objName, target, link ? "True" : "False", objName, objName, target, objName);
} }
void PyOutStream::linkBackground(const char* target, const char* sceneName) { void PyOutStream::linkBackground(const char* target, const char* sceneName) {
if (!sceneName) { if (!sceneName) {
format( format(fmt(
"with bpy.data.libraries.load('''%s''', link=True, relative=True) as (data_from, data_to):\n" "with bpy.data.libraries.load('''{}''', link=True, relative=True) as (data_from, data_to):\n"
" data_to.scenes = data_from.scenes\n" " data_to.scenes = data_from.scenes\n"
"obj_scene = None\n" "obj_scene = None\n"
"for scene in data_to.scenes:\n" "for scene in data_to.scenes:\n"
" obj_scene = scene\n" " obj_scene = scene\n"
" break\n" " break\n"
"if not obj_scene:\n" "if not obj_scene:\n"
" raise RuntimeError('''unable to find %s. try deleting it and restart the extract.''')\n" " raise RuntimeError('''unable to find {}. try deleting it and restart the extract.''')\n"
"\n" "\n"
"bpy.context.scene.background_set = obj_scene\n", "bpy.context.scene.background_set = obj_scene\n"),
target, target); target, target);
} else { } else {
format( format(fmt(
"if '%s' not in bpy.data.scenes:\n" "if '{}' not in bpy.data.scenes:\n"
" with bpy.data.libraries.load('''%s''', link=True, relative=True) as (data_from, data_to):\n" " with bpy.data.libraries.load('''{}''', link=True, relative=True) as (data_from, data_to):\n"
" data_to.scenes = data_from.scenes\n" " data_to.scenes = data_from.scenes\n"
" obj_scene = None\n" " obj_scene = None\n"
" for scene in data_to.scenes:\n" " for scene in data_to.scenes:\n"
" if scene.name == '%s':\n" " if scene.name == '{}':\n"
" obj_scene = scene\n" " obj_scene = scene\n"
" break\n" " break\n"
" if not obj_scene:\n" " if not obj_scene:\n"
" raise RuntimeError('''unable to find %s in %s. try deleting it and restart the extract.''')\n" " raise RuntimeError('''unable to find {} in {}. try deleting it and restart the extract.''')\n"
"\n" "\n"
"bpy.context.scene.background_set = bpy.data.scenes['%s']\n", "bpy.context.scene.background_set = bpy.data.scenes['{}']\n"),
sceneName, target, sceneName, sceneName, target, sceneName); sceneName, target, sceneName, sceneName, target, sceneName);
} }
} }
@ -707,16 +681,16 @@ void PyOutStream::linkBackground(const char* target, const char* sceneName) {
void PyOutStream::AABBToBMesh(const atVec3f& min, const atVec3f& max) { void PyOutStream::AABBToBMesh(const atVec3f& min, const atVec3f& max) {
athena::simd_floats minf(min.simd); athena::simd_floats minf(min.simd);
athena::simd_floats maxf(max.simd); athena::simd_floats maxf(max.simd);
format( format(fmt(
"bm = bmesh.new()\n" "bm = bmesh.new()\n"
"bm.verts.new((%f,%f,%f))\n" "bm.verts.new(({},{},{}))\n"
"bm.verts.new((%f,%f,%f))\n" "bm.verts.new(({},{},{}))\n"
"bm.verts.new((%f,%f,%f))\n" "bm.verts.new(({},{},{}))\n"
"bm.verts.new((%f,%f,%f))\n" "bm.verts.new(({},{},{}))\n"
"bm.verts.new((%f,%f,%f))\n" "bm.verts.new(({},{},{}))\n"
"bm.verts.new((%f,%f,%f))\n" "bm.verts.new(({},{},{}))\n"
"bm.verts.new((%f,%f,%f))\n" "bm.verts.new(({},{},{}))\n"
"bm.verts.new((%f,%f,%f))\n" "bm.verts.new(({},{},{}))\n"
"bm.verts.ensure_lookup_table()\n" "bm.verts.ensure_lookup_table()\n"
"bm.edges.new((bm.verts[0], bm.verts[1]))\n" "bm.edges.new((bm.verts[0], bm.verts[1]))\n"
"bm.edges.new((bm.verts[0], bm.verts[2]))\n" "bm.edges.new((bm.verts[0], bm.verts[2]))\n"
@ -729,7 +703,7 @@ void PyOutStream::AABBToBMesh(const atVec3f& min, const atVec3f& max) {
"bm.edges.new((bm.verts[5], bm.verts[7]))\n" "bm.edges.new((bm.verts[5], bm.verts[7]))\n"
"bm.edges.new((bm.verts[6], bm.verts[2]))\n" "bm.edges.new((bm.verts[6], bm.verts[2]))\n"
"bm.edges.new((bm.verts[6], bm.verts[4]))\n" "bm.edges.new((bm.verts[6], bm.verts[4]))\n"
"bm.edges.new((bm.verts[6], bm.verts[7]))\n", "bm.edges.new((bm.verts[6], bm.verts[7]))\n"),
minf[0], minf[1], minf[2], maxf[0], minf[1], minf[2], minf[0], maxf[1], minf[2], maxf[0], maxf[1], minf[2], minf[0], minf[1], minf[2], maxf[0], minf[1], minf[2], minf[0], maxf[1], minf[2], maxf[0], maxf[1], minf[2],
minf[0], minf[1], maxf[2], maxf[0], minf[1], maxf[2], minf[0], maxf[1], maxf[2], maxf[0], maxf[1], maxf[2]); minf[0], minf[1], maxf[2], maxf[0], minf[1], maxf[2], minf[0], maxf[1], maxf[2], maxf[0], maxf[1], maxf[2]);
} }
@ -763,7 +737,7 @@ ANIMOutStream::ANIMOutStream(Connection* parent) : m_parent(parent) {
char readBuf[16]; char readBuf[16];
m_parent->_readStr(readBuf, 16); m_parent->_readStr(readBuf, 16);
if (strcmp(readBuf, "ANIMREADY")) if (strcmp(readBuf, "ANIMREADY"))
BlenderLog.report(logvisor::Fatal, "unable to open ANIMOutStream"); BlenderLog.report(logvisor::Fatal, fmt("unable to open ANIMOutStream"));
} }
ANIMOutStream::~ANIMOutStream() { ANIMOutStream::~ANIMOutStream() {
@ -772,12 +746,12 @@ ANIMOutStream::~ANIMOutStream() {
char readBuf[16]; char readBuf[16];
m_parent->_readStr(readBuf, 16); m_parent->_readStr(readBuf, 16);
if (strcmp(readBuf, "ANIMDONE")) if (strcmp(readBuf, "ANIMDONE"))
BlenderLog.report(logvisor::Fatal, "unable to close ANIMOutStream"); BlenderLog.report(logvisor::Fatal, fmt("unable to close ANIMOutStream"));
} }
void ANIMOutStream::changeCurve(CurveType type, unsigned crvIdx, unsigned keyCount) { void ANIMOutStream::changeCurve(CurveType type, unsigned crvIdx, unsigned keyCount) {
if (m_curCount != m_totalCount) if (m_curCount != m_totalCount)
BlenderLog.report(logvisor::Fatal, "incomplete ANIMOutStream for change"); BlenderLog.report(logvisor::Fatal, fmt("incomplete ANIMOutStream for change"));
m_curCount = 0; m_curCount = 0;
m_totalCount = keyCount; m_totalCount = keyCount;
char tp = char(type); char tp = char(type);
@ -792,7 +766,7 @@ void ANIMOutStream::changeCurve(CurveType type, unsigned crvIdx, unsigned keyCou
void ANIMOutStream::write(unsigned frame, float val) { void ANIMOutStream::write(unsigned frame, float val) {
if (!m_inCurve) if (!m_inCurve)
BlenderLog.report(logvisor::Fatal, "changeCurve not called before write"); BlenderLog.report(logvisor::Fatal, fmt("changeCurve not called before write"));
if (m_curCount < m_totalCount) { if (m_curCount < m_totalCount) {
struct { struct {
uint32_t frm; uint32_t frm;
@ -801,7 +775,7 @@ void ANIMOutStream::write(unsigned frame, float val) {
m_parent->_writeBuf(reinterpret_cast<const char*>(&key), 8); m_parent->_writeBuf(reinterpret_cast<const char*>(&key), 8);
++m_curCount; ++m_curCount;
} else } else
BlenderLog.report(logvisor::Fatal, "ANIMOutStream keyCount overflow"); BlenderLog.report(logvisor::Fatal, fmt("ANIMOutStream keyCount overflow"));
} }
Mesh::SkinBind::SkinBind(Connection& conn) { Mesh::SkinBind::SkinBind(Connection& conn) {
@ -1495,7 +1469,7 @@ DataStream::DataStream(Connection* parent) : m_parent(parent) {
char readBuf[16]; char readBuf[16];
m_parent->_readStr(readBuf, 16); m_parent->_readStr(readBuf, 16);
if (strcmp(readBuf, "READY")) if (strcmp(readBuf, "READY"))
BlenderLog.report(logvisor::Fatal, "unable to open DataStream with blender"); BlenderLog.report(logvisor::Fatal, fmt("unable to open DataStream with blender"));
} }
void DataStream::close() { void DataStream::close() {
@ -1504,7 +1478,7 @@ void DataStream::close() {
char readBuf[16]; char readBuf[16];
m_parent->_readStr(readBuf, 16); m_parent->_readStr(readBuf, 16);
if (strcmp(readBuf, "DONE")) if (strcmp(readBuf, "DONE"))
BlenderLog.report(logvisor::Fatal, "unable to close DataStream with blender"); BlenderLog.report(logvisor::Fatal, fmt("unable to close DataStream with blender"));
m_parent->m_dataStreamActive = false; m_parent->m_dataStreamActive = false;
m_parent->m_lock = false; m_parent->m_lock = false;
} }
@ -1540,14 +1514,14 @@ std::vector<std::string> DataStream::getLightList() {
std::pair<atVec3f, atVec3f> DataStream::getMeshAABB() { std::pair<atVec3f, atVec3f> DataStream::getMeshAABB() {
if (m_parent->m_loadedType != BlendType::Mesh && m_parent->m_loadedType != BlendType::Actor) if (m_parent->m_loadedType != BlendType::Mesh && m_parent->m_loadedType != BlendType::Actor)
BlenderLog.report(logvisor::Fatal, _SYS_STR("%s is not a MESH or ACTOR blend"), BlenderLog.report(logvisor::Fatal, fmt(_SYS_STR("{} is not a MESH or ACTOR blend")),
m_parent->m_loadedBlend.getAbsolutePath().data()); m_parent->m_loadedBlend.getAbsolutePath());
m_parent->_writeStr("MESHAABB"); m_parent->_writeStr("MESHAABB");
char readBuf[256]; char readBuf[256];
m_parent->_readStr(readBuf, 256); m_parent->_readStr(readBuf, 256);
if (strcmp(readBuf, "OK")) if (strcmp(readBuf, "OK"))
BlenderLog.report(logvisor::Fatal, "unable get AABB: %s", readBuf); BlenderLog.report(logvisor::Fatal, fmt("unable get AABB: {}"), readBuf);
Vector3f minPt(*m_parent); Vector3f minPt(*m_parent);
Vector3f maxPt(*m_parent); Vector3f maxPt(*m_parent);
@ -1561,66 +1535,60 @@ const char* DataStream::MeshOutputModeString(HMDLTopology topology) {
Mesh DataStream::compileMesh(HMDLTopology topology, int skinSlotCount) { Mesh DataStream::compileMesh(HMDLTopology topology, int skinSlotCount) {
if (m_parent->getBlendType() != BlendType::Mesh) if (m_parent->getBlendType() != BlendType::Mesh)
BlenderLog.report(logvisor::Fatal, _SYS_STR("%s is not a MESH blend"), BlenderLog.report(logvisor::Fatal, fmt(_SYS_STR("{} is not a MESH blend")),
m_parent->getBlendPath().getAbsolutePath().data()); m_parent->getBlendPath().getAbsolutePath());
m_parent->_writeStr("MESHCOMPILE"); m_parent->_writeStr("MESHCOMPILE");
char readBuf[256]; char readBuf[256];
m_parent->_readStr(readBuf, 256); m_parent->_readStr(readBuf, 256);
if (strcmp(readBuf, "OK")) if (strcmp(readBuf, "OK"))
BlenderLog.report(logvisor::Fatal, "unable to cook mesh: %s", readBuf); BlenderLog.report(logvisor::Fatal, fmt("unable to cook mesh: {}"), readBuf);
return Mesh(*m_parent, topology, skinSlotCount); return Mesh(*m_parent, topology, skinSlotCount);
} }
Mesh DataStream::compileMesh(std::string_view name, HMDLTopology topology, int skinSlotCount, bool useLuv) { Mesh DataStream::compileMesh(std::string_view name, HMDLTopology topology, int skinSlotCount, bool useLuv) {
if (m_parent->getBlendType() != BlendType::Area) if (m_parent->getBlendType() != BlendType::Area)
BlenderLog.report(logvisor::Fatal, _SYS_STR("%s is not an AREA blend"), BlenderLog.report(logvisor::Fatal, fmt(_SYS_STR("{} is not an AREA blend")),
m_parent->getBlendPath().getAbsolutePath().data()); m_parent->getBlendPath().getAbsolutePath());
char req[128]; m_parent->_writeStr(fmt::format(fmt("MESHCOMPILENAME {} {}"), name, int(useLuv)));
snprintf(req, 128, "MESHCOMPILENAME %s %d", name.data(), int(useLuv));
m_parent->_writeStr(req);
char readBuf[256]; char readBuf[256];
m_parent->_readStr(readBuf, 256); m_parent->_readStr(readBuf, 256);
if (strcmp(readBuf, "OK")) if (strcmp(readBuf, "OK"))
BlenderLog.report(logvisor::Fatal, "unable to cook mesh '%s': %s", name.data(), readBuf); BlenderLog.report(logvisor::Fatal, fmt("unable to cook mesh '{}': {}"), name, readBuf);
return Mesh(*m_parent, topology, skinSlotCount, useLuv); return Mesh(*m_parent, topology, skinSlotCount, useLuv);
} }
ColMesh DataStream::compileColMesh(std::string_view name) { ColMesh DataStream::compileColMesh(std::string_view name) {
if (m_parent->getBlendType() != BlendType::Area) if (m_parent->getBlendType() != BlendType::Area)
BlenderLog.report(logvisor::Fatal, _SYS_STR("%s is not an AREA blend"), BlenderLog.report(logvisor::Fatal, fmt(_SYS_STR("{} is not an AREA blend")),
m_parent->getBlendPath().getAbsolutePath().data()); m_parent->getBlendPath().getAbsolutePath());
char req[128]; m_parent->_writeStr(fmt::format(fmt("MESHCOMPILENAMECOLLISION {}"), name));
snprintf(req, 128, "MESHCOMPILENAMECOLLISION %s", name.data());
m_parent->_writeStr(req);
char readBuf[256]; char readBuf[256];
m_parent->_readStr(readBuf, 256); m_parent->_readStr(readBuf, 256);
if (strcmp(readBuf, "OK")) if (strcmp(readBuf, "OK"))
BlenderLog.report(logvisor::Fatal, "unable to cook collision mesh '%s': %s", name.data(), readBuf); BlenderLog.report(logvisor::Fatal, fmt("unable to cook collision mesh '{}': {}"), name, readBuf);
return ColMesh(*m_parent); return ColMesh(*m_parent);
} }
std::vector<ColMesh> DataStream::compileColMeshes() { std::vector<ColMesh> DataStream::compileColMeshes() {
if (m_parent->getBlendType() != BlendType::ColMesh) if (m_parent->getBlendType() != BlendType::ColMesh)
BlenderLog.report(logvisor::Fatal, _SYS_STR("%s is not a CMESH blend"), BlenderLog.report(logvisor::Fatal, fmt(_SYS_STR("{} is not a CMESH blend")),
m_parent->getBlendPath().getAbsolutePath().data()); m_parent->getBlendPath().getAbsolutePath());
char req[128]; m_parent->_writeStr("MESHCOMPILECOLLISIONALL");
snprintf(req, 128, "MESHCOMPILECOLLISIONALL");
m_parent->_writeStr(req);
char readBuf[256]; char readBuf[256];
m_parent->_readStr(readBuf, 256); m_parent->_readStr(readBuf, 256);
if (strcmp(readBuf, "OK")) if (strcmp(readBuf, "OK"))
BlenderLog.report(logvisor::Fatal, "unable to cook collision meshes: %s", readBuf); BlenderLog.report(logvisor::Fatal, fmt("unable to cook collision meshes: {}"), readBuf);
uint32_t meshCount; uint32_t meshCount;
m_parent->_readBuf(&meshCount, 4); m_parent->_readBuf(&meshCount, 4);
@ -1636,15 +1604,15 @@ std::vector<ColMesh> DataStream::compileColMeshes() {
std::vector<Light> DataStream::compileLights() { std::vector<Light> DataStream::compileLights() {
if (m_parent->getBlendType() != BlendType::Area) if (m_parent->getBlendType() != BlendType::Area)
BlenderLog.report(logvisor::Fatal, _SYS_STR("%s is not an AREA blend"), BlenderLog.report(logvisor::Fatal, fmt(_SYS_STR("{} is not an AREA blend")),
m_parent->getBlendPath().getAbsolutePath().data()); m_parent->getBlendPath().getAbsolutePath());
m_parent->_writeStr("LIGHTCOMPILEALL"); m_parent->_writeStr("LIGHTCOMPILEALL");
char readBuf[256]; char readBuf[256];
m_parent->_readStr(readBuf, 256); m_parent->_readStr(readBuf, 256);
if (strcmp(readBuf, "OK")) if (strcmp(readBuf, "OK"))
BlenderLog.report(logvisor::Fatal, "unable to gather all lights: %s", readBuf); BlenderLog.report(logvisor::Fatal, fmt("unable to gather all lights: {}"), readBuf);
uint32_t lightCount; uint32_t lightCount;
m_parent->_readBuf(&lightCount, 4); m_parent->_readBuf(&lightCount, 4);
@ -1660,15 +1628,15 @@ std::vector<Light> DataStream::compileLights() {
PathMesh DataStream::compilePathMesh() { PathMesh DataStream::compilePathMesh() {
if (m_parent->getBlendType() != BlendType::PathMesh) if (m_parent->getBlendType() != BlendType::PathMesh)
BlenderLog.report(logvisor::Fatal, _SYS_STR("%s is not a PATH blend"), BlenderLog.report(logvisor::Fatal, fmt(_SYS_STR("{} is not a PATH blend")),
m_parent->getBlendPath().getAbsolutePath().data()); m_parent->getBlendPath().getAbsolutePath());
m_parent->_writeStr("MESHCOMPILEPATH"); m_parent->_writeStr("MESHCOMPILEPATH");
char readBuf[256]; char readBuf[256];
m_parent->_readStr(readBuf, 256); m_parent->_readStr(readBuf, 256);
if (strcmp(readBuf, "OK")) if (strcmp(readBuf, "OK"))
BlenderLog.report(logvisor::Fatal, "unable to path collision mesh: %s", readBuf); BlenderLog.report(logvisor::Fatal, fmt("unable to path collision mesh: {}"), readBuf);
return PathMesh(*m_parent); return PathMesh(*m_parent);
} }
@ -1676,17 +1644,15 @@ PathMesh DataStream::compilePathMesh() {
std::vector<uint8_t> DataStream::compileGuiFrame(int version) { std::vector<uint8_t> DataStream::compileGuiFrame(int version) {
std::vector<uint8_t> ret; std::vector<uint8_t> ret;
if (m_parent->getBlendType() != BlendType::Frame) if (m_parent->getBlendType() != BlendType::Frame)
BlenderLog.report(logvisor::Fatal, _SYS_STR("%s is not a FRAME blend"), BlenderLog.report(logvisor::Fatal, fmt(_SYS_STR("{} is not a FRAME blend")),
m_parent->getBlendPath().getAbsolutePath().data()); m_parent->getBlendPath().getAbsolutePath());
char req[512]; m_parent->_writeStr(fmt::format(fmt("FRAMECOMPILE {}"), version));
snprintf(req, 512, "FRAMECOMPILE %d", version);
m_parent->_writeStr(req);
char readBuf[1024]; char readBuf[1024];
m_parent->_readStr(readBuf, 1024); m_parent->_readStr(readBuf, 1024);
if (strcmp(readBuf, "OK")) if (strcmp(readBuf, "OK"))
BlenderLog.report(logvisor::Fatal, "unable to compile frame: %s", readBuf); BlenderLog.report(logvisor::Fatal, fmt("unable to compile frame: {}"), readBuf);
while (true) { while (true) {
m_parent->_readStr(readBuf, 1024); m_parent->_readStr(readBuf, 1024);
@ -1703,8 +1669,7 @@ std::vector<uint8_t> DataStream::compileGuiFrame(int version) {
relative = proj.getProjectRootPath().getProjectRelativeFromAbsolute(absolute.sys_str()); relative = proj.getProjectRootPath().getProjectRelativeFromAbsolute(absolute.sys_str());
hecl::ProjectPath path(proj.getProjectWorkingPath(), relative); hecl::ProjectPath path(proj.getProjectWorkingPath(), relative);
snprintf(req, 512, "%016" PRIX64, path.hash().val64()); m_parent->_writeStr(fmt::format(fmt("{:016X}"), path.hash().val64()));
m_parent->_writeStr(req);
} }
uint32_t len; uint32_t len;
@ -1720,7 +1685,7 @@ std::vector<ProjectPath> DataStream::getTextures() {
char readBuf[256]; char readBuf[256];
m_parent->_readStr(readBuf, 256); m_parent->_readStr(readBuf, 256);
if (strcmp(readBuf, "OK")) if (strcmp(readBuf, "OK"))
BlenderLog.report(logvisor::Fatal, "unable to get textures: %s", readBuf); BlenderLog.report(logvisor::Fatal, fmt("unable to get textures: {}"), readBuf);
uint32_t texCount; uint32_t texCount;
m_parent->_readBuf(&texCount, 4); m_parent->_readBuf(&texCount, 4);
@ -1743,77 +1708,75 @@ std::vector<ProjectPath> DataStream::getTextures() {
Actor DataStream::compileActor() { Actor DataStream::compileActor() {
if (m_parent->getBlendType() != BlendType::Actor) if (m_parent->getBlendType() != BlendType::Actor)
BlenderLog.report(logvisor::Fatal, _SYS_STR("%s is not an ACTOR blend"), BlenderLog.report(logvisor::Fatal, fmt(_SYS_STR("{} is not an ACTOR blend")),
m_parent->getBlendPath().getAbsolutePath().data()); m_parent->getBlendPath().getAbsolutePath());
m_parent->_writeStr("ACTORCOMPILE"); m_parent->_writeStr("ACTORCOMPILE");
char readBuf[256]; char readBuf[256];
m_parent->_readStr(readBuf, 256); m_parent->_readStr(readBuf, 256);
if (strcmp(readBuf, "OK")) if (strcmp(readBuf, "OK"))
BlenderLog.report(logvisor::Fatal, "unable to compile actor: %s", readBuf); BlenderLog.report(logvisor::Fatal, fmt("unable to compile actor: {}"), readBuf);
return Actor(*m_parent); return Actor(*m_parent);
} }
Actor DataStream::compileActorCharacterOnly() { Actor DataStream::compileActorCharacterOnly() {
if (m_parent->getBlendType() != BlendType::Actor) if (m_parent->getBlendType() != BlendType::Actor)
BlenderLog.report(logvisor::Fatal, _SYS_STR("%s is not an ACTOR blend"), BlenderLog.report(logvisor::Fatal, fmt(_SYS_STR("{} is not an ACTOR blend")),
m_parent->getBlendPath().getAbsolutePath().data()); m_parent->getBlendPath().getAbsolutePath());
m_parent->_writeStr("ACTORCOMPILECHARACTERONLY"); m_parent->_writeStr("ACTORCOMPILECHARACTERONLY");
char readBuf[256]; char readBuf[256];
m_parent->_readStr(readBuf, 256); m_parent->_readStr(readBuf, 256);
if (strcmp(readBuf, "OK")) if (strcmp(readBuf, "OK"))
BlenderLog.report(logvisor::Fatal, "unable to compile actor: %s", readBuf); BlenderLog.report(logvisor::Fatal, fmt("unable to compile actor: {}"), readBuf);
return Actor(*m_parent); return Actor(*m_parent);
} }
Action DataStream::compileActionChannelsOnly(std::string_view name) { Action DataStream::compileActionChannelsOnly(std::string_view name) {
if (m_parent->getBlendType() != BlendType::Actor) if (m_parent->getBlendType() != BlendType::Actor)
BlenderLog.report(logvisor::Fatal, _SYS_STR("%s is not an ACTOR blend"), BlenderLog.report(logvisor::Fatal, fmt(_SYS_STR("{} is not an ACTOR blend")),
m_parent->getBlendPath().getAbsolutePath().data()); m_parent->getBlendPath().getAbsolutePath());
char req[128]; m_parent->_writeStr(fmt::format(fmt("ACTIONCOMPILECHANNELSONLY {}"), name));
snprintf(req, 128, "ACTIONCOMPILECHANNELSONLY %s", name.data());
m_parent->_writeStr(req);
char readBuf[256]; char readBuf[256];
m_parent->_readStr(readBuf, 256); m_parent->_readStr(readBuf, 256);
if (strcmp(readBuf, "OK")) if (strcmp(readBuf, "OK"))
BlenderLog.report(logvisor::Fatal, "unable to compile action: %s", readBuf); BlenderLog.report(logvisor::Fatal, fmt("unable to compile action: {}"), readBuf);
return Action(*m_parent); return Action(*m_parent);
} }
World DataStream::compileWorld() { World DataStream::compileWorld() {
if (m_parent->getBlendType() != BlendType::World) if (m_parent->getBlendType() != BlendType::World)
BlenderLog.report(logvisor::Fatal, _SYS_STR("%s is not an WORLD blend"), BlenderLog.report(logvisor::Fatal, fmt(_SYS_STR("{} is not an WORLD blend")),
m_parent->getBlendPath().getAbsolutePath().data()); m_parent->getBlendPath().getAbsolutePath());
m_parent->_writeStr("WORLDCOMPILE"); m_parent->_writeStr("WORLDCOMPILE");
char readBuf[256]; char readBuf[256];
m_parent->_readStr(readBuf, 256); m_parent->_readStr(readBuf, 256);
if (strcmp(readBuf, "OK")) if (strcmp(readBuf, "OK"))
BlenderLog.report(logvisor::Fatal, "unable to compile world: %s", readBuf); BlenderLog.report(logvisor::Fatal, fmt("unable to compile world: {}"), readBuf);
return World(*m_parent); return World(*m_parent);
} }
std::vector<std::string> DataStream::getArmatureNames() { std::vector<std::string> DataStream::getArmatureNames() {
if (m_parent->getBlendType() != BlendType::Actor) if (m_parent->getBlendType() != BlendType::Actor)
BlenderLog.report(logvisor::Fatal, _SYS_STR("%s is not an ACTOR blend"), BlenderLog.report(logvisor::Fatal, fmt(_SYS_STR("{} is not an ACTOR blend")),
m_parent->getBlendPath().getAbsolutePath().data()); m_parent->getBlendPath().getAbsolutePath());
m_parent->_writeStr("GETARMATURENAMES"); m_parent->_writeStr("GETARMATURENAMES");
char readBuf[256]; char readBuf[256];
m_parent->_readStr(readBuf, 256); m_parent->_readStr(readBuf, 256);
if (strcmp(readBuf, "OK")) if (strcmp(readBuf, "OK"))
BlenderLog.report(logvisor::Fatal, "unable to get armatures of actor: %s", readBuf); BlenderLog.report(logvisor::Fatal, fmt("unable to get armatures of actor: {}"), readBuf);
std::vector<std::string> ret; std::vector<std::string> ret;
@ -1834,15 +1797,15 @@ std::vector<std::string> DataStream::getArmatureNames() {
std::vector<std::string> DataStream::getSubtypeNames() { std::vector<std::string> DataStream::getSubtypeNames() {
if (m_parent->getBlendType() != BlendType::Actor) if (m_parent->getBlendType() != BlendType::Actor)
BlenderLog.report(logvisor::Fatal, _SYS_STR("%s is not an ACTOR blend"), BlenderLog.report(logvisor::Fatal, fmt(_SYS_STR("{} is not an ACTOR blend")),
m_parent->getBlendPath().getAbsolutePath().data()); m_parent->getBlendPath().getAbsolutePath());
m_parent->_writeStr("GETSUBTYPENAMES"); m_parent->_writeStr("GETSUBTYPENAMES");
char readBuf[256]; char readBuf[256];
m_parent->_readStr(readBuf, 256); m_parent->_readStr(readBuf, 256);
if (strcmp(readBuf, "OK")) if (strcmp(readBuf, "OK"))
BlenderLog.report(logvisor::Fatal, "unable to get subtypes of actor: %s", readBuf); BlenderLog.report(logvisor::Fatal, fmt("unable to get subtypes of actor: {}"), readBuf);
std::vector<std::string> ret; std::vector<std::string> ret;
@ -1863,15 +1826,15 @@ std::vector<std::string> DataStream::getSubtypeNames() {
std::vector<std::string> DataStream::getActionNames() { std::vector<std::string> DataStream::getActionNames() {
if (m_parent->getBlendType() != BlendType::Actor) if (m_parent->getBlendType() != BlendType::Actor)
BlenderLog.report(logvisor::Fatal, _SYS_STR("%s is not an ACTOR blend"), BlenderLog.report(logvisor::Fatal, fmt(_SYS_STR("{} is not an ACTOR blend")),
m_parent->getBlendPath().getAbsolutePath().data()); m_parent->getBlendPath().getAbsolutePath());
m_parent->_writeStr("GETACTIONNAMES"); m_parent->_writeStr("GETACTIONNAMES");
char readBuf[256]; char readBuf[256];
m_parent->_readStr(readBuf, 256); m_parent->_readStr(readBuf, 256);
if (strcmp(readBuf, "OK")) if (strcmp(readBuf, "OK"))
BlenderLog.report(logvisor::Fatal, "unable to get actions of actor: %s", readBuf); BlenderLog.report(logvisor::Fatal, fmt("unable to get actions of actor: {}"), readBuf);
std::vector<std::string> ret; std::vector<std::string> ret;
@ -1892,17 +1855,15 @@ std::vector<std::string> DataStream::getActionNames() {
std::vector<std::string> DataStream::getSubtypeOverlayNames(std::string_view name) { std::vector<std::string> DataStream::getSubtypeOverlayNames(std::string_view name) {
if (m_parent->getBlendType() != BlendType::Actor) if (m_parent->getBlendType() != BlendType::Actor)
BlenderLog.report(logvisor::Fatal, _SYS_STR("%s is not an ACTOR blend"), BlenderLog.report(logvisor::Fatal, fmt(_SYS_STR("{} is not an ACTOR blend")),
m_parent->getBlendPath().getAbsolutePath().data()); m_parent->getBlendPath().getAbsolutePath());
char req[128]; m_parent->_writeStr(fmt::format(fmt("GETSUBTYPEOVERLAYNAMES {}"), name));
snprintf(req, 128, "GETSUBTYPEOVERLAYNAMES %s", name.data());
m_parent->_writeStr(req);
char readBuf[256]; char readBuf[256];
m_parent->_readStr(readBuf, 256); m_parent->_readStr(readBuf, 256);
if (strcmp(readBuf, "OK")) if (strcmp(readBuf, "OK"))
BlenderLog.report(logvisor::Fatal, "unable to get subtype overlays of actor: %s", readBuf); BlenderLog.report(logvisor::Fatal, fmt("unable to get subtype overlays of actor: {}"), readBuf);
std::vector<std::string> ret; std::vector<std::string> ret;
@ -1923,15 +1884,15 @@ std::vector<std::string> DataStream::getSubtypeOverlayNames(std::string_view nam
std::vector<std::string> DataStream::getAttachmentNames() { std::vector<std::string> DataStream::getAttachmentNames() {
if (m_parent->getBlendType() != BlendType::Actor) if (m_parent->getBlendType() != BlendType::Actor)
BlenderLog.report(logvisor::Fatal, _SYS_STR("%s is not an ACTOR blend"), BlenderLog.report(logvisor::Fatal, fmt(_SYS_STR("{} is not an ACTOR blend")),
m_parent->getBlendPath().getAbsolutePath().data()); m_parent->getBlendPath().getAbsolutePath());
m_parent->_writeStr("GETATTACHMENTNAMES"); m_parent->_writeStr("GETATTACHMENTNAMES");
char readBuf[256]; char readBuf[256];
m_parent->_readStr(readBuf, 256); m_parent->_readStr(readBuf, 256);
if (strcmp(readBuf, "OK")) if (strcmp(readBuf, "OK"))
BlenderLog.report(logvisor::Fatal, "unable to get attachments of actor: %s", readBuf); BlenderLog.report(logvisor::Fatal, fmt("unable to get attachments of actor: {}"), readBuf);
std::vector<std::string> ret; std::vector<std::string> ret;
@ -1955,17 +1916,15 @@ std::unordered_map<std::string, Matrix3f> DataStream::getBoneMatrices(std::strin
return {}; return {};
if (m_parent->getBlendType() != BlendType::Actor) if (m_parent->getBlendType() != BlendType::Actor)
BlenderLog.report(logvisor::Fatal, _SYS_STR("%s is not an ACTOR blend"), BlenderLog.report(logvisor::Fatal, fmt(_SYS_STR("{} is not an ACTOR blend")),
m_parent->getBlendPath().getAbsolutePath().data()); m_parent->getBlendPath().getAbsolutePath());
char req[128]; m_parent->_writeStr(fmt::format(fmt("GETBONEMATRICES {}"), name));
snprintf(req, 128, "GETBONEMATRICES %s", name.data());
m_parent->_writeStr(req);
char readBuf[256]; char readBuf[256];
m_parent->_readStr(readBuf, 256); m_parent->_readStr(readBuf, 256);
if (strcmp(readBuf, "OK")) if (strcmp(readBuf, "OK"))
BlenderLog.report(logvisor::Fatal, "unable to get matrices of armature: %s", readBuf); BlenderLog.report(logvisor::Fatal, fmt("unable to get matrices of armature: {}"), readBuf);
std::unordered_map<std::string, Matrix3f> ret; std::unordered_map<std::string, Matrix3f> ret;
@ -2000,19 +1959,17 @@ bool DataStream::renderPvs(std::string_view path, const atVec3f& location) {
return false; return false;
if (m_parent->getBlendType() != BlendType::Area) if (m_parent->getBlendType() != BlendType::Area)
BlenderLog.report(logvisor::Fatal, _SYS_STR("%s is not an AREA blend"), BlenderLog.report(logvisor::Fatal, fmt(_SYS_STR("{} is not an AREA blend")),
m_parent->getBlendPath().getAbsolutePath().data()); m_parent->getBlendPath().getAbsolutePath());
char req[256];
athena::simd_floats f(location.simd); athena::simd_floats f(location.simd);
snprintf(req, 256, "RENDERPVS %s %f %f %f", path.data(), f[0], f[1], f[2]); m_parent->_writeStr(fmt::format(fmt("RENDERPVS {} {} {} {}"), path, f[0], f[1], f[2]));
m_parent->_writeStr(req);
char readBuf[256]; char readBuf[256];
m_parent->_readStr(readBuf, 256); m_parent->_readStr(readBuf, 256);
if (strcmp(readBuf, "OK")) if (strcmp(readBuf, "OK"))
BlenderLog.report(logvisor::Fatal, "unable to render PVS for: %s; %s", BlenderLog.report(logvisor::Fatal, fmt("unable to render PVS for: {}; {}"),
m_parent->getBlendPath().getAbsolutePathUTF8().data(), readBuf); m_parent->getBlendPath().getAbsolutePathUTF8(), readBuf);
return true; return true;
} }
@ -2022,50 +1979,48 @@ bool DataStream::renderPvsLight(std::string_view path, std::string_view lightNam
return false; return false;
if (m_parent->getBlendType() != BlendType::Area) if (m_parent->getBlendType() != BlendType::Area)
BlenderLog.report(logvisor::Fatal, _SYS_STR("%s is not an AREA blend"), BlenderLog.report(logvisor::Fatal, fmt(_SYS_STR("{} is not an AREA blend")),
m_parent->getBlendPath().getAbsolutePath().data()); m_parent->getBlendPath().getAbsolutePath());
char req[256]; m_parent->_writeStr(fmt::format(fmt("RENDERPVSLIGHT {} {}"), path, lightName));
snprintf(req, 256, "RENDERPVSLIGHT %s %s", path.data(), lightName.data());
m_parent->_writeStr(req);
char readBuf[256]; char readBuf[256];
m_parent->_readStr(readBuf, 256); m_parent->_readStr(readBuf, 256);
if (strcmp(readBuf, "OK")) if (strcmp(readBuf, "OK"))
BlenderLog.report(logvisor::Fatal, "unable to render PVS light %s for: %s; %s", lightName.data(), BlenderLog.report(logvisor::Fatal, fmt("unable to render PVS light {} for: {}; {}"), lightName,
m_parent->getBlendPath().getAbsolutePathUTF8().data(), readBuf); m_parent->getBlendPath().getAbsolutePathUTF8(), readBuf);
return true; return true;
} }
MapArea DataStream::compileMapArea() { MapArea DataStream::compileMapArea() {
if (m_parent->getBlendType() != BlendType::MapArea) if (m_parent->getBlendType() != BlendType::MapArea)
BlenderLog.report(logvisor::Fatal, _SYS_STR("%s is not a MAPAREA blend"), BlenderLog.report(logvisor::Fatal, fmt(_SYS_STR("{} is not a MAPAREA blend")),
m_parent->getBlendPath().getAbsolutePath().data()); m_parent->getBlendPath().getAbsolutePath());
m_parent->_writeStr("MAPAREACOMPILE"); m_parent->_writeStr("MAPAREACOMPILE");
char readBuf[256]; char readBuf[256];
m_parent->_readStr(readBuf, 256); m_parent->_readStr(readBuf, 256);
if (strcmp(readBuf, "OK")) if (strcmp(readBuf, "OK"))
BlenderLog.report(logvisor::Fatal, "unable to compile map area: %s; %s", BlenderLog.report(logvisor::Fatal, fmt("unable to compile map area: {}; {}"),
m_parent->getBlendPath().getAbsolutePathUTF8().data(), readBuf); m_parent->getBlendPath().getAbsolutePathUTF8(), readBuf);
return {*m_parent}; return {*m_parent};
} }
MapUniverse DataStream::compileMapUniverse() { MapUniverse DataStream::compileMapUniverse() {
if (m_parent->getBlendType() != BlendType::MapUniverse) if (m_parent->getBlendType() != BlendType::MapUniverse)
BlenderLog.report(logvisor::Fatal, _SYS_STR("%s is not a MAPUNIVERSE blend"), BlenderLog.report(logvisor::Fatal, fmt(_SYS_STR("{} is not a MAPUNIVERSE blend")),
m_parent->getBlendPath().getAbsolutePath().data()); m_parent->getBlendPath().getAbsolutePath());
m_parent->_writeStr("MAPUNIVERSECOMPILE"); m_parent->_writeStr("MAPUNIVERSECOMPILE");
char readBuf[256]; char readBuf[256];
m_parent->_readStr(readBuf, 256); m_parent->_readStr(readBuf, 256);
if (strcmp(readBuf, "OK")) if (strcmp(readBuf, "OK"))
BlenderLog.report(logvisor::Fatal, "unable to compile map universe: %s; %s", BlenderLog.report(logvisor::Fatal, fmt("unable to compile map universe: {}; {}"),
m_parent->getBlendPath().getAbsolutePathUTF8().data(), readBuf); m_parent->getBlendPath().getAbsolutePathUTF8(), readBuf);
return {*m_parent}; return {*m_parent};
} }
@ -2103,7 +2058,7 @@ void Token::shutdown() {
m_conn->quitBlender(); m_conn->quitBlender();
m_conn.reset(); m_conn.reset();
if (hecl::VerbosityLevel >= 1) if (hecl::VerbosityLevel >= 1)
BlenderLog.report(logvisor::Info, "Blender Shutdown Successful"); BlenderLog.report(logvisor::Info, fmt("Blender Shutdown Successful"));
} }
} }

View File

@ -44,7 +44,7 @@ MeshOptimizer::Vertex::Vertex(Connection& conn) {
co.read(conn); co.read(conn);
Index skin_count(conn); Index skin_count(conn);
if (skin_count.val > MaxSkinEntries) if (skin_count.val > MaxSkinEntries)
Log.report(logvisor::Fatal, "Skin entry overflow %u/%u", skin_count.val, MaxSkinEntries); Log.report(logvisor::Fatal, fmt("Skin entry overflow {}/{}"), skin_count.val, MaxSkinEntries);
for (uint32_t i = 0; i < skin_count.val; ++i) for (uint32_t i = 0; i < skin_count.val; ++i)
skin_ents[i] = Mesh::SkinBind(conn); skin_ents[i] = Mesh::SkinBind(conn);
} }
@ -69,7 +69,7 @@ MeshOptimizer::Edge::Edge(Connection& conn) {
verts[i] = Index(conn).val; verts[i] = Index(conn).val;
Index face_count(conn); Index face_count(conn);
if (face_count > MaxLinkFaces) if (face_count > MaxLinkFaces)
Log.report(logvisor::Fatal, "Face overflow %u/%u", face_count.val, MaxLinkFaces); Log.report(logvisor::Fatal, fmt("Face overflow {}/{}"), face_count.val, MaxLinkFaces);
for (uint32_t i = 0; i < face_count.val; ++i) for (uint32_t i = 0; i < face_count.val; ++i)
link_faces[i] = Index(conn).val; link_faces[i] = Index(conn).val;
is_contiguous = Boolean(conn).val; is_contiguous = Boolean(conn).val;
@ -377,10 +377,10 @@ MeshOptimizer::MeshOptimizer(Connection& conn, const std::vector<Material>& mate
: materials(materials), use_luvs(use_luvs) { : materials(materials), use_luvs(use_luvs) {
color_count = Index(conn).val; color_count = Index(conn).val;
if (color_count > MaxColorLayers) if (color_count > MaxColorLayers)
Log.report(logvisor::Fatal, "Color layer overflow %u/%u", color_count, MaxColorLayers); Log.report(logvisor::Fatal, fmt("Color layer overflow {}/{}"), color_count, MaxColorLayers);
uv_count = Index(conn).val; uv_count = Index(conn).val;
if (uv_count > MaxUVLayers) if (uv_count > MaxUVLayers)
Log.report(logvisor::Fatal, "UV layer overflow %u/%u", uv_count, MaxUVLayers); Log.report(logvisor::Fatal, fmt("UV layer overflow {}/{}"), uv_count, MaxUVLayers);
/* Simultaneously load topology objects and build unique mapping indices */ /* Simultaneously load topology objects and build unique mapping indices */

View File

@ -226,7 +226,7 @@ bool CVar::fromVec4f(const atVec4f& val) {
return false; return false;
athena::simd_floats f(val.simd); athena::simd_floats f(val.simd);
m_value.assign(hecl::Format("%f %f %f %f", f[0], f[1], f[2], f[3])); m_value.assign(fmt::format(fmt("{} {} {} {}"), f[0], f[1], f[2], f[3]));
m_flags |= EFlags::Modified; m_flags |= EFlags::Modified;
return true; return true;
} }
@ -243,7 +243,7 @@ bool CVar::fromFloat(float val) {
if (isReadOnly() && (com_developer && !com_developer->toBoolean())) if (isReadOnly() && (com_developer && !com_developer->toBoolean()))
return false; return false;
m_value.assign(hecl::Format("%f", val)); m_value.assign(fmt::format(fmt("{}"), val));
setModified(); setModified();
return true; return true;
} }
@ -281,7 +281,7 @@ bool CVar::fromInteger(int val) {
if (isReadOnly() && (com_developer && !com_developer->toBoolean())) if (isReadOnly() && (com_developer && !com_developer->toBoolean()))
return false; return false;
m_value = hecl::Format("%i", val); m_value = fmt::format(fmt("{}"), val);
setModified(); setModified();
return true; return true;
} }

View File

@ -196,20 +196,20 @@ CVarManager* CVarManager::instance() { return m_instance; }
void CVarManager::list(Console* con, const std::vector<std::string>& /*args*/) { void CVarManager::list(Console* con, const std::vector<std::string>& /*args*/) {
for (const auto& cvar : m_cvars) { for (const auto& cvar : m_cvars) {
if (!cvar.second->isHidden()) if (!cvar.second->isHidden())
con->report(Console::Level::Info, "%s: %s", cvar.second->name().data(), cvar.second->help().c_str()); con->report(Console::Level::Info, fmt("{}: {}"), cvar.second->name(), cvar.second->help());
} }
} }
void CVarManager::setCVar(Console* con, const std::vector<std::string>& args) { void CVarManager::setCVar(Console* con, const std::vector<std::string>& args) {
if (args.size() < 2) { if (args.size() < 2) {
con->report(Console::Level::Info, "Usage setCvar <cvar> <value>"); con->report(Console::Level::Info, fmt("Usage setCvar <cvar> <value>"));
return; return;
} }
std::string cvName = args[0]; std::string cvName = args[0];
athena::utility::tolower(cvName); athena::utility::tolower(cvName);
if (m_cvars.find(cvName) == m_cvars.end()) { if (m_cvars.find(cvName) == m_cvars.end()) {
con->report(Console::Level::Error, "CVar '%s' does not exist", args[0].c_str()); con->report(Console::Level::Error, fmt("CVar '%s' does not exist"), args[0].c_str());
return; return;
} }
@ -225,26 +225,26 @@ void CVarManager::setCVar(Console* con, const std::vector<std::string>& args) {
return; return;
if (!cv->fromLiteralToType(value)) if (!cv->fromLiteralToType(value))
con->report(Console::Level::Warning, "Unable to set cvar '%s' to value '%s'", cv->name().data(), value.c_str()); con->report(Console::Level::Warning, fmt("Unable to set cvar '%s' to value '%s'"), cv->name().data(), value.c_str());
else else
con->report(Console::Level::Info, "Set '%s' from '%s' to '%s'", cv->name().data(), oldVal.c_str(), value.c_str()); con->report(Console::Level::Info, fmt("Set '%s' from '%s' to '%s'"), cv->name().data(), oldVal.c_str(), value.c_str());
} }
void CVarManager::getCVar(Console* con, const std::vector<std::string>& args) { void CVarManager::getCVar(Console* con, const std::vector<std::string>& args) {
if (args.empty()) { if (args.empty()) {
con->report(Console::Level::Info, "Usage getCVar <cvar>"); con->report(Console::Level::Info, fmt("Usage getCVar <cvar>"));
return; return;
} }
std::string cvName = args[0]; std::string cvName = args[0];
athena::utility::tolower(cvName); athena::utility::tolower(cvName);
if (m_cvars.find(cvName) == m_cvars.end()) { if (m_cvars.find(cvName) == m_cvars.end()) {
con->report(Console::Level::Error, "CVar '%s' does not exist", args[0].c_str()); con->report(Console::Level::Error, fmt("CVar '%s' does not exist"), args[0].c_str());
return; return;
} }
const auto& cv = m_cvars[cvName]; const auto& cv = m_cvars[cvName];
con->report(Console::Level::Info, "'%s' = '%s'", cv->name().data(), cv->value().c_str()); con->report(Console::Level::Info, fmt("'%s' = '%s'"), cv->name().data(), cv->value().c_str());
} }
void CVarManager::setDeveloperMode(bool v, bool setDeserialized) { void CVarManager::setDeveloperMode(bool v, bool setDeserialized) {

View File

@ -59,7 +59,7 @@ static int GetCPUCount() {
void ClientProcess::BufferTransaction::run(blender::Token& btok) { void ClientProcess::BufferTransaction::run(blender::Token& btok) {
athena::io::FileReader r(m_path.getAbsolutePath(), 32 * 1024, false); athena::io::FileReader r(m_path.getAbsolutePath(), 32 * 1024, false);
if (r.hasError()) { if (r.hasError()) {
CP_Log.report(logvisor::Fatal, _SYS_STR("unable to background-buffer '%s'"), m_path.getAbsolutePath().data()); CP_Log.report(logvisor::Fatal, fmt(_SYS_STR("unable to background-buffer '{}'")), m_path.getAbsolutePath());
return; return;
} }
if (m_offset) if (m_offset)
@ -89,9 +89,7 @@ ClientProcess::Worker::Worker(ClientProcess& proc, int idx) : m_proc(proc), m_id
void ClientProcess::Worker::proc() { void ClientProcess::Worker::proc() {
ClientProcess::ThreadWorker.reset(this); ClientProcess::ThreadWorker.reset(this);
char thrName[64]; logvisor::RegisterThreadName(fmt::format(fmt("HECL Worker {}"), m_idx).c_str());
snprintf(thrName, 64, "HECL Worker %d", m_idx);
logvisor::RegisterThreadName(thrName);
std::unique_lock<std::mutex> lk(m_proc.m_mutex); std::unique_lock<std::mutex> lk(m_proc.m_mutex);
while (m_proc.m_running) { while (m_proc.m_running) {
@ -176,25 +174,24 @@ bool ClientProcess::syncCook(const hecl::ProjectPath& path, Database::IDataSpec*
if (m_progPrinter) { if (m_progPrinter) {
hecl::SystemString str; hecl::SystemString str;
if (path.getAuxInfo().empty()) if (path.getAuxInfo().empty())
str = hecl::SysFormat(_SYS_STR("Cooking %s"), path.getRelativePath().data()); str = fmt::format(fmt(_SYS_STR("Cooking {}")), path.getRelativePath());
else else
str = hecl::SysFormat(_SYS_STR("Cooking %s|%s"), path.getRelativePath().data(), path.getAuxInfo().data()); str = fmt::format(fmt(_SYS_STR("Cooking {}|{}")), path.getRelativePath(), path.getAuxInfo());
m_progPrinter->print(str.c_str(), nullptr, -1.f, hecl::ClientProcess::GetThreadWorkerIdx()); m_progPrinter->print(str.c_str(), nullptr, -1.f, hecl::ClientProcess::GetThreadWorkerIdx());
m_progPrinter->flush(); m_progPrinter->flush();
} else { } else {
if (path.getAuxInfo().empty()) if (path.getAuxInfo().empty())
LogModule.report(logvisor::Info, _SYS_STR("Cooking %s"), path.getRelativePath().data()); LogModule.report(logvisor::Info, fmt(_SYS_STR("Cooking {}")), path.getRelativePath());
else else
LogModule.report(logvisor::Info, _SYS_STR("Cooking %s|%s"), path.getRelativePath().data(), LogModule.report(logvisor::Info, fmt(_SYS_STR("Cooking {}|{}")), path.getRelativePath(), path.getAuxInfo());
path.getAuxInfo().data());
} }
spec->doCook(path, cooked, false, btok, [](const SystemChar*) {}); spec->doCook(path, cooked, false, btok, [](const SystemChar*) {});
if (m_progPrinter) { if (m_progPrinter) {
hecl::SystemString str; hecl::SystemString str;
if (path.getAuxInfo().empty()) if (path.getAuxInfo().empty())
str = hecl::SysFormat(_SYS_STR("Cooked %s"), path.getRelativePath().data()); str = fmt::format(fmt(_SYS_STR("Cooked {}")), path.getRelativePath());
else else
str = hecl::SysFormat(_SYS_STR("Cooked %s|%s"), path.getRelativePath().data(), path.getAuxInfo().data()); str = fmt::format(fmt(_SYS_STR("Cooked {}|{}")), path.getRelativePath(), path.getAuxInfo());
m_progPrinter->print(str.c_str(), nullptr, -1.f, hecl::ClientProcess::GetThreadWorkerIdx()); m_progPrinter->print(str.c_str(), nullptr, -1.f, hecl::ClientProcess::GetThreadWorkerIdx());
m_progPrinter->flush(); m_progPrinter->flush();
} }

View File

@ -64,15 +64,15 @@ struct ShaderCompiler<PlatformType::Vulkan> {
const char* strings[] = {"#version 330\n", BOO_GLSL_BINDING_HEAD, text.data()}; const char* strings[] = {"#version 330\n", BOO_GLSL_BINDING_HEAD, text.data()};
shader.setStrings(strings, 3); shader.setStrings(strings, 3);
if (!shader.parse(&glslang::DefaultTBuiltInResource, 110, false, messages)) { if (!shader.parse(&glslang::DefaultTBuiltInResource, 110, false, messages)) {
printf("%s\n", text.data()); fmt::print(fmt("{}\n"), text);
Log.report(logvisor::Fatal, "unable to compile shader\n%s", shader.getInfoLog()); Log.report(logvisor::Fatal, fmt("unable to compile shader\n{}"), shader.getInfoLog());
return {}; return {};
} }
glslang::TProgram prog; glslang::TProgram prog;
prog.addShader(&shader); prog.addShader(&shader);
if (!prog.link(messages)) { if (!prog.link(messages)) {
Log.report(logvisor::Fatal, "unable to link shader program\n%s", prog.getInfoLog()); Log.report(logvisor::Fatal, fmt("unable to link shader program\n{}"), prog.getInfoLog());
return {}; return {};
} }
@ -100,7 +100,7 @@ struct ShaderCompiler<PlatformType::D3D11> {
if (FAILED(D3DCompilePROC(text.data(), text.size(), "Boo HLSL Source", nullptr, nullptr, "main", if (FAILED(D3DCompilePROC(text.data(), text.size(), "Boo HLSL Source", nullptr, nullptr, "main",
D3DShaderTypes[int(S::Enum)], BOO_D3DCOMPILE_FLAG, 0, &blobOut, &errBlob))) { D3DShaderTypes[int(S::Enum)], BOO_D3DCOMPILE_FLAG, 0, &blobOut, &errBlob))) {
printf("%s\n", text.data()); printf("%s\n", text.data());
Log.report(logvisor::Fatal, "error compiling shader: %s", errBlob->GetBufferPointer()); Log.report(logvisor::Fatal, fmt("error compiling shader: %s"), errBlob->GetBufferPointer());
return {}; return {};
} }
std::pair<StageBinaryData, size_t> ret(MakeStageBinaryData(blobOut->GetBufferSize()), blobOut->GetBufferSize()); std::pair<StageBinaryData, size_t> ret(MakeStageBinaryData(blobOut->GetBufferSize()), blobOut->GetBufferSize());
@ -162,8 +162,7 @@ struct ShaderCompiler<PlatformType::Metal> {
pid_t pid = getpid(); pid_t pid = getpid();
const char* tmpdir = getenv("TMPDIR"); const char* tmpdir = getenv("TMPDIR");
char libFile[1024]; std::string libFile = fmt::format(fmt("{}boo_metal_shader{}.metallib"), tmpdir, pid);
snprintf(libFile, 1024, "%sboo_metal_shader%d.metallib", tmpdir, pid);
/* Pipe source write to compiler */ /* Pipe source write to compiler */
pid_t compilerPid = fork(); pid_t compilerPid = fork();
@ -197,7 +196,7 @@ struct ShaderCompiler<PlatformType::Metal> {
close(compilerIn[1]); close(compilerIn[1]);
/* metallib doesn't like outputting to a pipe, so temp file will have to do */ /* metallib doesn't like outputting to a pipe, so temp file will have to do */
execlp("xcrun", "xcrun", "-sdk", "macosx", "metallib", "-", "-o", libFile, NULL); execlp("xcrun", "xcrun", "-sdk", "macosx", "metallib", "-", "-o", libFile.c_str(), NULL);
fprintf(stderr, "execlp fail %s\n", strerror(errno)); fprintf(stderr, "execlp fail %s\n", strerror(errno));
exit(1); exit(1);
} }
@ -222,29 +221,29 @@ struct ShaderCompiler<PlatformType::Metal> {
while (waitpid(compilerPid, &compilerStat, 0) < 0) { while (waitpid(compilerPid, &compilerStat, 0) < 0) {
if (errno == EINTR) if (errno == EINTR)
continue; continue;
Log.report(logvisor::Fatal, "waitpid fail %s", strerror(errno)); Log.report(logvisor::Fatal, fmt("waitpid fail %s"), strerror(errno));
return {}; return {};
} }
if (WEXITSTATUS(compilerStat)) { if (WEXITSTATUS(compilerStat)) {
Log.report(logvisor::Fatal, "compile fail"); Log.report(logvisor::Fatal, fmt("compile fail"));
return {}; return {};
} }
while (waitpid(linkerPid, &linkerStat, 0) < 0) { while (waitpid(linkerPid, &linkerStat, 0) < 0) {
if (errno == EINTR) if (errno == EINTR)
continue; continue;
Log.report(logvisor::Fatal, "waitpid fail %s", strerror(errno)); Log.report(logvisor::Fatal, fmt("waitpid fail %s"), strerror(errno));
return {}; return {};
} }
if (WEXITSTATUS(linkerStat)) { if (WEXITSTATUS(linkerStat)) {
Log.report(logvisor::Fatal, "link fail"); Log.report(logvisor::Fatal, fmt("link fail"));
return {}; return {};
} }
/* Copy temp file into buffer with first byte set to indicate binary data */ /* Copy temp file into buffer with first byte set to indicate binary data */
FILE* fin = fopen(libFile, "rb"); FILE* fin = fopen(libFile.c_str(), "rb");
fseek(fin, 0, SEEK_END); fseek(fin, 0, SEEK_END);
long libLen = ftell(fin); long libLen = ftell(fin);
fseek(fin, 0, SEEK_SET); fseek(fin, 0, SEEK_SET);

View File

@ -90,7 +90,7 @@ void Console::executeString(const std::string& str) {
if (isInLiteral) { if (isInLiteral) {
if ((curLiteral.back() != '\'' && curLiteral.back() != '"') || depth > 1) { if ((curLiteral.back() != '\'' && curLiteral.back() != '"') || depth > 1) {
report(Level::Warning, "Unterminated string literal"); report(Level::Warning, fmt("Unterminated string literal"));
return; return;
} }
args.push_back(curLiteral); args.push_back(curLiteral);
@ -104,12 +104,12 @@ void Console::executeString(const std::string& str) {
if (m_commands.find(lowComName) != m_commands.end()) { if (m_commands.find(lowComName) != m_commands.end()) {
const SConsoleCommand& cmd = m_commands[lowComName]; const SConsoleCommand& cmd = m_commands[lowComName];
if (bool(cmd.m_flags & SConsoleCommand::ECommandFlags::Developer) && !com_developer->toBoolean()) { if (bool(cmd.m_flags & SConsoleCommand::ECommandFlags::Developer) && !com_developer->toBoolean()) {
report(Level::Error, "This command can only be executed in developer mode", commandName.c_str()); report(Level::Error, fmt("This command can only be executed in developer mode"), commandName);
return; return;
} }
if (bool(cmd.m_flags & SConsoleCommand::ECommandFlags::Cheat) && !com_enableCheats->toBoolean()) { if (bool(cmd.m_flags & SConsoleCommand::ECommandFlags::Cheat) && !com_enableCheats->toBoolean()) {
report(Level::Error, "This command can only be executed with cheats enabled", commandName.c_str()); report(Level::Error, fmt("This command can only be executed with cheats enabled"), commandName);
return; return;
} }
m_commands[lowComName].m_func(this, args); m_commands[lowComName].m_func(this, args);
@ -120,31 +120,31 @@ void Console::executeString(const std::string& str) {
else else
m_cvarMgr->getCVar(this, args); m_cvarMgr->getCVar(this, args);
} else } else
report(Level::Error, "Command '%s' is not valid!", commandName.c_str()); report(Level::Error, fmt("Command '{}' is not valid!"), commandName);
} }
} }
void Console::help(Console* /*con*/, const std::vector<std::string>& args) { void Console::help(Console* /*con*/, const std::vector<std::string>& args) {
if (args.empty()) { if (args.empty()) {
report(Level::Info, "Expected usage: help <command>"); report(Level::Info, fmt("Expected usage: help <command>"));
return; return;
} }
std::string cmd = args.front(); std::string cmd = args.front();
athena::utility::tolower(cmd); athena::utility::tolower(cmd);
auto it = m_commands.find(cmd); auto it = m_commands.find(cmd);
if (it == m_commands.end()) { if (it == m_commands.end()) {
report(Level::Error, "No such command '%s'", args.front().c_str()); report(Level::Error, fmt("No such command '{}'"), args.front());
return; return;
} }
report(Level::Info, "%s: %s", it->second.m_displayName.c_str(), it->second.m_helpString.c_str()); report(Level::Info, fmt("{}: {}"), it->second.m_displayName, it->second.m_helpString);
if (!it->second.m_usage.empty()) if (!it->second.m_usage.empty())
report(Level::Info, "Usage: %s %s", it->second.m_displayName.c_str(), it->second.m_usage.c_str()); report(Level::Info, fmt("Usage: {} {}"), it->second.m_displayName, it->second.m_usage);
} }
void Console::listCommands(Console* /*con*/, const std::vector<std::string>& /*args*/) { void Console::listCommands(Console* /*con*/, const std::vector<std::string>& /*args*/) {
for (const auto& comPair : m_commands) for (const auto& comPair : m_commands)
report(Level::Info, "'%s': %s", comPair.second.m_displayName.c_str(), comPair.second.m_helpString.c_str()); report(Level::Info, fmt("'{}': {}"), comPair.second.m_displayName, comPair.second.m_helpString);
} }
bool Console::commandExists(std::string_view cmd) { bool Console::commandExists(std::string_view cmd) {
@ -154,23 +154,14 @@ bool Console::commandExists(std::string_view cmd) {
return m_commands.find(cmdName) != m_commands.end(); return m_commands.find(cmdName) != m_commands.end();
} }
void Console::report(Level level, const char* fmt, va_list list) { void Console::vreport(Level level, fmt::string_view fmt, fmt::format_args args) {
char tmp[2048]; std::string tmp = fmt::vformat(fmt, args);
vsnprintf(tmp, 2048, fmt, list);
std::vector<std::string> lines = athena::utility::split(tmp, '\n'); std::vector<std::string> lines = athena::utility::split(tmp, '\n');
for (const std::string& line : lines) { for (const std::string& line : lines)
std::string v = athena::utility::sprintf("%s", line.c_str()); m_log.emplace_back(line, level);
m_log.emplace_back(v, level); fmt::print(fmt("{}\n"), tmp);
}
printf("%s\n", tmp);
} }
void Console::report(Level level, const char* fmt, ...) {
va_list ap;
va_start(ap, fmt);
report(level, fmt, ap);
va_end(ap);
}
void Console::init(boo::IWindow* window) { void Console::init(boo::IWindow* window) {
m_window = window; m_window = window;
} }
@ -187,7 +178,7 @@ void Console::proc() {
} }
if (m_state == State::Opened) { if (m_state == State::Opened) {
printf("\r%s ", m_commandString.c_str()); fmt::print(fmt("\r{} "), m_commandString);
fflush(stdout); fflush(stdout);
} else if (m_state == State::Opening) } else if (m_state == State::Opening)
m_state = State::Opened; m_state = State::Opened;
@ -290,7 +281,7 @@ void Console::handleSpecialKeyDown(boo::ESpecialKey sp, boo::EModifierKey mod, b
break; break;
} }
case boo::ESpecialKey::Enter: { case boo::ESpecialKey::Enter: {
printf("\n"); fmt::print(fmt("\n"));
executeString(m_commandString); executeString(m_commandString);
m_cursorPosition = -1; m_cursorPosition = -1;
m_commandHistory.insert(m_commandHistory.begin(), m_commandString); m_commandHistory.insert(m_commandHistory.begin(), m_commandString);
@ -372,42 +363,39 @@ void Console::handleSpecialKeyDown(boo::ESpecialKey sp, boo::EModifierKey mod, b
void Console::handleSpecialKeyUp(boo::ESpecialKey /*sp*/, boo::EModifierKey /*mod*/) {} void Console::handleSpecialKeyUp(boo::ESpecialKey /*sp*/, boo::EModifierKey /*mod*/) {}
void Console::LogVisorAdapter::report(const char* modName, logvisor::Level severity, const char* format, va_list ap) { void Console::LogVisorAdapter::report(const char* modName, logvisor::Level severity,
char tmp[2048]; fmt::string_view format, fmt::format_args args) {
vsnprintf(tmp, 2048, format, ap); auto tmp = fmt::internal::vformat(format, args);
std::vector<std::string> lines = athena::utility::split(tmp, '\n'); std::vector<std::string> lines = athena::utility::split(tmp, '\n');
for (const std::string& line : lines) { for (const std::string& line : lines) {
std::string v = athena::utility::sprintf("[%s] %s", modName, line.c_str()); auto v = fmt::format(fmt("[%s] %s"), modName, line.c_str());
m_con->m_log.emplace_back(v, Console::Level(severity)); m_con->m_log.emplace_back(v, Console::Level(severity));
} }
} }
void Console::LogVisorAdapter::report(const char* modName, logvisor::Level severity, const wchar_t* format, void Console::LogVisorAdapter::report(const char* modName, logvisor::Level severity,
va_list ap) { fmt::wstring_view format, fmt::wformat_args args) {
wchar_t tmp[2048]; auto tmp = fmt::internal::vformat(format, args);
vswprintf(tmp, 2048, format, ap);
std::vector<std::string> lines = athena::utility::split(athena::utility::wideToUtf8(tmp), '\n'); std::vector<std::string> lines = athena::utility::split(athena::utility::wideToUtf8(tmp), '\n');
for (const std::string& line : lines) { for (const std::string& line : lines) {
std::string v = athena::utility::sprintf("[%s] %s", modName, line.c_str()); auto v = fmt::format(fmt("[%s] %s"), modName, line.c_str());
m_con->m_log.emplace_back(v, Console::Level(severity)); m_con->m_log.emplace_back(v, Console::Level(severity));
} }
} }
void Console::LogVisorAdapter::reportSource(const char* modName, logvisor::Level severity, const char* file, void Console::LogVisorAdapter::reportSource(const char* modName, logvisor::Level severity, const char* file,
unsigned linenum, const char* format, va_list ap) { unsigned linenum, fmt::string_view format, fmt::format_args args) {
char tmp[2048]; auto tmp = fmt::internal::vformat(format, args);
vsnprintf(tmp, 2048, format, ap); auto v = fmt::format(fmt("[%s] %s %s:%i"), modName, tmp, file, linenum);
std::string v = athena::utility::sprintf("[%s] %s %s:%i", modName, tmp, file, linenum);
m_con->m_log.emplace_back(v, Console::Level(severity)); m_con->m_log.emplace_back(v, Console::Level(severity));
} }
void Console::LogVisorAdapter::reportSource(const char* modName, logvisor::Level severity, const char* file, void Console::LogVisorAdapter::reportSource(const char* modName, logvisor::Level severity, const char* file,
unsigned linenum, const wchar_t* format, va_list ap) { unsigned linenum, fmt::wstring_view format, fmt::wformat_args args) {
wchar_t tmp[2048]; auto tmp = fmt::internal::vformat(format, args);
vswprintf(tmp, 2048, format, ap);
std::vector<std::string> lines = athena::utility::split(athena::utility::wideToUtf8(tmp), '\n'); std::vector<std::string> lines = athena::utility::split(athena::utility::wideToUtf8(tmp), '\n');
for (const std::string& line : lines) { for (const std::string& line : lines) {
std::string v = athena::utility::sprintf("[%s] %s %s:%i", modName, line.c_str(), file, linenum); auto v = fmt::format(fmt("[%s] %s %s:%i"), modName, line.c_str(), file, linenum);
m_con->m_log.emplace_back(v, Console::Level(severity)); m_con->m_log.emplace_back(v, Console::Level(severity));
} }
} }
@ -416,16 +404,16 @@ void Console::dumpLog() {
for (const auto& l : m_log) { for (const auto& l : m_log) {
switch (l.second) { switch (l.second) {
case Level::Info: case Level::Info:
printf("%s\n", l.first.c_str()); fmt::print(fmt("{}\n"), l.first);
break; break;
case Level::Warning: case Level::Warning:
printf("[Warning] %s\n", l.first.c_str()); fmt::print(fmt("[Warning] {}\n"), l.first);
break; break;
case Level::Error: case Level::Error:
printf("[ Error ] %s\n", l.first.c_str()); fmt::print(fmt("[ Error ] {}\n"), l.first);
break; break;
case Level::Fatal: case Level::Fatal:
printf("[ Fatal ] %s\n", l.first.c_str()); fmt::print(fmt("[ Fatal ] {}\n"), l.first);
break; break;
} }
} }

View File

@ -48,7 +48,7 @@ std::string HumanizeNumber(int64_t quotient, size_t len, const char* suffix, int
if (suffix == nullptr) if (suffix == nullptr)
suffix = ""; suffix = "";
if ((flags & HNFlags::Divisor1000) != HNFlags::None && (flags & HNFlags::IECPrefixes) != HNFlags::None) if ((flags & HNFlags::Divisor1000) != HNFlags::None && (flags & HNFlags::IECPrefixes) != HNFlags::None)
Log.report(logvisor::Fatal, "invalid flags combo"); Log.report(logvisor::Fatal, fmt("invalid flags combo"));
/* setup parameters */ /* setup parameters */
remainder = 0; remainder = 0;
@ -109,8 +109,7 @@ std::string HumanizeNumber(int64_t quotient, size_t len, const char* suffix, int
/* Check if enough room for `x y' + suffix */ /* Check if enough room for `x y' + suffix */
if (len < baselen) if (len < baselen)
Log.report(logvisor::Fatal, "buffer size %" PRISize "insufficient for minimum size %" PRISize, len, baselen); Log.report(logvisor::Fatal, fmt("buffer size {} insufficient for minimum size {}"), len, baselen);
std::string ret(len, '\0');
len += 1; len += 1;
if ((scale & int(HNScale::AutoScale)) != 0) { if ((scale & int(HNScale::AutoScale)) != 0) {
@ -143,12 +142,10 @@ std::string HumanizeNumber(int64_t quotient, size_t len, const char* suffix, int
(flags & HNFlags::Decimal) != HNFlags::None) { (flags & HNFlags::Decimal) != HNFlags::None) {
s1 = (int)quotient + ((remainder * 10 + divisor / 2) / divisor / 10); s1 = (int)quotient + ((remainder * 10 + divisor / 2) / divisor / 10);
s2 = ((remainder * 10 + divisor / 2) / divisor) % 10; s2 = ((remainder * 10 + divisor / 2) / divisor) % 10;
snprintf(&ret[0], len, "%d%s%d%s%s%s", sign * s1, localeconv()->decimal_point, s2, sep, SCALE2PREFIX(i), suffix); return fmt::format(fmt("{}{}{}{}{}{}"), sign * s1, localeconv()->decimal_point, s2, sep, SCALE2PREFIX(i), suffix);
} else } else
snprintf(&ret[0], len, "%" PRId64 "%s%s%s", sign * (quotient + (remainder + divisor / 2) / divisor), sep, return fmt::format(fmt("{}{}{}{}"), sign * (quotient + (remainder + divisor / 2) / divisor), sep,
SCALE2PREFIX(i), suffix); SCALE2PREFIX(i), suffix);
return ret;
} }
} // namespace hecl } // namespace hecl

View File

@ -2,7 +2,7 @@
#define BOLD "\033[1m" #define BOLD "\033[1m"
#define NORMAL "\033[0m" #define NORMAL "\033[0m"
#define PREV_LINE "\r\033[%dA" #define PREV_LINE "\r\033[{:d}A"
#define HIDE_CURSOR "\033[?25l" #define HIDE_CURSOR "\033[?25l"
#define SHOW_CURSOR "\033[?25h" #define SHOW_CURSOR "\033[?25h"
@ -33,46 +33,46 @@ void MultiProgressPrinter::ThreadStat::print(const TermInfo& tinfo) const {
if (submessageLen) { if (submessageLen) {
if (messageLen > half - submessageLen - 1) if (messageLen > half - submessageLen - 1)
hecl::Printf(_SYS_STR(" %.*s... %s "), half - submessageLen - 4, m_message.c_str(), m_submessage.c_str()); fmt::print(fmt(_SYS_STR(" {:.{}}... {} ")), m_message, half - submessageLen - 4, m_submessage);
else { else {
hecl::Printf(_SYS_STR(" %s"), m_message.c_str()); fmt::print(fmt(_SYS_STR(" {}")), m_message);
for (int i = half - messageLen - submessageLen - 1; i >= 0; --i) for (int i = half - messageLen - submessageLen - 1; i >= 0; --i)
hecl::Printf(_SYS_STR(" ")); fmt::print(fmt(_SYS_STR(" ")));
hecl::Printf(_SYS_STR("%s "), m_submessage.c_str()); fmt::print(fmt(_SYS_STR("{} ")), m_submessage);
} }
} else { } else {
if (messageLen > half) if (messageLen > half)
hecl::Printf(_SYS_STR(" %.*s... "), half - 3, m_message.c_str()); fmt::print(fmt(_SYS_STR(" {:.{}}... ")), m_message, half - 3);
else { else {
hecl::Printf(_SYS_STR(" %s"), m_message.c_str()); fmt::print(fmt(_SYS_STR(" {}")), m_message);
for (int i = half - messageLen; i >= 0; --i) for (int i = half - messageLen; i >= 0; --i)
hecl::Printf(_SYS_STR(" ")); fmt::print(fmt(_SYS_STR(" ")));
} }
} }
if (blocks) { if (blocks) {
int rightHalf = tinfo.width - half - 4; int rightHalf = tinfo.width - half - 4;
int blocks = rightHalf - 7; int nblocks = rightHalf - 7;
int filled = blocks * factor; int filled = nblocks * factor;
int rem = blocks - filled; int rem = nblocks - filled;
if (tinfo.xtermColor) { if (tinfo.xtermColor) {
hecl::Printf(_SYS_STR("" BOLD "%3d%% ["), iFactor); fmt::print(fmt(_SYS_STR("" BOLD "{:3d}% [")), iFactor);
for (int b = 0; b < filled; ++b) for (int b = 0; b < filled; ++b)
hecl::Printf(_SYS_STR("#")); fmt::print(fmt(_SYS_STR("#")));
for (int b = 0; b < rem; ++b) for (int b = 0; b < rem; ++b)
hecl::Printf(_SYS_STR("-")); fmt::print(fmt(_SYS_STR("-")));
hecl::Printf(_SYS_STR("]" NORMAL "")); fmt::print(fmt(_SYS_STR("]" NORMAL "")));
} else { } else {
#if _WIN32 #if _WIN32
SetConsoleTextAttribute(tinfo.console, FOREGROUND_INTENSITY | FOREGROUND_WHITE); SetConsoleTextAttribute(tinfo.console, FOREGROUND_INTENSITY | FOREGROUND_WHITE);
#endif #endif
hecl::Printf(_SYS_STR("%3d%% ["), iFactor); fmt::print(fmt(_SYS_STR("{:3d}% [")), iFactor);
for (int b = 0; b < filled; ++b) for (int b = 0; b < filled; ++b)
hecl::Printf(_SYS_STR("#")); fmt::print(fmt(_SYS_STR("#")));
for (int b = 0; b < rem; ++b) for (int b = 0; b < rem; ++b)
hecl::Printf(_SYS_STR("-")); fmt::print(fmt(_SYS_STR("-")));
hecl::Printf(_SYS_STR("]")); fmt::print(fmt(_SYS_STR("]")));
#if _WIN32 #if _WIN32
SetConsoleTextAttribute(tinfo.console, FOREGROUND_WHITE); SetConsoleTextAttribute(tinfo.console, FOREGROUND_WHITE);
#endif #endif
@ -95,24 +95,24 @@ void MultiProgressPrinter::DrawIndeterminateBar() {
int rem = blocks - pre - 1; int rem = blocks - pre - 1;
if (m_termInfo.xtermColor) { if (m_termInfo.xtermColor) {
hecl::Printf(_SYS_STR("" BOLD " [")); fmt::print(fmt(_SYS_STR("" BOLD " [")));
for (int b = 0; b < pre; ++b) for (int b = 0; b < pre; ++b)
hecl::Printf(_SYS_STR("-")); fmt::print(fmt(_SYS_STR("-")));
hecl::Printf(_SYS_STR("#")); fmt::print(fmt(_SYS_STR("#")));
for (int b = 0; b < rem; ++b) for (int b = 0; b < rem; ++b)
hecl::Printf(_SYS_STR("-")); fmt::print(fmt(_SYS_STR("-")));
hecl::Printf(_SYS_STR("]" NORMAL "")); fmt::print(fmt(_SYS_STR("]" NORMAL "")));
} else { } else {
#if _WIN32 #if _WIN32
SetConsoleTextAttribute(m_termInfo.console, FOREGROUND_INTENSITY | FOREGROUND_WHITE); SetConsoleTextAttribute(m_termInfo.console, FOREGROUND_INTENSITY | FOREGROUND_WHITE);
#endif #endif
hecl::Printf(_SYS_STR(" [")); fmt::print(fmt(_SYS_STR(" [")));
for (int b = 0; b < pre; ++b) for (int b = 0; b < pre; ++b)
hecl::Printf(_SYS_STR("-")); fmt::print(fmt(_SYS_STR("-")));
hecl::Printf(_SYS_STR("#")); fmt::print(fmt(_SYS_STR("#")));
for (int b = 0; b < rem; ++b) for (int b = 0; b < rem; ++b)
hecl::Printf(_SYS_STR("-")); fmt::print(fmt(_SYS_STR("-")));
hecl::Printf(_SYS_STR("]")); fmt::print(fmt(_SYS_STR("]")));
#if _WIN32 #if _WIN32
SetConsoleTextAttribute(m_termInfo.console, FOREGROUND_WHITE); SetConsoleTextAttribute(m_termInfo.console, FOREGROUND_WHITE);
#endif #endif
@ -122,7 +122,7 @@ void MultiProgressPrinter::DrawIndeterminateBar() {
void MultiProgressPrinter::MoveCursorUp(int n) { void MultiProgressPrinter::MoveCursorUp(int n) {
if (n) { if (n) {
if (m_termInfo.xtermColor) { if (m_termInfo.xtermColor) {
hecl::Printf(_SYS_STR("" PREV_LINE ""), n); fmt::print(fmt(_SYS_STR("" PREV_LINE "")), n);
} }
#if _WIN32 #if _WIN32
else { else {
@ -134,7 +134,7 @@ void MultiProgressPrinter::MoveCursorUp(int n) {
} }
#endif #endif
} else { } else {
hecl::Printf(_SYS_STR("\r")); fmt::print(fmt(_SYS_STR("\r")));
} }
} }
@ -152,7 +152,7 @@ void MultiProgressPrinter::DoPrint() {
SetConsoleCursorInfo(m_termInfo.console, &cursorInfo); SetConsoleCursorInfo(m_termInfo.console, &cursorInfo);
#endif #endif
if (m_termInfo.xtermColor) if (m_termInfo.xtermColor)
hecl::Printf(_SYS_STR("" HIDE_CURSOR "")); fmt::print(fmt(_SYS_STR("" HIDE_CURSOR "")));
if (m_dirty) { if (m_dirty) {
m_termInfo.width = (hecl::GuiMode ? 120 : std::max(80, hecl::ConsoleWidth(&m_termInfo.truncate))); m_termInfo.width = (hecl::GuiMode ? 120 : std::max(80, hecl::ConsoleWidth(&m_termInfo.truncate)));
@ -163,7 +163,7 @@ void MultiProgressPrinter::DoPrint() {
for (const ThreadStat& stat : m_threadStats) { for (const ThreadStat& stat : m_threadStats) {
if (stat.m_active) { if (stat.m_active) {
stat.print(m_termInfo); stat.print(m_termInfo);
hecl::Printf(_SYS_STR("\n")); fmt::print(fmt(_SYS_STR("\n")));
++m_curThreadLines; ++m_curThreadLines;
} }
} }
@ -174,7 +174,7 @@ void MultiProgressPrinter::DoPrint() {
#endif #endif
) { ) {
DrawIndeterminateBar(); DrawIndeterminateBar();
hecl::Printf(_SYS_STR("\n")); fmt::print(fmt(_SYS_STR("\n")));
++m_curProgLines; ++m_curProgLines;
} else if (m_mainFactor >= 0.f) { } else if (m_mainFactor >= 0.f) {
float factor = std::max(0.0f, std::min(1.0f, m_mainFactor)); float factor = std::max(0.0f, std::min(1.0f, m_mainFactor));
@ -186,34 +186,34 @@ void MultiProgressPrinter::DoPrint() {
int rem = blocks - filled; int rem = blocks - filled;
if (m_termInfo.xtermColor) { if (m_termInfo.xtermColor) {
hecl::Printf(_SYS_STR("" BOLD " %3d%% ["), iFactor); fmt::print(fmt(_SYS_STR("" BOLD " {:3d}% [")), iFactor);
for (int b = 0; b < filled; ++b) for (int b = 0; b < filled; ++b)
hecl::Printf(_SYS_STR("#")); fmt::print(fmt(_SYS_STR("#")));
for (int b = 0; b < rem; ++b) for (int b = 0; b < rem; ++b)
hecl::Printf(_SYS_STR("-")); fmt::print(fmt(_SYS_STR("-")));
hecl::Printf(_SYS_STR("]" NORMAL "")); fmt::print(fmt(_SYS_STR("]" NORMAL "")));
} else { } else {
#if _WIN32 #if _WIN32
SetConsoleTextAttribute(m_termInfo.console, FOREGROUND_INTENSITY | FOREGROUND_WHITE); SetConsoleTextAttribute(m_termInfo.console, FOREGROUND_INTENSITY | FOREGROUND_WHITE);
#endif #endif
hecl::Printf(_SYS_STR(" %3d%% ["), iFactor); fmt::print(fmt(_SYS_STR(" {:3d}% [")), iFactor);
for (int b = 0; b < filled; ++b) for (int b = 0; b < filled; ++b)
hecl::Printf(_SYS_STR("#")); fmt::print(fmt(_SYS_STR("#")));
for (int b = 0; b < rem; ++b) for (int b = 0; b < rem; ++b)
hecl::Printf(_SYS_STR("-")); fmt::print(fmt(_SYS_STR("-")));
hecl::Printf(_SYS_STR("]")); fmt::print(fmt(_SYS_STR("]")));
#if _WIN32 #if _WIN32
SetConsoleTextAttribute(m_termInfo.console, FOREGROUND_WHITE); SetConsoleTextAttribute(m_termInfo.console, FOREGROUND_WHITE);
#endif #endif
} }
hecl::Printf(_SYS_STR("\n")); fmt::print(fmt(_SYS_STR("\n")));
++m_curProgLines; ++m_curProgLines;
} }
} else if (m_latestThread != -1) { } else if (m_latestThread != -1) {
const ThreadStat& stat = m_threadStats[m_latestThread]; const ThreadStat& stat = m_threadStats[m_latestThread];
stat.print(m_termInfo); stat.print(m_termInfo);
hecl::Printf(_SYS_STR("\r")); fmt::print(fmt(_SYS_STR("\r")));
} }
m_dirty = false; m_dirty = false;
} else if (m_mainIndeterminate } else if (m_mainIndeterminate
@ -225,12 +225,12 @@ void MultiProgressPrinter::DoPrint() {
MoveCursorUp(m_curProgLines); MoveCursorUp(m_curProgLines);
m_curProgLines = 0; m_curProgLines = 0;
DrawIndeterminateBar(); DrawIndeterminateBar();
hecl::Printf(_SYS_STR("\n")); fmt::print(fmt(_SYS_STR("\n")));
++m_curProgLines; ++m_curProgLines;
} }
if (m_termInfo.xtermColor) if (m_termInfo.xtermColor)
hecl::Printf(_SYS_STR("" SHOW_CURSOR "")); fmt::print(fmt(_SYS_STR("" SHOW_CURSOR "")));
fflush(stdout); fflush(stdout);
#if _WIN32 #if _WIN32
@ -331,7 +331,7 @@ void MultiProgressPrinter::startNewLine() const {
m_curThreadLines = 0; m_curThreadLines = 0;
m_mainFactor = -1.f; m_mainFactor = -1.f;
auto logLk = logvisor::LockLog(); auto logLk = logvisor::LockLog();
hecl::Printf(_SYS_STR("\n")); fmt::print(fmt(_SYS_STR("\n")));
} }
void MultiProgressPrinter::flush() const { void MultiProgressPrinter::flush() const {

View File

@ -23,7 +23,7 @@ static const hecl::FourCC HECLfcc("HECL");
* Project::ConfigFile * Project::ConfigFile
**********************************************/ **********************************************/
static inline bool CheckNewLineAdvance(std::string::const_iterator& it) { static bool CheckNewLineAdvance(std::string::const_iterator& it) {
if (*it == '\n') { if (*it == '\n') {
it += 1; it += 1;
return true; return true;
@ -84,7 +84,7 @@ void Project::ConfigFile::addLine(std::string_view line) {
void Project::ConfigFile::removeLine(std::string_view refLine) { void Project::ConfigFile::removeLine(std::string_view refLine) {
if (!m_lockedFile) { if (!m_lockedFile) {
LogModule.reportSource(logvisor::Fatal, __FILE__, __LINE__, "Project::ConfigFile::lockAndRead not yet called"); LogModule.reportSource(logvisor::Fatal, __FILE__, __LINE__, fmt("Project::ConfigFile::lockAndRead not yet called"));
return; return;
} }
@ -99,7 +99,7 @@ void Project::ConfigFile::removeLine(std::string_view refLine) {
bool Project::ConfigFile::checkForLine(std::string_view refLine) { bool Project::ConfigFile::checkForLine(std::string_view refLine) {
if (!m_lockedFile) { if (!m_lockedFile) {
LogModule.reportSource(logvisor::Fatal, __FILE__, __LINE__, "Project::ConfigFile::lockAndRead not yet called"); LogModule.reportSource(logvisor::Fatal, __FILE__, __LINE__, fmt("Project::ConfigFile::lockAndRead not yet called"));
return false; return false;
} }
@ -111,7 +111,7 @@ bool Project::ConfigFile::checkForLine(std::string_view refLine) {
void Project::ConfigFile::unlockAndDiscard() { void Project::ConfigFile::unlockAndDiscard() {
if (!m_lockedFile) { if (!m_lockedFile) {
LogModule.reportSource(logvisor::Fatal, __FILE__, __LINE__, "Project::ConfigFile::lockAndRead not yet called"); LogModule.reportSource(logvisor::Fatal, __FILE__, __LINE__, fmt("Project::ConfigFile::lockAndRead not yet called"));
return; return;
} }
@ -122,7 +122,7 @@ void Project::ConfigFile::unlockAndDiscard() {
bool Project::ConfigFile::unlockAndCommit() { bool Project::ConfigFile::unlockAndCommit() {
if (!m_lockedFile) { if (!m_lockedFile) {
LogModule.reportSource(logvisor::Fatal, __FILE__, __LINE__, "Project::ConfigFile::lockAndRead not yet called"); LogModule.reportSource(logvisor::Fatal, __FILE__, __LINE__, fmt("Project::ConfigFile::lockAndRead not yet called"));
return false; return false;
} }
@ -176,13 +176,13 @@ Project::Project(const ProjectRootPath& rootPath)
/* Stat for existing project directory (must already exist) */ /* Stat for existing project directory (must already exist) */
Sstat myStat; Sstat myStat;
if (hecl::Stat(m_rootPath.getAbsolutePath().data(), &myStat)) { if (hecl::Stat(m_rootPath.getAbsolutePath().data(), &myStat)) {
LogModule.report(logvisor::Error, _SYS_STR("unable to stat %s"), m_rootPath.getAbsolutePath().data()); LogModule.report(logvisor::Error, fmt(_SYS_STR("unable to stat {}")), m_rootPath.getAbsolutePath());
return; return;
} }
if (!S_ISDIR(myStat.st_mode)) { if (!S_ISDIR(myStat.st_mode)) {
LogModule.report(logvisor::Error, _SYS_STR("provided path must be a directory; '%s' isn't"), LogModule.report(logvisor::Error, fmt(_SYS_STR("provided path must be a directory; '{}' isn't")),
m_rootPath.getAbsolutePath().data()); m_rootPath.getAbsolutePath());
return; return;
} }
@ -206,7 +206,7 @@ Project::Project(const ProjectRootPath& rootPath)
} }
fclose(bf); fclose(bf);
if (beacon.magic != HECLfcc || SBig(beacon.version) != DATA_VERSION) { if (beacon.magic != HECLfcc || SBig(beacon.version) != DATA_VERSION) {
LogModule.report(logvisor::Fatal, "incompatible project version"); LogModule.report(logvisor::Fatal, fmt("incompatible project version"));
return; return;
} }
@ -219,7 +219,7 @@ const ProjectPath& Project::getProjectCookedPath(const DataSpecEntry& spec) cons
for (const ProjectDataSpec& sp : m_compiledSpecs) for (const ProjectDataSpec& sp : m_compiledSpecs)
if (&sp.spec == &spec) if (&sp.spec == &spec)
return sp.cookedPath; return sp.cookedPath;
LogModule.report(logvisor::Fatal, "Unable to find spec '%s'", spec.m_name.data()); LogModule.report(logvisor::Fatal, fmt("Unable to find spec '{}'"), spec.m_name);
return m_cookedRoot; return m_cookedRoot;
} }
@ -460,7 +460,7 @@ bool Project::packagePath(const ProjectPath& path, const hecl::MultiProgressPrin
} }
if (!specEntry) if (!specEntry)
LogModule.report(logvisor::Fatal, "No matching DataSpec"); LogModule.report(logvisor::Fatal, fmt("No matching DataSpec"));
if (!m_lastPackageSpec || m_lastPackageSpec->getDataSpecEntry() != specEntry) if (!m_lastPackageSpec || m_lastPackageSpec->getDataSpecEntry() != specEntry)
m_lastPackageSpec = specEntry->m_factory(*this, DataSpecTool::Package); m_lastPackageSpec = specEntry->m_factory(*this, DataSpecTool::Package);

View File

@ -19,7 +19,7 @@ static SystemString CanonRelPath(SystemStringView path) {
else if (!match.compare(_SYS_STR(".."))) { else if (!match.compare(_SYS_STR(".."))) {
if (comps.empty()) { if (comps.empty()) {
/* Unable to resolve outside project */ /* Unable to resolve outside project */
LogModule.report(logvisor::Fatal, _SYS_STR("Unable to resolve outside project root in %s"), path.data()); LogModule.report(logvisor::Fatal, fmt(_SYS_STR("Unable to resolve outside project root in {}")), path);
return _SYS_STR("."); return _SYS_STR(".");
} }
comps.pop_back(); comps.pop_back();
@ -180,7 +180,7 @@ Time ProjectPath::getModtime() const {
return Time(latestTime); return Time(latestTime);
} }
} }
LogModule.report(logvisor::Fatal, _SYS_STR("invalid path type for computing modtime in '%s'"), m_absPath.c_str()); LogModule.report(logvisor::Fatal, fmt(_SYS_STR("invalid path type for computing modtime in '{}'")), m_absPath);
return Time(); return Time();
} }

View File

@ -16,7 +16,7 @@ FileStoreManager::FileStoreManager(SystemStringView domain) : m_domain(domain) {
#if !WINDOWS_STORE #if !WINDOWS_STORE
WCHAR home[MAX_PATH]; WCHAR home[MAX_PATH];
if (!SUCCEEDED(SHGetFolderPathW(NULL, CSIDL_PROFILE, NULL, 0, home))) if (!SUCCEEDED(SHGetFolderPathW(NULL, CSIDL_PROFILE, NULL, 0, home)))
Log.report(logvisor::Fatal, _SYS_STR("unable to locate profile for file store")); Log.report(logvisor::Fatal, fmt(_SYS_STR("unable to locate profile for file store")));
SystemString path(home); SystemString path(home);
#else #else
@ -34,15 +34,15 @@ FileStoreManager::FileStoreManager(SystemStringView domain) : m_domain(domain) {
#else #else
const char* home = getenv("HOME"); const char* home = getenv("HOME");
if (!home) if (!home)
Log.report(logvisor::Fatal, "unable to locate $HOME for file store"); Log.report(logvisor::Fatal, fmt("unable to locate $HOME for file store"));
std::string path(home); std::string path(home);
path += "/.heclrun"; path += "/.heclrun";
if (mkdir(path.c_str(), 0755) && errno != EEXIST) if (mkdir(path.c_str(), 0755) && errno != EEXIST)
Log.report(logvisor::Fatal, "unable to mkdir at %s", path.c_str()); Log.report(logvisor::Fatal, fmt("unable to mkdir at {}"), path);
path += '/'; path += '/';
path += domain.data(); path += domain.data();
if (mkdir(path.c_str(), 0755) && errno != EEXIST) if (mkdir(path.c_str(), 0755) && errno != EEXIST)
Log.report(logvisor::Fatal, "unable to mkdir at %s", path.c_str()); Log.report(logvisor::Fatal, fmt("unable to mkdir at {}"), path);
m_storeRoot = path; m_storeRoot = path;
#endif #endif
} }

View File

@ -12,7 +12,7 @@ HMDLData::HMDLData(boo::IGraphicsDataFactory::Context& ctx, const void* metaData
meta.read(r); meta.read(r);
} }
if (meta.magic != 'TACO') if (meta.magic != 'TACO')
HMDL_Log.report(logvisor::Fatal, "invalid HMDL magic"); HMDL_Log.report(logvisor::Fatal, fmt("invalid HMDL magic"));
m_vbo = ctx.newStaticBuffer(boo::BufferUse::Vertex, vbo, meta.vertStride, meta.vertCount); m_vbo = ctx.newStaticBuffer(boo::BufferUse::Vertex, vbo, meta.vertStride, meta.vertCount);
m_ibo = ctx.newStaticBuffer(boo::BufferUse::Index, ibo, 4, meta.indexCount); m_ibo = ctx.newStaticBuffer(boo::BufferUse::Index, ibo, 4, meta.indexCount);

View File

@ -11,7 +11,7 @@ std::string WideToUTF8(std::wstring_view src) {
utf8proc_uint8_t mb[4]; utf8proc_uint8_t mb[4];
utf8proc_ssize_t c = utf8proc_encode_char(utf8proc_int32_t(ch), mb); utf8proc_ssize_t c = utf8proc_encode_char(utf8proc_int32_t(ch), mb);
if (c < 0) { if (c < 0) {
Log.report(logvisor::Warning, "invalid UTF-8 character while encoding"); Log.report(logvisor::Warning, fmt("invalid UTF-8 character while encoding"));
return retval; return retval;
} }
retval.append(reinterpret_cast<char*>(mb), c); retval.append(reinterpret_cast<char*>(mb), c);
@ -26,7 +26,7 @@ std::string Char16ToUTF8(std::u16string_view src) {
utf8proc_uint8_t mb[4]; utf8proc_uint8_t mb[4];
utf8proc_ssize_t c = utf8proc_encode_char(utf8proc_int32_t(ch), mb); utf8proc_ssize_t c = utf8proc_encode_char(utf8proc_int32_t(ch), mb);
if (c < 0) { if (c < 0) {
Log.report(logvisor::Warning, "invalid UTF-8 character while encoding"); Log.report(logvisor::Warning, fmt("invalid UTF-8 character while encoding"));
return retval; return retval;
} }
retval.append(reinterpret_cast<char*>(mb), c); retval.append(reinterpret_cast<char*>(mb), c);
@ -42,7 +42,7 @@ std::wstring UTF8ToWide(std::string_view src) {
utf8proc_int32_t wc; utf8proc_int32_t wc;
utf8proc_ssize_t len = utf8proc_iterate(buf, -1, &wc); utf8proc_ssize_t len = utf8proc_iterate(buf, -1, &wc);
if (len < 0) { if (len < 0) {
Log.report(logvisor::Warning, "invalid UTF-8 character while decoding"); Log.report(logvisor::Warning, fmt("invalid UTF-8 character while decoding"));
return retval; return retval;
} }
buf += len; buf += len;
@ -59,7 +59,7 @@ std::u16string UTF8ToChar16(std::string_view src) {
utf8proc_int32_t wc; utf8proc_int32_t wc;
utf8proc_ssize_t len = utf8proc_iterate(buf, -1, &wc); utf8proc_ssize_t len = utf8proc_iterate(buf, -1, &wc);
if (len < 0) { if (len < 0) {
Log.report(logvisor::Warning, "invalid UTF-8 character while decoding"); Log.report(logvisor::Warning, fmt("invalid UTF-8 character while decoding"));
return retval; return retval;
} }
buf += len; buf += len;

View File

@ -26,58 +26,6 @@ bool GuiMode = false;
logvisor::Module LogModule("hecl"); logvisor::Module LogModule("hecl");
static const std::string Illegals{"<>?\""}; static const std::string Illegals{"<>?\""};
#if __GNUC__
__attribute__((__format__(__printf__, 1, 2)))
#endif
SystemString
SysFormat(const SystemChar* format, ...) {
SystemChar resultBuf[FORMAT_BUF_SZ];
va_list va;
va_start(va, format);
#if HECL_UCS2
int printSz = vswprintf(resultBuf, FORMAT_BUF_SZ, format, va);
#else
int printSz = vsnprintf(resultBuf, FORMAT_BUF_SZ, format, va);
#endif
va_end(va);
return SystemString(resultBuf, printSz);
}
#if __GNUC__
__attribute__((__format__(__printf__, 1, 2)))
#endif
std::string
Format(const char* format, ...) {
char resultBuf[FORMAT_BUF_SZ];
va_list va;
va_start(va, format);
int printSz = vsnprintf(resultBuf, FORMAT_BUF_SZ, format, va);
va_end(va);
return std::string(resultBuf, printSz);
}
std::wstring WideFormat(const wchar_t* format, ...) {
wchar_t resultBuf[FORMAT_BUF_SZ];
va_list va;
va_start(va, format);
int printSz = vswprintf(resultBuf, FORMAT_BUF_SZ, format, va);
va_end(va);
return std::wstring(resultBuf, printSz);
}
std::u16string Char16Format(const wchar_t* format, ...) {
wchar_t resultBuf[FORMAT_BUF_SZ];
va_list va;
va_start(va, format);
size_t printSz = vswprintf(resultBuf, FORMAT_BUF_SZ, format, va);
va_end(va);
std::u16string res;
res.reserve(printSz);
for (size_t i = 0; i < printSz; ++i)
res.push_back(resultBuf[i]);
return res;
}
void SanitizePath(std::string& path) { void SanitizePath(std::string& path) {
if (path.empty()) if (path.empty())
return; return;
@ -146,7 +94,7 @@ SystemString GetcwdStr() {
return SystemString(stackBuffer); return SystemString(stackBuffer);
if (errno != ERANGE) { if (errno != ERANGE) {
// It's not ERANGE, so we don't know how to handle it // It's not ERANGE, so we don't know how to handle it
LogModule.report(logvisor::Fatal, "Cannot determine the current path."); LogModule.report(logvisor::Fatal, fmt("Cannot determine the current path."));
// Of course you may choose a different error reporting method // Of course you may choose a different error reporting method
} }
// Ok, the stack buffer isn't long enough; fallback to heap allocation // Ok, the stack buffer isn't long enough; fallback to heap allocation
@ -158,11 +106,11 @@ SystemString GetcwdStr() {
return SystemString(cwd.get()); return SystemString(cwd.get());
if (errno != ERANGE) { if (errno != ERANGE) {
// It's not ERANGE, so we don't know how to handle it // It's not ERANGE, so we don't know how to handle it
LogModule.report(logvisor::Fatal, "Cannot determine the current path."); LogModule.report(logvisor::Fatal, fmt("Cannot determine the current path."));
// Of course you may choose a different error reporting method // Of course you may choose a different error reporting method
} }
} }
LogModule.report(logvisor::Fatal, "Cannot determine the current path; the path is apparently unreasonably long"); LogModule.report(logvisor::Fatal, fmt("Cannot determine the current path; the path is apparently unreasonably long"));
return SystemString(); return SystemString();
} }
@ -180,7 +128,7 @@ bool ResourceLock::InProgress(const ProjectPath& path) {
bool ResourceLock::SetThreadRes(const ProjectPath& path) { bool ResourceLock::SetThreadRes(const ProjectPath& path) {
std::unique_lock<std::mutex> lk(PathsMutex); std::unique_lock<std::mutex> lk(PathsMutex);
if (PathsInProgress.find(std::this_thread::get_id()) != PathsInProgress.cend()) if (PathsInProgress.find(std::this_thread::get_id()) != PathsInProgress.cend())
LogModule.report(logvisor::Fatal, "multiple resource locks on thread"); LogModule.report(logvisor::Fatal, fmt("multiple resource locks on thread"));
for (const auto& p : PathsInProgress) for (const auto& p : PathsInProgress)
if (p.second == path) if (p.second == path)
@ -752,13 +700,13 @@ int RunProcess(const SystemChar* path, const SystemChar* const args[]) {
SECURITY_ATTRIBUTES sattrs = {sizeof(SECURITY_ATTRIBUTES), NULL, TRUE}; SECURITY_ATTRIBUTES sattrs = {sizeof(SECURITY_ATTRIBUTES), NULL, TRUE};
HANDLE consoleOutReadTmp, consoleOutWrite, consoleErrWrite, consoleOutRead; HANDLE consoleOutReadTmp, consoleOutWrite, consoleErrWrite, consoleOutRead;
if (!CreatePipe(&consoleOutReadTmp, &consoleOutWrite, &sattrs, 0)) { if (!CreatePipe(&consoleOutReadTmp, &consoleOutWrite, &sattrs, 0)) {
LogModule.report(logvisor::Fatal, "Error with CreatePipe"); LogModule.report(logvisor::Fatal, fmt("Error with CreatePipe"));
return -1; return -1;
} }
if (!DuplicateHandle(GetCurrentProcess(), consoleOutWrite, GetCurrentProcess(), &consoleErrWrite, 0, TRUE, if (!DuplicateHandle(GetCurrentProcess(), consoleOutWrite, GetCurrentProcess(), &consoleErrWrite, 0, TRUE,
DUPLICATE_SAME_ACCESS)) { DUPLICATE_SAME_ACCESS)) {
LogModule.report(logvisor::Fatal, "Error with DuplicateHandle"); LogModule.report(logvisor::Fatal, fmt("Error with DuplicateHandle"));
CloseHandle(consoleOutReadTmp); CloseHandle(consoleOutReadTmp);
CloseHandle(consoleOutWrite); CloseHandle(consoleOutWrite);
return -1; return -1;
@ -768,7 +716,7 @@ int RunProcess(const SystemChar* path, const SystemChar* const args[]) {
&consoleOutRead, // Address of new handle. &consoleOutRead, // Address of new handle.
0, FALSE, // Make it uninheritable. 0, FALSE, // Make it uninheritable.
DUPLICATE_SAME_ACCESS)) { DUPLICATE_SAME_ACCESS)) {
LogModule.report(logvisor::Fatal, "Error with DupliateHandle"); LogModule.report(logvisor::Fatal, fmt("Error with DupliateHandle"));
CloseHandle(consoleOutReadTmp); CloseHandle(consoleOutReadTmp);
CloseHandle(consoleOutWrite); CloseHandle(consoleOutWrite);
CloseHandle(consoleErrWrite); CloseHandle(consoleErrWrite);
@ -825,13 +773,13 @@ int RunProcess(const SystemChar* path, const SystemChar* const args[]) {
if (err == ERROR_BROKEN_PIPE) if (err == ERROR_BROKEN_PIPE)
break; // pipe done - normal exit path. break; // pipe done - normal exit path.
else else
LogModule.report(logvisor::Error, "Error with ReadFile: %08X", err); // Something bad happened. LogModule.report(logvisor::Error, fmt("Error with ReadFile: %08X"), err); // Something bad happened.
} }
// Display the character read on the screen. // Display the character read on the screen.
auto lk = logvisor::LockLog(); auto lk = logvisor::LockLog();
if (!WriteConsoleA(GetStdHandle(STD_OUTPUT_HANDLE), lpBuffer, nBytesRead, &nCharsWritten, NULL)) { if (!WriteConsoleA(GetStdHandle(STD_OUTPUT_HANDLE), lpBuffer, nBytesRead, &nCharsWritten, NULL)) {
// LogModule.report(logvisor::Error, "Error with WriteConsole: %08X", GetLastError()); // LogModule.report(logvisor::Error, fmt("Error with WriteConsole: %08X"), GetLastError());
} }
} }

View File

@ -3,6 +3,7 @@
#include "athena/FileWriter.hpp" #include "athena/FileWriter.hpp"
#include "glslang/Public/ShaderLang.h" #include "glslang/Public/ShaderLang.h"
#include "hecl/hecl.hpp" #include "hecl/hecl.hpp"
#include <sstream>
static logvisor::Module Log("shaderc"); static logvisor::Module Log("shaderc");
@ -42,13 +43,13 @@ int main(int argc, const hecl::SystemChar** argv)
#if _WIN32 #if _WIN32
if (!FindBestD3DCompile()) { if (!FindBestD3DCompile()) {
Log.report(logvisor::Info, "Unable to find D3DCompiler dll"); Log.report(logvisor::Info, fmt("Unable to find D3DCompiler dll"));
return 1; return 1;
} }
#endif #endif
if (argc == 1) { if (argc == 1) {
Log.report(logvisor::Info, "Usage: shaderc -o <out-base> [-D definevar=defineval]... <in-files>..."); Log.report(logvisor::Info, fmt("Usage: shaderc -o <out-base> [-D definevar=defineval]... <in-files>..."));
return 0; return 0;
} }
@ -63,7 +64,7 @@ int main(int argc, const hecl::SystemChar** argv)
++i; ++i;
outPath = argv[i]; outPath = argv[i];
} else { } else {
Log.report(logvisor::Error, "Invalid -o argument"); Log.report(logvisor::Error, fmt("Invalid -o argument"));
return 1; return 1;
} }
} else if (argv[i][1] == 'D') { } else if (argv[i][1] == 'D') {
@ -74,7 +75,7 @@ int main(int argc, const hecl::SystemChar** argv)
++i; ++i;
define = argv[i]; define = argv[i];
} else { } else {
Log.report(logvisor::Error, "Invalid -D argument"); Log.report(logvisor::Error, fmt("Invalid -D argument"));
return 1; return 1;
} }
hecl::SystemUTF8Conv conv(define); hecl::SystemUTF8Conv conv(define);
@ -84,7 +85,7 @@ int main(int argc, const hecl::SystemChar** argv)
else else
c.addDefine(defineU8, ""); c.addDefine(defineU8, "");
} else { } else {
Log.report(logvisor::Error, "Unrecognized flag option '%c'", argv[i][1]); Log.report(logvisor::Error, fmt("Unrecognized flag option '{:c}'"), argv[i][1]);
return 1; return 1;
} }
} else { } else {
@ -93,7 +94,7 @@ int main(int argc, const hecl::SystemChar** argv)
} }
if (outPath.empty()) { if (outPath.empty()) {
Log.report(logvisor::Error, "-o option is required"); Log.report(logvisor::Error, fmt("-o option is required"));
return 1; return 1;
} }
@ -105,12 +106,12 @@ int main(int argc, const hecl::SystemChar** argv)
baseName = outPath; baseName = outPath;
if (!glslang::InitializeProcess()) { if (!glslang::InitializeProcess()) {
Log.report(logvisor::Error, "Unable to initialize glslang"); Log.report(logvisor::Error, fmt("Unable to initialize glslang"));
return 1; return 1;
} }
hecl::SystemUTF8Conv conv(baseName); hecl::SystemUTF8Conv conv(baseName);
std::pair<std::string, std::string> ret; std::pair<std::stringstream, std::stringstream> ret;
if (!c.compile(conv.str(), ret)) if (!c.compile(conv.str(), ret))
return 1; return 1;
@ -118,20 +119,22 @@ int main(int argc, const hecl::SystemChar** argv)
hecl::SystemString headerPath = outPath + _SYS_STR(".hpp"); hecl::SystemString headerPath = outPath + _SYS_STR(".hpp");
athena::io::FileWriter w(headerPath); athena::io::FileWriter w(headerPath);
if (w.hasError()) { if (w.hasError()) {
Log.report(logvisor::Error, _SYS_STR("Error opening '%s' for writing"), headerPath.c_str()); Log.report(logvisor::Error, fmt(_SYS_STR("Error opening '{}' for writing")), headerPath);
return 1; return 1;
} }
w.writeBytes(ret.first.data(), ret.first.size()); std::string header = ret.first.str();
w.writeBytes(header.data(), header.size());
} }
{ {
hecl::SystemString impPath = outPath + _SYS_STR(".cpp"); hecl::SystemString impPath = outPath + _SYS_STR(".cpp");
athena::io::FileWriter w(impPath); athena::io::FileWriter w(impPath);
if (w.hasError()) { if (w.hasError()) {
Log.report(logvisor::Error, _SYS_STR("Error opening '%s' for writing"), impPath.c_str()); Log.report(logvisor::Error, fmt(_SYS_STR("Error opening '{}' for writing")), impPath);
return 1; return 1;
} }
w.writeBytes(ret.second.data(), ret.second.size()); std::string source = ret.second.str();
w.writeBytes(source.data(), source.size());
} }
return 0; return 0;

View File

@ -10,26 +10,15 @@
#include <bitset> #include <bitset>
#include <memory> #include <memory>
#include <cstdint> #include <cstdint>
#include <fmt/ostream.h>
#include <sstream>
using namespace std::literals; using namespace std::literals;
namespace hecl::shaderc { namespace hecl::shaderc {
static logvisor::Module Log("shaderc"); static logvisor::Module Log("shaderc");
static constexpr std::regex::flag_type RegexFlags = std::regex::ECMAScript | std::regex::optimize; constexpr std::regex::flag_type RegexFlags = std::regex::ECMAScript | std::regex::optimize;
#if __GNUC__
__attribute__((__format__(__printf__, 1, 2)))
#endif
static std::string
Format(const char* format, ...) {
char resultBuf[FORMAT_BUF_SZ];
va_list va;
va_start(va, format);
int printSz = vsnprintf(resultBuf, FORMAT_BUF_SZ, format, va);
va_end(va);
return std::string(resultBuf, printSz);
}
static const char* StageNames[] = { static const char* StageNames[] = {
"hecl::PipelineStage::Vertex", "hecl::PipelineStage::Vertex",
@ -59,41 +48,41 @@ void Compiler::addInputFile(SystemStringView file) {
void Compiler::addDefine(std::string_view var, std::string_view val) { m_defines[var.data()] = val; } void Compiler::addDefine(std::string_view var, std::string_view val) { m_defines[var.data()] = val; }
static const char* ShaderHeaderTemplate = constexpr auto ShaderHeaderTemplate = fmt(
"class Shader_%s : public hecl::GeneralShader\n" "class Shader_{} : public hecl::GeneralShader\n"
"{\n" "{{\n"
"public:\n" "public:\n"
" static const boo::VertexFormatInfo VtxFmt;\n" " static const boo::VertexFormatInfo VtxFmt;\n"
" static const boo::AdditionalPipelineInfo PipelineInfo;\n" " static const boo::AdditionalPipelineInfo PipelineInfo;\n"
" static constexpr bool HasHash = true;\n" " static constexpr bool HasHash = true;\n"
" static constexpr uint64_t Hash() { return 0x%016llX; }\n" " static constexpr uint64_t Hash() {{ return 0x{:016X}; }}\n"
" static constexpr bool HasStageHash = true;\n" " static constexpr bool HasStageHash = true;\n"
" template <typename S>\n" " template <typename S>\n"
" static constexpr uint64_t StageHash();\n" " static constexpr uint64_t StageHash();\n"
"};\n\n"; "}};\n\n");
static const char* StageObjectHeaderTemplate = constexpr auto StageObjectHeaderTemplate = fmt(
"template<typename P, typename S>\n" "template<typename P, typename S>\n"
"class StageObject_%s : public hecl::StageBinary<P, S>\n" "class StageObject_{} : public hecl::StageBinary<P, S>\n"
"{\n" "{{\n"
" static const hecl::StageBinary<P, S> Prototype;\n" " static const hecl::StageBinary<P, S> Prototype;\n"
"public:\n" "public:\n"
" StageObject_%s(hecl::StageConverter<P, S>& conv, hecl::FactoryCtx& ctx, const Shader_%s& in)\n" " StageObject_{}(hecl::StageConverter<P, S>& conv, hecl::FactoryCtx& ctx, const Shader_{}& in)\n"
" : hecl::StageBinary<P, S>(Prototype) {}\n" " : hecl::StageBinary<P, S>(Prototype) {{}}\n"
"};\n" "}};\n"
"STAGEOBJECT_PROTOTYPE_DECLARATIONS(StageObject_%s)\n\n"; "STAGEOBJECT_PROTOTYPE_DECLARATIONS(StageObject_{})\n\n");
static const char* StageObjectImplTemplate = constexpr auto StageObjectImplTemplate = fmt(
"template<>\n" "template<>\n"
"const hecl::StageBinary<hecl::PlatformType::%s, hecl::PipelineStage::%s>\n" "const hecl::StageBinary<hecl::PlatformType::{}, hecl::PipelineStage::{}>\n"
"StageObject_%s<hecl::PlatformType::%s, hecl::PipelineStage::%s>::Prototype = \n" "StageObject_{}<hecl::PlatformType::{}, hecl::PipelineStage::{}>::Prototype = \n"
"{%s_%s_%s_data, sizeof(%s_%s_%s_data)};\n\n"; "{{{}_{}_{}_data, sizeof({}_{}_{}_data)}};\n\n");
struct CompileSubStageAction { struct CompileSubStageAction {
template <typename P, typename S> template <typename P, typename S>
static bool Do(const std::string& name, const std::string& basename, const std::string& stage, std::string& implOut) { static bool Do(const std::string& name, const std::string& basename, const std::string& stage, std::stringstream& out) {
implOut += Format(StageObjectImplTemplate, P::Name, S::Name, name.c_str(), P::Name, S::Name, basename.c_str(), fmt::print(out, StageObjectImplTemplate, P::Name, S::Name, name, P::Name, S::Name, basename,
P::Name, S::Name, basename.c_str(), P::Name, S::Name); P::Name, S::Name, basename, P::Name, S::Name);
return true; return true;
} }
@ -101,21 +90,21 @@ struct CompileSubStageAction {
struct CompileStageAction { struct CompileStageAction {
template <typename P, typename S> template <typename P, typename S>
static bool Do(const std::string& name, const std::string& basename, const std::string& stage, std::string& implOut) { static bool Do(const std::string& name, const std::string& basename, const std::string& stage, std::stringstream& out) {
std::pair<StageBinaryData, size_t> data = CompileShader<P, S>(stage); std::pair<StageBinaryData, size_t> data = CompileShader<P, S>(stage);
if (data.second == 0) if (data.second == 0)
return false; return false;
implOut += Format("static const uint8_t %s_%s_%s_data[] = {\n", name.c_str(), P::Name, S::Name); fmt::print(out, fmt("static const uint8_t {}_{}_{}_data[] = {{\n"), name, P::Name, S::Name);
for (size_t i = 0; i < data.second;) { for (size_t i = 0; i < data.second;) {
implOut += " "; out << " ";
for (int j = 0; j < 10 && i < data.second; ++i, ++j) for (int j = 0; j < 10 && i < data.second; ++i, ++j)
implOut += Format("0x%02X, ", data.first.get()[i]); fmt::print(out, fmt("0x{:02X}, "), data.first.get()[i]);
implOut += "\n"; out << "\n";
} }
implOut += "};\n\n"; out << "};\n\n";
implOut += Format(StageObjectImplTemplate, P::Name, S::Name, name.c_str(), P::Name, S::Name, name.c_str(), P::Name, fmt::print(out, StageObjectImplTemplate, P::Name, S::Name, name, P::Name, S::Name, name,
S::Name, name.c_str(), P::Name, S::Name); P::Name, S::Name, name, P::Name, S::Name);
return true; return true;
} }
@ -123,7 +112,7 @@ struct CompileStageAction {
template <typename Action, typename P> template <typename Action, typename P>
bool Compiler::StageAction(StageType type, const std::string& name, const std::string& basename, bool Compiler::StageAction(StageType type, const std::string& name, const std::string& basename,
const std::string& stage, std::string& implOut) { const std::string& stage, std::stringstream& implOut) {
switch (type) { switch (type) {
case StageType::Vertex: case StageType::Vertex:
return Action::template Do<P, PipelineStage::Vertex>(name, basename, stage, implOut); return Action::template Do<P, PipelineStage::Vertex>(name, basename, stage, implOut);
@ -138,7 +127,7 @@ bool Compiler::StageAction(StageType type, const std::string& name, const std::s
default: default:
break; break;
} }
Log.report(logvisor::Error, "Unknown stage type"); Log.report(logvisor::Error, fmt("Unknown stage type"));
return false; return false;
} }
@ -146,7 +135,7 @@ static const std::regex regWord(R"((\w+))", RegexFlags);
template <typename Action> template <typename Action>
bool Compiler::StageAction(const std::string& platforms, StageType type, const std::string& name, bool Compiler::StageAction(const std::string& platforms, StageType type, const std::string& name,
const std::string& basename, const std::string& stage, std::string& implOut) { const std::string& basename, const std::string& stage, std::stringstream& implOut) {
std::smatch match; std::smatch match;
auto begin = platforms.cbegin(); auto begin = platforms.cbegin();
auto end = platforms.cend(); auto end = platforms.cend();
@ -183,7 +172,7 @@ bool Compiler::StageAction(const std::string& platforms, StageType type, const s
return false; return false;
#endif #endif
} else { } else {
Log.report(logvisor::Error, "Unknown platform '%s'", plat.c_str()); Log.report(logvisor::Error, fmt("Unknown platform '{}'"), plat);
return false; return false;
} }
begin = match.suffix().first; begin = match.suffix().first;
@ -219,13 +208,13 @@ static const std::regex regEvaluation(R"(#\s*evaluation\s+(.*))", RegexFlags);
bool Compiler::includeFile(SystemStringView file, std::string& out, int depth) { bool Compiler::includeFile(SystemStringView file, std::string& out, int depth) {
if (depth > 32) { if (depth > 32) {
Log.report(logvisor::Error, _SYS_STR("Too many levels of includes (>32) at '%s'"), file.data()); Log.report(logvisor::Error, fmt(_SYS_STR("Too many levels of includes (>32) at '{}'")), file);
return false; return false;
} }
const std::string* data = getFileContents(file); const std::string* data = getFileContents(file);
if (!data) { if (!data) {
Log.report(logvisor::Error, _SYS_STR("Unable to access '%s'"), file.data()); Log.report(logvisor::Error, fmt(_SYS_STR("Unable to access '{}'")), file);
return false; return false;
} }
const std::string& sdata = *data; const std::string& sdata = *data;
@ -251,7 +240,7 @@ bool Compiler::includeFile(SystemStringView file, std::string& out, int depth) {
if (std::regex_search(begin, nextBegin, subMatch, regInclude)) { if (std::regex_search(begin, nextBegin, subMatch, regInclude)) {
std::string path = subMatch[1].str(); std::string path = subMatch[1].str();
if (path.empty()) { if (path.empty()) {
Log.report(logvisor::Error, _SYS_STR("Empty path provided to include in '%s'"), file.data()); Log.report(logvisor::Error, fmt(_SYS_STR("Empty path provided to include in '{}'")), file);
return false; return false;
} }
@ -269,7 +258,7 @@ bool Compiler::includeFile(SystemStringView file, std::string& out, int depth) {
return true; return true;
} }
static std::string_view BlendFactorToStr(boo::BlendFactor fac) { constexpr std::string_view BlendFactorToStr(boo::BlendFactor fac) {
switch (fac) { switch (fac) {
case boo::BlendFactor::Zero: case boo::BlendFactor::Zero:
default: default:
@ -301,7 +290,7 @@ static std::string_view BlendFactorToStr(boo::BlendFactor fac) {
} }
} }
static bool StrToBlendFactor(std::string str, boo::BlendFactor& fac) { inline bool StrToBlendFactor(std::string str, boo::BlendFactor& fac) {
std::transform(str.begin(), str.end(), str.begin(), ::tolower); std::transform(str.begin(), str.end(), str.begin(), ::tolower);
if (str == "zero") if (str == "zero")
fac = boo::BlendFactor::Zero; fac = boo::BlendFactor::Zero;
@ -330,13 +319,13 @@ static bool StrToBlendFactor(std::string str, boo::BlendFactor& fac) {
else if (str == "subtract") else if (str == "subtract")
fac = boo::BlendFactor::Subtract; fac = boo::BlendFactor::Subtract;
else { else {
Log.report(logvisor::Error, "Unrecognized blend mode '%s'", str.c_str()); Log.report(logvisor::Error, fmt("Unrecognized blend mode '{}'"), str);
return false; return false;
} }
return true; return true;
} }
static std::string_view PrimitiveToStr(boo::Primitive prim) { constexpr std::string_view PrimitiveToStr(boo::Primitive prim) {
switch (prim) { switch (prim) {
case boo::Primitive::Triangles: case boo::Primitive::Triangles:
default: default:
@ -348,7 +337,7 @@ static std::string_view PrimitiveToStr(boo::Primitive prim) {
} }
} }
static bool StrToPrimitive(std::string str, boo::Primitive& prim) { inline bool StrToPrimitive(std::string str, boo::Primitive& prim) {
std::transform(str.begin(), str.end(), str.begin(), ::tolower); std::transform(str.begin(), str.end(), str.begin(), ::tolower);
if (str == "triangles") if (str == "triangles")
prim = boo::Primitive::Triangles; prim = boo::Primitive::Triangles;
@ -357,13 +346,13 @@ static bool StrToPrimitive(std::string str, boo::Primitive& prim) {
else if (str == "patches") else if (str == "patches")
prim = boo::Primitive::Patches; prim = boo::Primitive::Patches;
else { else {
Log.report(logvisor::Error, "Unrecognized primitive '%s'", str.c_str()); Log.report(logvisor::Error, fmt("Unrecognized primitive '{}'"), str);
return false; return false;
} }
return true; return true;
} }
static std::string_view ZTestToStr(boo::ZTest ztest) { constexpr std::string_view ZTestToStr(boo::ZTest ztest) {
switch (ztest) { switch (ztest) {
case boo::ZTest::None: case boo::ZTest::None:
default: default:
@ -379,7 +368,7 @@ static std::string_view ZTestToStr(boo::ZTest ztest) {
} }
} }
static bool StrToZTest(std::string str, boo::ZTest& ztest) { inline bool StrToZTest(std::string str, boo::ZTest& ztest) {
std::transform(str.begin(), str.end(), str.begin(), ::tolower); std::transform(str.begin(), str.end(), str.begin(), ::tolower);
if (str == "none") if (str == "none")
ztest = boo::ZTest::None; ztest = boo::ZTest::None;
@ -392,13 +381,13 @@ static bool StrToZTest(std::string str, boo::ZTest& ztest) {
else if (str == "equal") else if (str == "equal")
ztest = boo::ZTest::Equal; ztest = boo::ZTest::Equal;
else { else {
Log.report(logvisor::Error, "Unrecognized ztest '%s'", str.c_str()); Log.report(logvisor::Error, fmt("Unrecognized ztest '{}'"), str);
return false; return false;
} }
return true; return true;
} }
static std::string_view CullModeToStr(boo::CullMode cull) { constexpr std::string_view CullModeToStr(boo::CullMode cull) {
switch (cull) { switch (cull) {
case boo::CullMode::None: case boo::CullMode::None:
default: default:
@ -410,7 +399,7 @@ static std::string_view CullModeToStr(boo::CullMode cull) {
} }
} }
static bool StrToCullMode(std::string str, boo::CullMode& cull) { inline bool StrToCullMode(std::string str, boo::CullMode& cull) {
std::transform(str.begin(), str.end(), str.begin(), ::tolower); std::transform(str.begin(), str.end(), str.begin(), ::tolower);
if (str == "none") if (str == "none")
cull = boo::CullMode::None; cull = boo::CullMode::None;
@ -419,15 +408,15 @@ static bool StrToCullMode(std::string str, boo::CullMode& cull) {
else if (str == "frontface") else if (str == "frontface")
cull = boo::CullMode::Frontface; cull = boo::CullMode::Frontface;
else { else {
Log.report(logvisor::Error, "Unrecognized cull mode '%s'", str.c_str()); Log.report(logvisor::Error, fmt("Unrecognized cull mode '{}'"), str);
return false; return false;
} }
return true; return true;
} }
static std::string_view BoolToStr(bool b) { return b ? "true"sv : "false"sv; } constexpr std::string_view BoolToStr(bool b) { return b ? "true"sv : "false"sv; }
static bool StrToBool(std::string str, bool& b) { inline bool StrToBool(std::string str, bool& b) {
std::transform(str.begin(), str.end(), str.begin(), ::tolower); std::transform(str.begin(), str.end(), str.begin(), ::tolower);
if (strtol(str.c_str(), nullptr, 0)) if (strtol(str.c_str(), nullptr, 0))
b = true; b = true;
@ -436,13 +425,24 @@ static bool StrToBool(std::string str, bool& b) {
else if (str == "false") else if (str == "false")
b = false; b = false;
else { else {
Log.report(logvisor::Error, "Unrecognized bool '%s'", str.c_str()); Log.report(logvisor::Error, fmt("Unrecognized bool '{}'"), str);
return false; return false;
} }
return true; return true;
} }
bool Compiler::compileFile(SystemStringView file, std::string_view baseName, std::pair<std::string, std::string>& out) { template <typename Format>
constexpr void SemanticOut(std::stringstream& out,
const std::pair<boo::VertexSemantic, int>& attr, const Format& fmtstr) {
fmt::print(out, fmtstr,
True(attr.first & boo::VertexSemantic::Instanced)
? " | boo::VertexSemantic::Instanced"
: "",
attr.second);
}
bool Compiler::compileFile(SystemStringView file, std::string_view baseName,
std::pair<std::stringstream, std::stringstream>& out) {
std::string includesPass; std::string includesPass;
if (!includeFile(file, includesPass)) if (!includeFile(file, includesPass))
return false; return false;
@ -469,7 +469,7 @@ bool Compiler::compileFile(SystemStringView file, std::string_view baseName, std
return true; return true;
if (shaderName.empty()) { if (shaderName.empty()) {
Log.report(logvisor::Error, "`#shader <name>` must be issued before stages"); Log.report(logvisor::Error, fmt("`#shader <name>` must be issued before stages"));
return false; return false;
} }
std::string stage(stageBegin, stageEnd); std::string stage(stageBegin, stageEnd);
@ -503,9 +503,8 @@ bool Compiler::compileFile(SystemStringView file, std::string_view baseName, std
if (uses.stages.test(5)) if (uses.stages.test(5))
return true; return true;
out.first += Format(ShaderHeaderTemplate, shaderName.c_str(), XXH64(shaderName.c_str(), shaderName.size(), 0)); fmt::print(out.first, ShaderHeaderTemplate, shaderName, XXH64(shaderName.c_str(), shaderName.size(), 0));
out.first += Format(StageObjectHeaderTemplate, shaderName.c_str(), shaderName.c_str(), shaderName.c_str(), fmt::print(out.first, StageObjectHeaderTemplate, shaderName, shaderName, shaderName, shaderName);
shaderName.c_str());
if (!shaderBase.empty()) { if (!shaderBase.empty()) {
shaderBases[shaderName] = shaderBase; shaderBases[shaderName] = shaderBase;
@ -534,76 +533,70 @@ bool Compiler::compileFile(SystemStringView file, std::string_view baseName, std
shaderBase.clear(); shaderBase.clear();
} }
out.second += Format("static const boo::VertexElementDescriptor %s_vtxfmtelems[] = {\n", shaderName.c_str()); fmt::print(out.second, fmt("static const boo::VertexElementDescriptor {}_vtxfmtelems[] = {{\n"), shaderName);
for (const auto& attr : shaderAttributes) { for (const auto& attr : shaderAttributes) {
const char* fmt;
switch (attr.first & boo::VertexSemantic::SemanticMask) { switch (attr.first & boo::VertexSemantic::SemanticMask) {
case boo::VertexSemantic::Position3: case boo::VertexSemantic::Position3:
fmt = "{boo::VertexSemantic::Position3%s, %d},\n"; SemanticOut(out.second, attr, fmt("{{boo::VertexSemantic::Position3{}, {}}},\n"));
break; break;
case boo::VertexSemantic::Position4: case boo::VertexSemantic::Position4:
fmt = "{boo::VertexSemantic::Position4%s, %d},\n"; SemanticOut(out.second, attr, fmt("{{boo::VertexSemantic::Position4{}, {}}},\n"));
break; break;
case boo::VertexSemantic::Normal3: case boo::VertexSemantic::Normal3:
fmt = "{boo::VertexSemantic::Normal3%s, %d},\n"; SemanticOut(out.second, attr, fmt("{{boo::VertexSemantic::Normal3{}, {}}},\n"));
break; break;
case boo::VertexSemantic::Normal4: case boo::VertexSemantic::Normal4:
fmt = "{boo::VertexSemantic::Normal4%s, %d},\n"; SemanticOut(out.second, attr, fmt("{{boo::VertexSemantic::Normal4{}, {}}},\n"));
break; break;
case boo::VertexSemantic::Color: case boo::VertexSemantic::Color:
fmt = "{boo::VertexSemantic::Color%s, %d},\n"; SemanticOut(out.second, attr, fmt("{{boo::VertexSemantic::Color{}, {}}},\n"));
break; break;
case boo::VertexSemantic::ColorUNorm: case boo::VertexSemantic::ColorUNorm:
fmt = "{boo::VertexSemantic::ColorUNorm%s, %d},\n"; SemanticOut(out.second, attr, fmt("{{boo::VertexSemantic::ColorUNorm{}, {}}},\n"));
break; break;
case boo::VertexSemantic::UV2: case boo::VertexSemantic::UV2:
fmt = "{boo::VertexSemantic::UV2%s, %d},\n"; SemanticOut(out.second, attr, fmt("{{boo::VertexSemantic::UV2{}, {}}},\n"));
break; break;
case boo::VertexSemantic::UV4: case boo::VertexSemantic::UV4:
fmt = "{boo::VertexSemantic::UV4%s, %d},\n"; SemanticOut(out.second, attr, fmt("{{boo::VertexSemantic::UV4{}, {}}},\n"));
break; break;
case boo::VertexSemantic::Weight: case boo::VertexSemantic::Weight:
fmt = "{boo::VertexSemantic::Weight%s, %d},\n"; SemanticOut(out.second, attr, fmt("{{boo::VertexSemantic::Weight{}, {}}},\n"));
break; break;
case boo::VertexSemantic::ModelView: case boo::VertexSemantic::ModelView:
fmt = "{boo::VertexSemantic::ModelView%s, %d},\n"; SemanticOut(out.second, attr, fmt("{{boo::VertexSemantic::ModelView{}, {}}},\n"));
break; break;
default: default:
fmt = "{boo::VertexSemantic::None%s, %d},\n"; SemanticOut(out.second, attr, fmt("{{boo::VertexSemantic::None{}, {}}},\n"));
break; break;
} }
out.second += Format(fmt,
True(attr.first & boo::VertexSemantic::Instanced)
? " | boo::VertexSemantic::Instanced"
: "",
attr.second);
} }
out.second += "};\n"; out.second << "};\n";
out.second += Format("const boo::VertexFormatInfo Shader_%s::VtxFmt = { %s_vtxfmtelems };\n\n", shaderName.c_str(), fmt::print(out.second, fmt("const boo::VertexFormatInfo Shader_{}::VtxFmt = {{ {}_vtxfmtelems }};\n\n"),
shaderName.c_str()); shaderName, shaderName);
out.second += Format("const boo::AdditionalPipelineInfo Shader_%s::PipelineInfo = {\n", shaderName.c_str()); fmt::print(out.second, fmt("const boo::AdditionalPipelineInfo Shader_{}::PipelineInfo = {{\n"), shaderName);
out.second += BlendFactorToStr(shaderInfo.srcFac); out.second << BlendFactorToStr(shaderInfo.srcFac);
out.second += ", "; out.second << ", ";
out.second += BlendFactorToStr(shaderInfo.dstFac); out.second << BlendFactorToStr(shaderInfo.dstFac);
out.second += ", "; out.second << ", ";
out.second += PrimitiveToStr(shaderInfo.prim); out.second << PrimitiveToStr(shaderInfo.prim);
out.second += ", "; out.second << ", ";
out.second += ZTestToStr(shaderInfo.depthTest); out.second << ZTestToStr(shaderInfo.depthTest);
out.second += ",\n"; out.second << ",\n";
out.second += BoolToStr(shaderInfo.depthWrite); out.second << BoolToStr(shaderInfo.depthWrite);
out.second += ", "; out.second << ", ";
out.second += BoolToStr(shaderInfo.colorWrite); out.second << BoolToStr(shaderInfo.colorWrite);
out.second += ", "; out.second << ", ";
out.second += BoolToStr(shaderInfo.alphaWrite); out.second << BoolToStr(shaderInfo.alphaWrite);
out.second += ", "; out.second << ", ";
out.second += CullModeToStr(shaderInfo.culling); out.second << CullModeToStr(shaderInfo.culling);
out.second += ", "; out.second << ", ";
out.second += Format("%d, ", shaderInfo.patchSize); fmt::print(out.second, fmt("{}, "), shaderInfo.patchSize);
out.second += BoolToStr(shaderInfo.overwriteAlpha); out.second << BoolToStr(shaderInfo.overwriteAlpha);
out.second += ", "; out.second << ", ";
out.second += BoolToStr(shaderInfo.depthAttachment); out.second << BoolToStr(shaderInfo.depthAttachment);
out.second += ", "; out.second << ", ";
out.second += "};\n\n"; out.second << "};\n\n";
uses.stages.set(5); uses.stages.set(5);
@ -638,7 +631,7 @@ bool Compiler::compileFile(SystemStringView file, std::string_view baseName, std
else if (semantic == "modelview") else if (semantic == "modelview")
shaderAttributes.push_back(std::make_pair(boo::VertexSemantic::ModelView | orsem, idxNum)); shaderAttributes.push_back(std::make_pair(boo::VertexSemantic::ModelView | orsem, idxNum));
else { else {
Log.report(logvisor::Error, "Unrecognized vertex semantic '%s'", semantic.c_str()); Log.report(logvisor::Error, fmt("Unrecognized vertex semantic '{}'"), semantic);
return false; return false;
} }
return true; return true;
@ -736,7 +729,7 @@ bool Compiler::compileFile(SystemStringView file, std::string_view baseName, std
char* endptr; char* endptr;
shaderInfo.patchSize = uint32_t(strtoul(str.c_str(), &endptr, 0)); shaderInfo.patchSize = uint32_t(strtoul(str.c_str(), &endptr, 0));
if (endptr == str.c_str()) { if (endptr == str.c_str()) {
Log.report(logvisor::Error, "Non-unsigned-integer value for #patchsize directive"); Log.report(logvisor::Error, fmt("Non-unsigned-integer value for #patchsize directive"));
return false; return false;
} }
} else if (std::regex_search(begin, nextBegin, subMatch, regOverwriteAlpha)) { } else if (std::regex_search(begin, nextBegin, subMatch, regOverwriteAlpha)) {
@ -772,42 +765,42 @@ bool Compiler::compileFile(SystemStringView file, std::string_view baseName, std
for (const auto& shader : shaderStageUses) { for (const auto& shader : shaderStageUses) {
for (int i = 0; i < 5; ++i) { for (int i = 0; i < 5; ++i) {
if (shader.second.stageHashes[i]) { if (shader.second.stageHashes[i]) {
out.first += "template <> constexpr uint64_t Shader_"; out.first << "template <> constexpr uint64_t Shader_";
out.first += shader.first; out.first << shader.first;
out.first += Format("::StageHash<%s>() { return 0x%016llX; }\n", StageNames[i], shader.second.stageHashes[i]); fmt::print(out.first, fmt("::StageHash<{}>() {{ return 0x{:016X}; }}\n"),
StageNames[i], shader.second.stageHashes[i]);
} }
} }
} }
out.first += "\n"; out.first << "\n";
out.first += "#define UNIVERSAL_PIPELINES_"; out.first << "#define UNIVERSAL_PIPELINES_";
out.first += baseName; out.first << baseName;
for (const auto& shader : shaderStageUses) { for (const auto& shader : shaderStageUses) {
out.first += " \\\n"; out.first << " \\\n";
out.first += "::Shader_"; out.first << "::Shader_";
out.first += shader.first; out.first << shader.first;
} }
out.first += "\n"; out.first << "\n";
out.first += "#define STAGES_"; out.first << "#define STAGES_";
out.first += baseName; out.first << baseName;
out.first += "(P, S)"; out.first << "(P, S)";
for (const auto& shader : shaderStageUses) { for (const auto& shader : shaderStageUses) {
out.first += " \\\n"; out.first << " \\\n";
out.first += "::StageObject_"; out.first << "::StageObject_";
out.first += shader.first; out.first << shader.first;
out.first += "<P, S>,"; out.first << "<P, S>,";
} }
out.first += "\n"; out.first << "\n";
return true; return true;
} }
bool Compiler::compile(std::string_view baseName, std::pair<std::string, std::string>& out) { bool Compiler::compile(std::string_view baseName, std::pair<std::stringstream, std::stringstream>& out) {
out = { out.first << "#pragma once\n"
"#pragma once\n" "#include \"hecl/PipelineBase.hpp\"\n\n";
"#include \"hecl/PipelineBase.hpp\"\n\n", fmt::print(out.second, fmt("#include \"{}.hpp\"\n\n"), baseName);
Format("#include \"%s.hpp\"\n\n", baseName.data())};
for (const auto& file : m_inputFiles) for (const auto& file : m_inputFiles)
if (!compileFile(file, baseName, out)) if (!compileFile(file, baseName, out))

View File

@ -15,17 +15,18 @@ class Compiler {
std::unordered_map<std::string, std::string> m_defines; std::unordered_map<std::string, std::string> m_defines;
template <typename Action, typename P> template <typename Action, typename P>
static bool StageAction(StageType type, const std::string& name, const std::string& basename, static bool StageAction(StageType type, const std::string& name, const std::string& basename,
const std::string& stage, std::string& implOut); const std::string& stage, std::stringstream& implOut);
template <typename Action> template <typename Action>
static bool StageAction(const std::string& platforms, StageType type, const std::string& name, static bool StageAction(const std::string& platforms, StageType type, const std::string& name,
const std::string& basename, const std::string& stage, std::string& implOut); const std::string& basename, const std::string& stage, std::stringstream& implOut);
bool includeFile(SystemStringView file, std::string& out, int depth = 0); bool includeFile(SystemStringView file, std::string& out, int depth = 0);
bool compileFile(SystemStringView file, std::string_view baseName, std::pair<std::string, std::string>& out); bool compileFile(SystemStringView file, std::string_view baseName,
std::pair<std::stringstream, std::stringstream>& out);
public: public:
void addInputFile(SystemStringView file); void addInputFile(SystemStringView file);
void addDefine(std::string_view var, std::string_view val); void addDefine(std::string_view var, std::string_view val);
bool compile(std::string_view baseName, std::pair<std::string, std::string>& out); bool compile(std::string_view baseName, std::pair<std::stringstream, std::stringstream>& out);
}; };
} // namespace hecl::shaderc } // namespace hecl::shaderc