diff --git a/hecl/driver/ToolBase.hpp b/hecl/driver/ToolBase.hpp index b2b0e323a..48f233703 100644 --- a/hecl/driver/ToolBase.hpp +++ b/hecl/driver/ToolBase.hpp @@ -18,18 +18,17 @@ extern logvisor::Module LogModule; -struct ToolPassInfo -{ - hecl::SystemString pname; - hecl::SystemString cwd; - std::vector args; - std::vector flags; - hecl::SystemString output; - hecl::Database::Project* project = nullptr; - unsigned verbosityLevel = 0; - bool force = false; - bool yes = false; - bool gui = false; +struct ToolPassInfo { + hecl::SystemString pname; + hecl::SystemString cwd; + std::vector args; + std::vector flags; + hecl::SystemString output; + hecl::Database::Project* project = nullptr; + unsigned verbosityLevel = 0; + bool force = false; + bool yes = false; + bool gui = false; }; #define RED "\033[0;31m" @@ -48,228 +47,189 @@ struct ToolPassInfo extern bool XTERM_COLOR; -class ToolBase -{ +class ToolBase { protected: - const ToolPassInfo& m_info; - bool m_good = false; + const ToolPassInfo& m_info; + bool m_good = false; - bool continuePrompt() - { - if (!m_info.yes) - { - if (XTERM_COLOR) - hecl::Printf(_SYS_STR("\n" BLUE BOLD "Continue?" NORMAL " (Y/n) ")); - else - hecl::Printf(_SYS_STR("\nContinue? (Y/n) ")); - fflush(stdout); + bool continuePrompt() { + if (!m_info.yes) { + if (XTERM_COLOR) + hecl::Printf(_SYS_STR("\n" BLUE BOLD "Continue?" NORMAL " (Y/n) ")); + else + hecl::Printf(_SYS_STR("\nContinue? (Y/n) ")); + fflush(stdout); - int ch; + int ch; #ifndef _WIN32 - struct termios tioOld, tioNew; - tcgetattr(0, &tioOld); - tioNew = tioOld; - tioNew.c_lflag &= ~ICANON; - tcsetattr(0, TCSANOW, &tioNew); - while ((ch = getchar())) + struct termios tioOld, tioNew; + tcgetattr(0, &tioOld); + tioNew = tioOld; + tioNew.c_lflag &= ~ICANON; + tcsetattr(0, TCSANOW, &tioNew); + while ((ch = getchar())) #else - while ((ch = getch())) -#endif - { - if (ch == 'n' || ch == 'N') - { - hecl::Printf(_SYS_STR("\n")); - return false; - } - if (ch == 'y' || ch == 'Y' || ch == '\r' || ch == '\n') - break; - } -#ifndef _WIN32 - tcsetattr(0, TCSANOW, &tioOld); + while ((ch = getch())) #endif + { + if (ch == 'n' || ch == 'N') { + hecl::Printf(_SYS_STR("\n")); + return false; } - hecl::Printf(_SYS_STR("\n")); - return true; + if (ch == 'y' || ch == 'Y' || ch == '\r' || ch == '\n') + break; + } +#ifndef _WIN32 + tcsetattr(0, TCSANOW, &tioOld); +#endif } + hecl::Printf(_SYS_STR("\n")); + return true; + } public: - ToolBase(const ToolPassInfo& info) - : m_info(info) - { - hecl::VerbosityLevel = info.verbosityLevel; - hecl::GuiMode = info.gui; - } - virtual ~ToolBase() = default; - virtual hecl::SystemString toolName() const=0; - virtual int run()=0; - virtual void cancel() {} - inline operator bool() const {return m_good;} + ToolBase(const ToolPassInfo& info) : m_info(info) { + hecl::VerbosityLevel = info.verbosityLevel; + hecl::GuiMode = info.gui; + } + virtual ~ToolBase() = default; + virtual hecl::SystemString toolName() const = 0; + virtual int run() = 0; + virtual void cancel() {} + inline operator bool() const { return m_good; } }; -class HelpOutput -{ +class HelpOutput { public: - typedef void(*HelpFunc)(HelpOutput&); + typedef void (*HelpFunc)(HelpOutput&); + private: - FILE* m_sout; - HelpFunc m_helpFunc; - int m_lineWidth; - hecl::SystemString m_wrapBuffer; + FILE* m_sout; + HelpFunc m_helpFunc; + int m_lineWidth; + hecl::SystemString m_wrapBuffer; - void _wrapBuf(hecl::SystemString& string) - { - int counter; - hecl::SystemString::iterator it = string.begin(); + void _wrapBuf(hecl::SystemString& string) { + int counter; + hecl::SystemString::iterator it = string.begin(); - while (it != string.end()) - { - std::ptrdiff_t v = it - string.begin(); + while (it != string.end()) { + std::ptrdiff_t v = it - string.begin(); - /* copy string until the end of the line is reached */ - for (counter=WRAP_INDENT ; counter < m_lineWidth ; ++counter) - { - if (it >= string.end()) - return; - if (*it == _SYS_STR('\n')) - { - counter = WRAP_INDENT; - ++it; - } - if (counter == WRAP_INDENT) - { - for (int i=0 ; i= string.end()) - return; - if (*it != _SYS_STR('\n')) - ++it; - } - /* check for whitespace */ - if (isspace(*it)) - { - *it = _SYS_STR('\n'); - counter = WRAP_INDENT; - ++it; - } - else - { - /* check for nearest whitespace back in string */ - for (hecl::SystemString::iterator k=it ; k!=string.begin() ; --k) - { - if (isspace(*k)) - { - counter = WRAP_INDENT; - if (k - string.begin() < v) - k = string.insert(it, _SYS_STR('\n')); - else - *k = _SYS_STR('\n'); - it = k + 1; - break; - } - } - } + /* copy string until the end of the line is reached */ + for (counter = WRAP_INDENT; counter < m_lineWidth; ++counter) { + if (it >= string.end()) + return; + if (*it == _SYS_STR('\n')) { + counter = WRAP_INDENT; + ++it; } + if (counter == WRAP_INDENT) { + for (int i = 0; i < WRAP_INDENT; ++i) + it = string.insert(it, _SYS_STR(' ')) + 1; + } + if (it >= string.end()) + return; + if (*it != _SYS_STR('\n')) + ++it; + } + /* check for whitespace */ + if (isspace(*it)) { + *it = _SYS_STR('\n'); + counter = WRAP_INDENT; + ++it; + } else { + /* check for nearest whitespace back in string */ + for (hecl::SystemString::iterator k = it; k != string.begin(); --k) { + if (isspace(*k)) { + counter = WRAP_INDENT; + if (k - string.begin() < v) + k = string.insert(it, _SYS_STR('\n')); + else + *k = _SYS_STR('\n'); + it = k + 1; + break; + } + } + } } + } public: + HelpOutput(HelpFunc helpFunc) + : m_sout(NULL), m_helpFunc(helpFunc), m_lineWidth(hecl::GuiMode ? 120 : hecl::ConsoleWidth()) {} - HelpOutput(HelpFunc helpFunc) - : m_sout(NULL), m_helpFunc(helpFunc), m_lineWidth(hecl::GuiMode ? 120 : hecl::ConsoleWidth()) - {} - - void go() - { + void go() { #if _WIN32 - m_sout = stdout; - m_helpFunc(*this); + m_sout = stdout; + m_helpFunc(*this); #else - m_sout = popen("less -R", "w"); - if (m_sout) - { - m_helpFunc(*this); - pclose(m_sout); - } - else - { - m_sout = stdout; - m_helpFunc(*this); - } + m_sout = popen("less -R", "w"); + if (m_sout) { + m_helpFunc(*this); + pclose(m_sout); + } else { + m_sout = stdout; + m_helpFunc(*this); + } #endif - } + } - void print(const hecl::SystemChar* str) - { - hecl::FPrintf(m_sout, _SYS_STR("%s"), str); - } + void print(const hecl::SystemChar* str) { hecl::FPrintf(m_sout, _SYS_STR("%s"), str); } - void printBold(const hecl::SystemChar* str) - { - if (XTERM_COLOR) - hecl::FPrintf(m_sout, _SYS_STR("" BOLD "%s" NORMAL ""), str); - else - hecl::FPrintf(m_sout, _SYS_STR("%s"), str); - } + void printBold(const hecl::SystemChar* str) { + if (XTERM_COLOR) + hecl::FPrintf(m_sout, _SYS_STR("" BOLD "%s" NORMAL ""), str); + else + hecl::FPrintf(m_sout, _SYS_STR("%s"), str); + } - void secHead(const hecl::SystemChar* headName) - { - if (XTERM_COLOR) - hecl::FPrintf(m_sout, _SYS_STR("" BOLD "%s" NORMAL "\n"), headName); - else - hecl::FPrintf(m_sout, _SYS_STR("%s\n"), headName); - } + void secHead(const hecl::SystemChar* headName) { + if (XTERM_COLOR) + hecl::FPrintf(m_sout, _SYS_STR("" BOLD "%s" NORMAL "\n"), headName); + else + hecl::FPrintf(m_sout, _SYS_STR("%s\n"), headName); + } - void optionHead(const hecl::SystemChar* flag, const hecl::SystemChar* synopsis) - { - if (XTERM_COLOR) - hecl::FPrintf(m_sout, _SYS_STR("" BOLD "%s" NORMAL " (%s)\n"), flag, synopsis); - else - hecl::FPrintf(m_sout, _SYS_STR("%s (%s)\n"), flag, synopsis); - } + void optionHead(const hecl::SystemChar* flag, const hecl::SystemChar* synopsis) { + if (XTERM_COLOR) + hecl::FPrintf(m_sout, _SYS_STR("" BOLD "%s" NORMAL " (%s)\n"), flag, synopsis); + else + hecl::FPrintf(m_sout, _SYS_STR("%s (%s)\n"), flag, synopsis); + } - void beginWrap() - { - m_wrapBuffer.clear(); - } + void beginWrap() { m_wrapBuffer.clear(); } - void wrap(const hecl::SystemChar* str) - { - m_wrapBuffer += str; - } + void wrap(const hecl::SystemChar* str) { m_wrapBuffer += str; } - void wrapBold(const hecl::SystemChar* str) - { - if (XTERM_COLOR) - m_wrapBuffer += _SYS_STR("" BOLD ""); - m_wrapBuffer += str; - if (XTERM_COLOR) - m_wrapBuffer += _SYS_STR("" NORMAL ""); - } + void wrapBold(const hecl::SystemChar* str) { + if (XTERM_COLOR) + m_wrapBuffer += _SYS_STR("" BOLD ""); + m_wrapBuffer += str; + if (XTERM_COLOR) + m_wrapBuffer += _SYS_STR("" NORMAL ""); + } - void endWrap() - { - _wrapBuf(m_wrapBuffer); - m_wrapBuffer += _SYS_STR('\n'); - hecl::FPrintf(m_sout, _SYS_STR("%s"), m_wrapBuffer.c_str()); - m_wrapBuffer.clear(); - } + void endWrap() { + _wrapBuf(m_wrapBuffer); + m_wrapBuffer += _SYS_STR('\n'); + hecl::FPrintf(m_sout, _SYS_STR("%s"), m_wrapBuffer.c_str()); + m_wrapBuffer.clear(); + } }; -static hecl::SystemString MakePathArgAbsolute(const hecl::SystemString& arg, - const hecl::SystemString& cwd) -{ +static hecl::SystemString MakePathArgAbsolute(const hecl::SystemString& arg, const hecl::SystemString& cwd) { #if _WIN32 - if (arg.size() >= 2 && iswalpha(arg[0]) && arg[1] == _SYS_STR(':')) - return arg; - if (arg[0] == _SYS_STR('\\') || arg[0] == _SYS_STR('/')) - return arg; - return cwd + _SYS_STR('\\') + arg; + if (arg.size() >= 2 && iswalpha(arg[0]) && arg[1] == _SYS_STR(':')) + return arg; + if (arg[0] == _SYS_STR('\\') || arg[0] == _SYS_STR('/')) + return arg; + return cwd + _SYS_STR('\\') + arg; #else - if (arg[0] == _SYS_STR('/') || arg[0] == _SYS_STR('\\')) - return arg; - if (cwd.back() == _SYS_STR('/') || cwd.back() == _SYS_STR('\\')) - return cwd + arg; - return cwd + _SYS_STR('/') + arg; + if (arg[0] == _SYS_STR('/') || arg[0] == _SYS_STR('\\')) + return arg; + if (cwd.back() == _SYS_STR('/') || cwd.back() == _SYS_STR('\\')) + return cwd + arg; + return cwd + _SYS_STR('/') + arg; #endif } - diff --git a/hecl/driver/ToolCook.hpp b/hecl/driver/ToolCook.hpp index 14cb55c7e..d9b2fd7b9 100644 --- a/hecl/driver/ToolCook.hpp +++ b/hecl/driver/ToolCook.hpp @@ -4,178 +4,157 @@ #include #include "hecl/ClientProcess.hpp" -class ToolCook final : public ToolBase -{ - std::vector m_selectedItems; - std::unique_ptr m_fallbackProj; - hecl::Database::Project* m_useProj; - const hecl::Database::DataSpecEntry* m_spec = nullptr; - bool m_recursive = false; - bool m_fast = false; +class ToolCook final : public ToolBase { + std::vector m_selectedItems; + std::unique_ptr m_fallbackProj; + hecl::Database::Project* m_useProj; + const hecl::Database::DataSpecEntry* m_spec = nullptr; + bool m_recursive = false; + bool m_fast = false; + public: - ToolCook(const ToolPassInfo& info) - : ToolBase(info), m_useProj(info.project) - { - /* Check for recursive flag */ - for (hecl::SystemChar arg : info.flags) - if (arg == _SYS_STR('r')) - m_recursive = true; + ToolCook(const ToolPassInfo& info) : ToolBase(info), m_useProj(info.project) { + /* Check for recursive flag */ + for (hecl::SystemChar arg : info.flags) + if (arg == _SYS_STR('r')) + m_recursive = true; - /* Scan args */ - if (info.args.size()) - { - /* See if project path is supplied via args and use that over the getcwd one */ - m_selectedItems.reserve(info.args.size()); - for (const hecl::SystemString& arg : info.args) - { - if (arg.empty()) - continue; - else if (!arg.compare(_SYS_STR("--fast"))) - { - m_fast = true; - continue; - } - else if (arg.size() >= 8 && !arg.compare(0, 7, _SYS_STR("--spec="))) - { - hecl::SystemString specName(arg.begin() + 7, arg.end()); - for (const hecl::Database::DataSpecEntry* spec : hecl::Database::DATA_SPEC_REGISTRY) - { - if (!hecl::StrCaseCmp(spec->m_name.data(), specName.c_str())) - { - m_spec = spec; - break; - } - } - if (!m_spec) - LogModule.report(logvisor::Fatal, "unable to find data spec '%s'", specName.c_str()); - continue; - } - else if (arg.size() >= 2 && arg[0] == _SYS_STR('-') && arg[1] == _SYS_STR('-')) - continue; - - hecl::SystemString subPath; - hecl::ProjectRootPath root = hecl::SearchForProject(MakePathArgAbsolute(arg, info.cwd), subPath); - if (root) - { - if (!m_fallbackProj) - { - m_fallbackProj.reset(new hecl::Database::Project(root)); - m_useProj = m_fallbackProj.get(); - } - else if (m_fallbackProj->getProjectRootPath() != root) - LogModule.report(logvisor::Fatal, - _SYS_STR("hecl cook can only process multiple items in the same project; ") - _SYS_STR("'%s' and '%s' are different projects"), - m_fallbackProj->getProjectRootPath().getAbsolutePath().data(), - root.getAbsolutePath().data()); - m_selectedItems.emplace_back(*m_useProj, subPath); - } + /* Scan args */ + if (info.args.size()) { + /* See if project path is supplied via args and use that over the getcwd one */ + m_selectedItems.reserve(info.args.size()); + for (const hecl::SystemString& arg : info.args) { + if (arg.empty()) + continue; + else if (!arg.compare(_SYS_STR("--fast"))) { + m_fast = true; + continue; + } else if (arg.size() >= 8 && !arg.compare(0, 7, _SYS_STR("--spec="))) { + hecl::SystemString specName(arg.begin() + 7, arg.end()); + for (const hecl::Database::DataSpecEntry* spec : hecl::Database::DATA_SPEC_REGISTRY) { + if (!hecl::StrCaseCmp(spec->m_name.data(), specName.c_str())) { + m_spec = spec; + break; } - } - if (!m_useProj) + } + if (!m_spec) + LogModule.report(logvisor::Fatal, "unable to find data spec '%s'", specName.c_str()); + continue; + } else if (arg.size() >= 2 && arg[0] == _SYS_STR('-') && arg[1] == _SYS_STR('-')) + continue; + + hecl::SystemString subPath; + hecl::ProjectRootPath root = hecl::SearchForProject(MakePathArgAbsolute(arg, info.cwd), subPath); + if (root) { + if (!m_fallbackProj) { + m_fallbackProj.reset(new hecl::Database::Project(root)); + m_useProj = m_fallbackProj.get(); + } else if (m_fallbackProj->getProjectRootPath() != root) LogModule.report(logvisor::Fatal, - "hecl cook must be ran within a project directory or " - "provided a path within a project"); - - /* Default case: recursive at root */ - if (m_selectedItems.empty()) - { - m_selectedItems.reserve(1); - m_selectedItems.push_back({hecl::ProjectPath(*m_useProj, _SYS_STR(""))}); - m_recursive = true; + _SYS_STR("hecl cook can only process multiple items in the same project; ") + _SYS_STR("'%s' and '%s' are different projects"), + m_fallbackProj->getProjectRootPath().getAbsolutePath().data(), + root.getAbsolutePath().data()); + m_selectedItems.emplace_back(*m_useProj, subPath); } + } } + if (!m_useProj) + LogModule.report(logvisor::Fatal, + "hecl cook must be ran within a project directory or " + "provided a path within a project"); - static void Help(HelpOutput& help) - { - help.secHead(_SYS_STR("NAME")); - help.beginWrap(); - help.wrap(_SYS_STR("hecl-cook - Cook objects within the project database\n")); - help.endWrap(); + /* Default case: recursive at root */ + if (m_selectedItems.empty()) { + m_selectedItems.reserve(1); + m_selectedItems.push_back({hecl::ProjectPath(*m_useProj, _SYS_STR(""))}); + m_recursive = true; + } + } - help.secHead(_SYS_STR("SYNOPSIS")); - help.beginWrap(); - help.wrap(_SYS_STR("hecl cook [-rf] [--fast] [--spec=] [...]\n")); - help.endWrap(); + static void Help(HelpOutput& help) { + help.secHead(_SYS_STR("NAME")); + help.beginWrap(); + help.wrap(_SYS_STR("hecl-cook - Cook objects within the project database\n")); + help.endWrap(); - help.secHead(_SYS_STR("DESCRIPTION")); - help.beginWrap(); - help.wrap(_SYS_STR("This command initiates a cooking pass on the project database. Cooking ") + help.secHead(_SYS_STR("SYNOPSIS")); + help.beginWrap(); + help.wrap(_SYS_STR("hecl cook [-rf] [--fast] [--spec=] [...]\n")); + help.endWrap(); + + help.secHead(_SYS_STR("DESCRIPTION")); + help.beginWrap(); + help.wrap(_SYS_STR("This command initiates a cooking pass on the project database. Cooking ") _SYS_STR("is analogous to compiling in software development. The resulting object buffers ") - _SYS_STR("are cached within the project database. HECL performs the following ") - _SYS_STR("tasks for each object during the cook process:\n\n")); - help.wrapBold(_SYS_STR("- Object Gather: ")); - help.wrap(_SYS_STR("Files added with ")); - help.wrapBold(_SYS_STR("hecl add")); - help.wrap(_SYS_STR(" are queried for their dependent files (e.g. ")); - help.wrapBold(_SYS_STR(".blend")); - help.wrap(_SYS_STR(" files return any linked ")); - help.wrapBold(_SYS_STR(".png")); - help.wrap(_SYS_STR(" images). If the dependent files are unable to be found, the cook process aborts.\n\n")); - help.wrapBold(_SYS_STR("- Modtime Comparison: ")); - help.wrap(_SYS_STR("Files that have previously finished a cook pass are inspected for their time of ") - _SYS_STR("last modification. If the file hasn't changed since its previous cook-pass, the ") - _SYS_STR("process is skipped. If the file has been moved or deleted, the object is automatically ") - _SYS_STR("removed from the project database.\n\n")); - help.wrapBold(_SYS_STR("- Cook: ")); - help.wrap(_SYS_STR("A type-specific procedure compiles the file's contents into an efficient format ") + _SYS_STR("are cached within the project database. HECL performs the following ") + _SYS_STR("tasks for each object during the cook process:\n\n")); + help.wrapBold(_SYS_STR("- Object Gather: ")); + help.wrap(_SYS_STR("Files added with ")); + help.wrapBold(_SYS_STR("hecl add")); + help.wrap(_SYS_STR(" are queried for their dependent files (e.g. ")); + help.wrapBold(_SYS_STR(".blend")); + help.wrap(_SYS_STR(" files return any linked ")); + help.wrapBold(_SYS_STR(".png")); + help.wrap(_SYS_STR(" images). If the dependent files are unable to be found, the cook process aborts.\n\n")); + help.wrapBold(_SYS_STR("- Modtime Comparison: ")); + help.wrap(_SYS_STR("Files that have previously finished a cook pass are inspected for their time of ") + _SYS_STR("last modification. If the file hasn't changed since its previous cook-pass, the ") _SYS_STR( + "process is skipped. If the file has been moved or deleted, the object is automatically ") + _SYS_STR("removed from the project database.\n\n")); + help.wrapBold(_SYS_STR("- Cook: ")); + help.wrap(_SYS_STR("A type-specific procedure compiles the file's contents into an efficient format ") _SYS_STR("for use by the runtime. A data-buffer is provided to HECL.\n\n")); - help.wrapBold(_SYS_STR("- Hash and Compress: ")); - help.wrap(_SYS_STR("The data-buffer is hashed and compressed before being cached in the object database.\n\n")); - help.endWrap(); + help.wrapBold(_SYS_STR("- Hash and Compress: ")); + help.wrap(_SYS_STR("The data-buffer is hashed and compressed before being cached in the object database.\n\n")); + help.endWrap(); - help.secHead(_SYS_STR("OPTIONS")); - help.optionHead(_SYS_STR("..."), _SYS_STR("input file(s)")); - help.beginWrap(); - help.wrap(_SYS_STR("Specifies working file(s) containing production data to be cooked by HECL. ") + help.secHead(_SYS_STR("OPTIONS")); + help.optionHead(_SYS_STR("..."), _SYS_STR("input file(s)")); + help.beginWrap(); + help.wrap(_SYS_STR("Specifies working file(s) containing production data to be cooked by HECL. ") _SYS_STR("Glob-strings may be specified (e.g. ")); - help.wrapBold(_SYS_STR("*.blend")); - help.wrap(_SYS_STR(") to automatically cook all matching current-directory files in the project database. ") + help.wrapBold(_SYS_STR("*.blend")); + help.wrap(_SYS_STR(") to automatically cook all matching current-directory files in the project database. ") _SYS_STR("If no path specified, all files in the project database are cooked.\n")); - help.endWrap(); + help.endWrap(); - help.optionHead(_SYS_STR("-r"), _SYS_STR("recursion")); - help.beginWrap(); - help.wrap(_SYS_STR("Enables recursive file-matching for cooking entire directories of working files.\n")); - help.endWrap(); - help.optionHead(_SYS_STR("-f"), _SYS_STR("force")); - help.beginWrap(); - help.wrap(_SYS_STR("Forces cooking of all matched files, ignoring timestamp differences.\n")); - help.endWrap(); - help.optionHead(_SYS_STR("--fast"), _SYS_STR("fast cook")); - help.beginWrap(); - help.wrap(_SYS_STR("Performs draft-optimization cooking for supported data types.\n")); - help.endWrap(); + help.optionHead(_SYS_STR("-r"), _SYS_STR("recursion")); + help.beginWrap(); + help.wrap(_SYS_STR("Enables recursive file-matching for cooking entire directories of working files.\n")); + help.endWrap(); + help.optionHead(_SYS_STR("-f"), _SYS_STR("force")); + help.beginWrap(); + help.wrap(_SYS_STR("Forces cooking of all matched files, ignoring timestamp differences.\n")); + help.endWrap(); + help.optionHead(_SYS_STR("--fast"), _SYS_STR("fast cook")); + help.beginWrap(); + help.wrap(_SYS_STR("Performs draft-optimization cooking for supported data types.\n")); + help.endWrap(); - help.optionHead(_SYS_STR("--spec="), _SYS_STR("data specification")); - help.beginWrap(); - help.wrap(_SYS_STR("Specifies a DataSpec to use when cooking. ") + help.optionHead(_SYS_STR("--spec="), _SYS_STR("data specification")); + help.beginWrap(); + help.wrap(_SYS_STR("Specifies a DataSpec to use when cooking. ") _SYS_STR("This build of hecl supports the following values of :\n")); - for (const hecl::Database::DataSpecEntry* spec : hecl::Database::DATA_SPEC_REGISTRY) - { - if (!spec->m_factory) - continue; - help.wrap(_SYS_STR(" ")); - help.wrapBold(spec->m_name.data()); - help.wrap(_SYS_STR("\n")); - } + for (const hecl::Database::DataSpecEntry* spec : hecl::Database::DATA_SPEC_REGISTRY) { + if (!spec->m_factory) + continue; + help.wrap(_SYS_STR(" ")); + help.wrapBold(spec->m_name.data()); + help.wrap(_SYS_STR("\n")); } + } - hecl::SystemString toolName() const {return _SYS_STR("cook");} + hecl::SystemString toolName() const { return _SYS_STR("cook"); } - int run() - { - hecl::MultiProgressPrinter printer(true); - hecl::ClientProcess cp(&printer); - for (const hecl::ProjectPath& path : m_selectedItems) - m_useProj->cookPath(path, printer, m_recursive, m_info.force, m_fast, m_spec, &cp); - cp.waitUntilComplete(); - return 0; - } + int run() { + hecl::MultiProgressPrinter printer(true); + hecl::ClientProcess cp(&printer); + for (const hecl::ProjectPath& path : m_selectedItems) + m_useProj->cookPath(path, printer, m_recursive, m_info.force, m_fast, m_spec, &cp); + cp.waitUntilComplete(); + return 0; + } - void cancel() - { - m_useProj->interruptCook(); - } + void cancel() { m_useProj->interruptCook(); } }; - diff --git a/hecl/driver/ToolExtract.hpp b/hecl/driver/ToolExtract.hpp index 8e022dfe6..fdac6d278 100644 --- a/hecl/driver/ToolExtract.hpp +++ b/hecl/driver/ToolExtract.hpp @@ -11,175 +11,156 @@ #include "hecl/MultiProgressPrinter.hpp" -class ToolExtract final : public ToolBase -{ - hecl::Database::IDataSpec::ExtractPassInfo m_einfo; - struct SpecExtractPass - { - const hecl::Database::DataSpecEntry* m_entry; - std::unique_ptr m_instance; - SpecExtractPass(const hecl::Database::DataSpecEntry* entry, - std::unique_ptr&& instance) - : m_entry(entry), m_instance(std::move(instance)) {} - SpecExtractPass(const SpecExtractPass& other) = delete; - SpecExtractPass(SpecExtractPass&& other) = default; - }; - std::vector m_specPasses; - std::vector m_reps; - std::unique_ptr m_fallbackProj; - hecl::Database::Project* m_useProj = nullptr; +class ToolExtract final : public ToolBase { + hecl::Database::IDataSpec::ExtractPassInfo m_einfo; + struct SpecExtractPass { + const hecl::Database::DataSpecEntry* m_entry; + std::unique_ptr m_instance; + SpecExtractPass(const hecl::Database::DataSpecEntry* entry, std::unique_ptr&& instance) + : m_entry(entry), m_instance(std::move(instance)) {} + SpecExtractPass(const SpecExtractPass& other) = delete; + SpecExtractPass(SpecExtractPass&& other) = default; + }; + std::vector m_specPasses; + std::vector m_reps; + std::unique_ptr m_fallbackProj; + hecl::Database::Project* m_useProj = nullptr; + public: - ToolExtract(const ToolPassInfo& info) - : ToolBase(info) - { - if (!m_info.args.size()) - LogModule.report(logvisor::Fatal, "hecl extract needs a source path as its first argument"); + ToolExtract(const ToolPassInfo& info) : ToolBase(info) { + if (!m_info.args.size()) + LogModule.report(logvisor::Fatal, "hecl extract needs a source path as its first argument"); - if (!info.project) - { - hecl::SystemString rootDir; + if (!info.project) { + hecl::SystemString rootDir; - if (info.output.empty()) - { - /* Get name from input file and init project there */ - hecl::SystemString baseFile = info.args.front(); - size_t slashPos = baseFile.rfind(_SYS_STR('/')); - if (slashPos == hecl::SystemString::npos) - slashPos = baseFile.rfind(_SYS_STR('\\')); - if (slashPos != hecl::SystemString::npos) - baseFile.assign(baseFile.begin() + slashPos + 1, baseFile.end()); - size_t dotPos = baseFile.rfind(_SYS_STR('.')); - if (dotPos != hecl::SystemString::npos) - baseFile.assign(baseFile.begin(), baseFile.begin() + dotPos); + if (info.output.empty()) { + /* Get name from input file and init project there */ + hecl::SystemString baseFile = info.args.front(); + size_t slashPos = baseFile.rfind(_SYS_STR('/')); + if (slashPos == hecl::SystemString::npos) + slashPos = baseFile.rfind(_SYS_STR('\\')); + if (slashPos != hecl::SystemString::npos) + baseFile.assign(baseFile.begin() + slashPos + 1, baseFile.end()); + size_t dotPos = baseFile.rfind(_SYS_STR('.')); + if (dotPos != hecl::SystemString::npos) + baseFile.assign(baseFile.begin(), baseFile.begin() + dotPos); - if (baseFile.empty()) - LogModule.report(logvisor::Fatal, "hecl extract must be ran within a project directory"); + if (baseFile.empty()) + LogModule.report(logvisor::Fatal, "hecl extract must be ran within a project directory"); - rootDir = info.cwd + baseFile; - } - else - { - if (hecl::PathRelative(info.output.c_str())) - rootDir = info.cwd + info.output; - else - rootDir = info.output; - } - - size_t ErrorRef = logvisor::ErrorCount; - hecl::ProjectRootPath newProjRoot(rootDir); - newProjRoot.makeDir(); - m_fallbackProj.reset(new hecl::Database::Project(newProjRoot)); - if (logvisor::ErrorCount > ErrorRef) - LogModule.report(logvisor::Fatal, "unable to init project at '%s'", rootDir.c_str()); - LogModule.report(logvisor::Info, _SYS_STR("initialized project at '%s/.hecl'"), rootDir.c_str()); - m_useProj = m_fallbackProj.get(); - } + rootDir = info.cwd + baseFile; + } else { + if (hecl::PathRelative(info.output.c_str())) + rootDir = info.cwd + info.output; else - m_useProj = info.project; + rootDir = info.output; + } - m_einfo.srcpath = m_info.args.front(); - m_einfo.force = info.force; - m_einfo.extractArgs.reserve(info.args.size()); - auto it=info.args.cbegin(); - ++it; - for (; it != info.args.cend(); ++it) - m_einfo.extractArgs.push_back(*it); + size_t ErrorRef = logvisor::ErrorCount; + hecl::ProjectRootPath newProjRoot(rootDir); + newProjRoot.makeDir(); + m_fallbackProj.reset(new hecl::Database::Project(newProjRoot)); + if (logvisor::ErrorCount > ErrorRef) + LogModule.report(logvisor::Fatal, "unable to init project at '%s'", rootDir.c_str()); + LogModule.report(logvisor::Info, _SYS_STR("initialized project at '%s/.hecl'"), rootDir.c_str()); + m_useProj = m_fallbackProj.get(); + } else + m_useProj = info.project; - m_specPasses.reserve(hecl::Database::DATA_SPEC_REGISTRY.size()); - for (const hecl::Database::DataSpecEntry* entry : hecl::Database::DATA_SPEC_REGISTRY) - { - if (entry->m_factory) - { - auto ds = entry->m_factory(*m_useProj, hecl::Database::DataSpecTool::Extract); - if (ds && ds->canExtract(m_einfo, m_reps)) - m_specPasses.emplace_back(entry, std::move(ds)); - } - } + m_einfo.srcpath = m_info.args.front(); + m_einfo.force = info.force; + m_einfo.extractArgs.reserve(info.args.size()); + auto it = info.args.cbegin(); + ++it; + for (; it != info.args.cend(); ++it) + m_einfo.extractArgs.push_back(*it); + + m_specPasses.reserve(hecl::Database::DATA_SPEC_REGISTRY.size()); + for (const hecl::Database::DataSpecEntry* entry : hecl::Database::DATA_SPEC_REGISTRY) { + if (entry->m_factory) { + auto ds = entry->m_factory(*m_useProj, hecl::Database::DataSpecTool::Extract); + if (ds && ds->canExtract(m_einfo, m_reps)) + m_specPasses.emplace_back(entry, std::move(ds)); + } } + } - static void Help(HelpOutput& help) - { - help.secHead(_SYS_STR("NAME")); - help.beginWrap(); - help.wrap(_SYS_STR("hecl-extract - Extract objects from supported package/image formats\n")); - help.endWrap(); + static void Help(HelpOutput& help) { + help.secHead(_SYS_STR("NAME")); + help.beginWrap(); + help.wrap(_SYS_STR("hecl-extract - Extract objects from supported package/image formats\n")); + help.endWrap(); - help.secHead(_SYS_STR("SYNOPSIS")); - help.beginWrap(); - help.wrap(_SYS_STR("hecl extract [...]\n")); - help.endWrap(); + help.secHead(_SYS_STR("SYNOPSIS")); + help.beginWrap(); + help.wrap(_SYS_STR("hecl extract [...]\n")); + help.endWrap(); - help.secHead(_SYS_STR("DESCRIPTION")); - help.beginWrap(); - help.wrap(_SYS_STR("This command recursively extracts all or part of a dataspec-supported ") + help.secHead(_SYS_STR("DESCRIPTION")); + help.beginWrap(); + help.wrap(_SYS_STR("This command recursively extracts all or part of a dataspec-supported ") _SYS_STR("package format. Each object is decoded to a working format and added to the project.\n\n")); - help.endWrap(); + help.endWrap(); - help.secHead(_SYS_STR("OPTIONS")); - help.optionHead(_SYS_STR("[/...]"), _SYS_STR("input file")); - help.beginWrap(); - help.wrap(_SYS_STR("Specifies the package file or disc image to source data from. ") + help.secHead(_SYS_STR("OPTIONS")); + help.optionHead(_SYS_STR("[/...]"), _SYS_STR("input file")); + help.beginWrap(); + help.wrap(_SYS_STR("Specifies the package file or disc image to source data from. ") _SYS_STR("An optional subnode specifies a named hierarchical-node specific ") - _SYS_STR("to the game architecture (levels/areas).")); - help.endWrap(); + _SYS_STR("to the game architecture (levels/areas).")); + help.endWrap(); + } + + hecl::SystemString toolName() const { return _SYS_STR("extract"); } + + static void _recursivePrint(int level, hecl::Database::IDataSpec::ExtractReport& rep) { + for (int l = 0; l < level; ++l) + hecl::Printf(_SYS_STR(" ")); + if (XTERM_COLOR) + hecl::Printf(_SYS_STR("" BOLD "%s" NORMAL ""), rep.name.c_str()); + else + hecl::Printf(_SYS_STR("%s"), rep.name.c_str()); + + if (rep.desc.size()) + hecl::Printf(_SYS_STR(" [%s]"), rep.desc.c_str()); + hecl::Printf(_SYS_STR("\n")); + for (hecl::Database::IDataSpec::ExtractReport& child : rep.childOpts) + _recursivePrint(level + 1, child); + } + + int run() { + if (m_specPasses.empty()) { + if (XTERM_COLOR) + hecl::Printf(_SYS_STR("" RED BOLD "NOTHING TO EXTRACT" NORMAL "\n")); + else + hecl::Printf(_SYS_STR("NOTHING TO EXTRACT\n")); + return 1; } - hecl::SystemString toolName() const {return _SYS_STR("extract");} + if (XTERM_COLOR) + hecl::Printf(_SYS_STR("" GREEN BOLD "ABOUT TO EXTRACT:" NORMAL "\n")); + else + hecl::Printf(_SYS_STR("ABOUT TO EXTRACT:\n")); - static void _recursivePrint(int level, hecl::Database::IDataSpec::ExtractReport& rep) - { - for (int l=0 ; lm_name.data()); else - hecl::Printf(_SYS_STR("%s"), rep.name.c_str()); + hecl::Printf(_SYS_STR("Using DataSpec %s:\n"), ds.m_entry->m_name.data()); - if (rep.desc.size()) - hecl::Printf(_SYS_STR(" [%s]"), rep.desc.c_str()); - hecl::Printf(_SYS_STR("\n")); - for (hecl::Database::IDataSpec::ExtractReport& child : rep.childOpts) - _recursivePrint(level + 1, child); + ds.m_instance->doExtract(m_einfo, {true}); + hecl::Printf(_SYS_STR("\n\n")); + } } - int run() - { - if (m_specPasses.empty()) - { - if (XTERM_COLOR) - hecl::Printf(_SYS_STR("" RED BOLD "NOTHING TO EXTRACT" NORMAL "\n")); - else - hecl::Printf(_SYS_STR("NOTHING TO EXTRACT\n")); - return 1; - } - - if (XTERM_COLOR) - hecl::Printf(_SYS_STR("" GREEN BOLD "ABOUT TO EXTRACT:" NORMAL "\n")); - else - hecl::Printf(_SYS_STR("ABOUT TO EXTRACT:\n")); - - for (hecl::Database::IDataSpec::ExtractReport& rep : m_reps) - { - _recursivePrint(0, rep); - hecl::Printf(_SYS_STR("\n")); - } - fflush(stdout); - - if (continuePrompt()) - { - for (SpecExtractPass& ds : m_specPasses) - { - if (XTERM_COLOR) - hecl::Printf(_SYS_STR("" MAGENTA BOLD "Using DataSpec %s:" NORMAL "\n"), ds.m_entry->m_name.data()); - else - hecl::Printf(_SYS_STR("Using DataSpec %s:\n"), ds.m_entry->m_name.data()); - - ds.m_instance->doExtract(m_einfo, {true}); - hecl::Printf(_SYS_STR("\n\n")); - } - } - - return 0; - } + return 0; + } }; - diff --git a/hecl/driver/ToolHelp.hpp b/hecl/driver/ToolHelp.hpp index 58efa508d..2abeb904e 100644 --- a/hecl/driver/ToolHelp.hpp +++ b/hecl/driver/ToolHelp.hpp @@ -4,89 +4,78 @@ #include #include -class ToolHelp final : public ToolBase -{ - +class ToolHelp final : public ToolBase { public: - ToolHelp(const ToolPassInfo& info) - : ToolBase(info) - { - if (m_info.args.empty()) - { - LogModule.report(logvisor::Error, "help requires a tool name argument"); - return; - } - m_good = true; + ToolHelp(const ToolPassInfo& info) : ToolBase(info) { + if (m_info.args.empty()) { + LogModule.report(logvisor::Error, "help requires a tool name argument"); + return; + } + m_good = true; + } + + ~ToolHelp() {} + + static void Help(HelpOutput& help) { + help.printBold( + _SYS_STR(" ___________ \n") _SYS_STR( + " ,.-'\"...........``~., \n") _SYS_STR(" " + ",.-\".......................\"-., \n") + _SYS_STR(" ,/..................................\":, \n") _SYS_STR( + " .,?........................................, \n") + _SYS_STR(" /...........................................,}\n") _SYS_STR( + " ./........................................,:`^`..}\n") + _SYS_STR(" ./.......................................,:\"...../\n") _SYS_STR( + " ?.....__..................................:`...../\n") + _SYS_STR(" /__.(...\"~-,_...........................,:`....../\n") _SYS_STR( + " /(_....\"~,_....\"~,_.....................,:`...._/ \n") + _SYS_STR(" {.._$;_....\"=,_.....\"-,_......,.-~-,},.~\";/....} \n") _SYS_STR( + " ((...*~_......\"=-._...\";,,./`........../\"..../ \n") + _SYS_STR(" ,,,___.`~,......\"~.,....................`......}....../ \n") _SYS_STR( + "............(....`=-,,...`.........................(...;_,,-\" \n") + _SYS_STR("............/.`~,......`-.................................../ \n") + _SYS_STR(".............`~.*-,.....................................|,./...,__ " + "\n") _SYS_STR(",,_..........}.>-._..................................." + "|.......`=~-, \n") _SYS_STR( + ".....`=~-,__......`,................................. \n") + _SYS_STR("...................`=~-,,.,........................... \n") + _SYS_STR(".........................`:,,..........................`\n") + _SYS_STR( + "...........................`=-,...............,%%`>--==`` \n") + _SYS_STR( + ".................................._.........._,-%%...` \n") + _SYS_STR("...................................,\n")); + } + + static void ShowHelp(const hecl::SystemString& toolName) { + /* Select tool's help-text streamer */ + HelpOutput::HelpFunc helpFunc = NULL; + if (toolName == _SYS_STR("init")) + helpFunc = ToolInit::Help; + else if (toolName == _SYS_STR("spec")) + helpFunc = ToolSpec::Help; + else if (toolName == _SYS_STR("extract")) + helpFunc = ToolExtract::Help; + else if (toolName == _SYS_STR("cook")) + helpFunc = ToolCook::Help; + else if (toolName == _SYS_STR("package") || toolName == _SYS_STR("pack")) + helpFunc = ToolPackage::Help; + else if (toolName == _SYS_STR("help")) + helpFunc = ToolHelp::Help; + else { + LogModule.report(logvisor::Error, _SYS_STR("unrecognized tool '%s' - can't help"), toolName.c_str()); + return; } - ~ToolHelp() - { - } + HelpOutput ho(helpFunc); + ho.go(); + } + hecl::SystemString toolName() const { return _SYS_STR("help"); } - - static void Help(HelpOutput& help) - { - help.printBold( - _SYS_STR(" ___________ \n") - _SYS_STR(" ,.-'\"...........``~., \n") - _SYS_STR(" ,.-\".......................\"-., \n") - _SYS_STR(" ,/..................................\":, \n") - _SYS_STR(" .,?........................................, \n") - _SYS_STR(" /...........................................,}\n") - _SYS_STR(" ./........................................,:`^`..}\n") - _SYS_STR(" ./.......................................,:\"...../\n") - _SYS_STR(" ?.....__..................................:`...../\n") - _SYS_STR(" /__.(...\"~-,_...........................,:`....../\n") - _SYS_STR(" /(_....\"~,_....\"~,_.....................,:`...._/ \n") - _SYS_STR(" {.._$;_....\"=,_.....\"-,_......,.-~-,},.~\";/....} \n") - _SYS_STR(" ((...*~_......\"=-._...\";,,./`........../\"..../ \n") - _SYS_STR(" ,,,___.`~,......\"~.,....................`......}....../ \n") - _SYS_STR("............(....`=-,,...`.........................(...;_,,-\" \n") - _SYS_STR("............/.`~,......`-.................................../ \n") - _SYS_STR(".............`~.*-,.....................................|,./...,__ \n") - _SYS_STR(",,_..........}.>-._...................................|.......`=~-, \n") - _SYS_STR(".....`=~-,__......`,................................. \n") - _SYS_STR("...................`=~-,,.,........................... \n") - _SYS_STR(".........................`:,,..........................`\n") - _SYS_STR("...........................`=-,...............,%%`>--==`` \n") - _SYS_STR(".................................._.........._,-%%...` \n") - _SYS_STR("...................................,\n")); - } - - static void ShowHelp(const hecl::SystemString& toolName) - { - /* Select tool's help-text streamer */ - HelpOutput::HelpFunc helpFunc = NULL; - if (toolName == _SYS_STR("init")) - helpFunc = ToolInit::Help; - else if (toolName == _SYS_STR("spec")) - helpFunc = ToolSpec::Help; - else if (toolName == _SYS_STR("extract")) - helpFunc = ToolExtract::Help; - else if (toolName == _SYS_STR("cook")) - helpFunc = ToolCook::Help; - else if (toolName == _SYS_STR("package") || toolName == _SYS_STR("pack")) - helpFunc = ToolPackage::Help; - else if (toolName == _SYS_STR("help")) - helpFunc = ToolHelp::Help; - else - { - LogModule.report(logvisor::Error, _SYS_STR("unrecognized tool '%s' - can't help"), toolName.c_str()); - return; - } - - HelpOutput ho(helpFunc); - ho.go(); - } - - hecl::SystemString toolName() const {return _SYS_STR("help");} - - int run() - { - ShowHelp(m_info.args.front()); - return 0; - } + int run() { + ShowHelp(m_info.args.front()); + return 0; + } }; - diff --git a/hecl/driver/ToolImage.hpp b/hecl/driver/ToolImage.hpp index 0947c162c..f383563c9 100644 --- a/hecl/driver/ToolImage.hpp +++ b/hecl/driver/ToolImage.hpp @@ -10,148 +10,128 @@ #include "nod/DiscWii.hpp" #include "athena/FileReader.hpp" -class ToolImage final : public ToolBase -{ - std::unique_ptr m_fallbackProj; - hecl::Database::Project* m_useProj; +class ToolImage final : public ToolBase { + std::unique_ptr m_fallbackProj; + hecl::Database::Project* m_useProj; public: - ToolImage(const ToolPassInfo& info) - : ToolBase(info), m_useProj(info.project) - { - if (!info.project) - LogModule.report(logvisor::Fatal, "hecl image must be ran within a project directory"); + ToolImage(const ToolPassInfo& info) : ToolBase(info), m_useProj(info.project) { + if (!info.project) + LogModule.report(logvisor::Fatal, "hecl image must be ran within a project directory"); - /* Scan args */ - if (info.args.size()) - { - /* See if project path is supplied via args and use that over the getcwd one */ - for (const hecl::SystemString& arg : info.args) - { - if (arg.empty()) - continue; + /* Scan args */ + if (info.args.size()) { + /* See if project path is supplied via args and use that over the getcwd one */ + for (const hecl::SystemString& arg : info.args) { + if (arg.empty()) + continue; - hecl::SystemString subPath; - hecl::ProjectRootPath root = hecl::SearchForProject(MakePathArgAbsolute(arg, info.cwd), subPath); + hecl::SystemString subPath; + hecl::ProjectRootPath root = hecl::SearchForProject(MakePathArgAbsolute(arg, info.cwd), subPath); - if (root) - { - if (!m_fallbackProj) - { - m_fallbackProj.reset(new hecl::Database::Project(root)); - m_useProj = m_fallbackProj.get(); - break; - } - } - } + if (root) { + if (!m_fallbackProj) { + m_fallbackProj.reset(new hecl::Database::Project(root)); + m_useProj = m_fallbackProj.get(); + break; + } } - if (!m_useProj) - LogModule.report(logvisor::Fatal, - "hecl image must be ran within a project directory or " - "provided a path within a project"); + } } + if (!m_useProj) + LogModule.report(logvisor::Fatal, + "hecl image must be ran within a project directory or " + "provided a path within a project"); + } - ~ToolImage() - { - } + ~ToolImage() {} - static void Help(HelpOutput& help) - { - help.secHead(_SYS_STR("NAME")); - help.beginWrap(); - help.wrap(_SYS_STR("hecl-image - Generate GameCube/Wii disc image from packaged files\n")); - help.endWrap(); + static void Help(HelpOutput& help) { + help.secHead(_SYS_STR("NAME")); + help.beginWrap(); + help.wrap(_SYS_STR("hecl-image - Generate GameCube/Wii disc image from packaged files\n")); + help.endWrap(); - help.secHead(_SYS_STR("SYNOPSIS")); - help.beginWrap(); - help.wrap(_SYS_STR("hecl image []\n")); - help.endWrap(); + help.secHead(_SYS_STR("SYNOPSIS")); + help.beginWrap(); + help.wrap(_SYS_STR("hecl image []\n")); + help.endWrap(); - help.secHead(_SYS_STR("DESCRIPTION")); - help.beginWrap(); - help.wrap(_SYS_STR("This command uses the current contents of `out` to generate a GameCube or ") + help.secHead(_SYS_STR("DESCRIPTION")); + help.beginWrap(); + help.wrap(_SYS_STR("This command uses the current contents of `out` to generate a GameCube or ") _SYS_STR("Wii disc image. `hecl package` must have been run previously to be effective.\n")); - help.endWrap(); + help.endWrap(); - help.secHead(_SYS_STR("OPTIONS")); - help.optionHead(_SYS_STR(""), _SYS_STR("input directory")); - help.beginWrap(); - help.wrap(_SYS_STR("Specifies a project subdirectory to root the resulting image from. ") + help.secHead(_SYS_STR("OPTIONS")); + help.optionHead(_SYS_STR(""), _SYS_STR("input directory")); + help.beginWrap(); + help.wrap(_SYS_STR("Specifies a project subdirectory to root the resulting image from. ") _SYS_STR("Project must contain an out/sys and out/files directory to succeed.\n")); - help.endWrap(); + help.endWrap(); + } + + hecl::SystemString toolName() const { return _SYS_STR("image"); } + + int run() { + if (XTERM_COLOR) + hecl::Printf(_SYS_STR("" GREEN BOLD "ABOUT TO IMAGE:" NORMAL "\n")); + else + hecl::Printf(_SYS_STR("ABOUT TO IMAGE:\n")); + + hecl::Printf(_SYS_STR(" %s\n"), m_useProj->getProjectRootPath().getAbsolutePath().data()); + fflush(stdout); + + if (continuePrompt()) { + hecl::ProjectPath outPath(m_useProj->getProjectWorkingPath(), _SYS_STR("out")); + if (!outPath.isDirectory()) { + LogModule.report(logvisor::Error, _SYS_STR("%s is not a directory"), outPath.getAbsolutePath().data()); + return 1; + } + + hecl::ProjectPath bootBinPath(outPath, _SYS_STR("sys/boot.bin")); + if (!bootBinPath.isFile()) { + LogModule.report(logvisor::Error, _SYS_STR("%s is not a file"), bootBinPath.getAbsolutePath().data()); + return 1; + } + + athena::io::FileReader r(bootBinPath.getAbsolutePath()); + if (r.hasError()) { + LogModule.report(logvisor::Error, _SYS_STR("unable to open %s"), bootBinPath.getAbsolutePath().data()); + return 1; + } + std::string id = r.readString(6); + r.close(); + + hecl::SystemStringConv idView(id); + hecl::SystemString fileOut = hecl::SystemString(outPath.getAbsolutePath()) + _SYS_STR('/') + idView.c_str(); + hecl::MultiProgressPrinter printer(true); + auto progFunc = [&printer](float totalProg, nod::SystemStringView fileName, size_t fileBytesXfered) { + printer.print(fileName.data(), nullptr, totalProg); + }; + if (id[0] == 'G') { + fileOut += _SYS_STR(".gcm"); + if (nod::DiscBuilderGCN::CalculateTotalSizeRequired(outPath.getAbsolutePath()) == -1) + return 1; + LogModule.report(logvisor::Info, _SYS_STR("Generating %s as GameCube image"), fileOut.c_str()); + nod::DiscBuilderGCN db(fileOut, progFunc); + if (db.buildFromDirectory(outPath.getAbsolutePath()) != nod::EBuildResult::Success) + return 1; + } else { + fileOut += _SYS_STR(".iso"); + bool dualLayer; + if (nod::DiscBuilderWii::CalculateTotalSizeRequired(outPath.getAbsolutePath(), dualLayer) == -1) + return 1; + LogModule.report(logvisor::Info, _SYS_STR("Generating %s as %s-layer Wii image"), fileOut.c_str(), + dualLayer ? _SYS_STR("dual") : _SYS_STR("single")); + nod::DiscBuilderWii db(fileOut, dualLayer, progFunc); + if (db.buildFromDirectory(outPath.getAbsolutePath()) != nod::EBuildResult::Success) + return 1; + } } - hecl::SystemString toolName() const {return _SYS_STR("image");} - - int run() - { - if (XTERM_COLOR) - hecl::Printf(_SYS_STR("" GREEN BOLD "ABOUT TO IMAGE:" NORMAL "\n")); - else - hecl::Printf(_SYS_STR("ABOUT TO IMAGE:\n")); - - hecl::Printf(_SYS_STR(" %s\n"), m_useProj->getProjectRootPath().getAbsolutePath().data()); - fflush(stdout); - - if (continuePrompt()) - { - hecl::ProjectPath outPath(m_useProj->getProjectWorkingPath(), _SYS_STR("out")); - if (!outPath.isDirectory()) - { - LogModule.report(logvisor::Error, _SYS_STR("%s is not a directory"), outPath.getAbsolutePath().data()); - return 1; - } - - hecl::ProjectPath bootBinPath(outPath, _SYS_STR("sys/boot.bin")); - if (!bootBinPath.isFile()) - { - LogModule.report(logvisor::Error, _SYS_STR("%s is not a file"), bootBinPath.getAbsolutePath().data()); - return 1; - } - - athena::io::FileReader r(bootBinPath.getAbsolutePath()); - if (r.hasError()) - { - LogModule.report(logvisor::Error, _SYS_STR("unable to open %s"), bootBinPath.getAbsolutePath().data()); - return 1; - } - std::string id = r.readString(6); - r.close(); - - hecl::SystemStringConv idView(id); - hecl::SystemString fileOut = hecl::SystemString(outPath.getAbsolutePath()) + _SYS_STR('/') + idView.c_str(); - hecl::MultiProgressPrinter printer(true); - auto progFunc = [&printer](float totalProg, nod::SystemStringView fileName, size_t fileBytesXfered) - { - printer.print(fileName.data(), nullptr, totalProg); - }; - if (id[0] == 'G') - { - fileOut += _SYS_STR(".gcm"); - if (nod::DiscBuilderGCN::CalculateTotalSizeRequired(outPath.getAbsolutePath()) == -1) - return 1; - LogModule.report(logvisor::Info, _SYS_STR("Generating %s as GameCube image"), fileOut.c_str()); - nod::DiscBuilderGCN db(fileOut, progFunc); - if (db.buildFromDirectory(outPath.getAbsolutePath()) != nod::EBuildResult::Success) - return 1; - } - else - { - fileOut += _SYS_STR(".iso"); - bool dualLayer; - if (nod::DiscBuilderWii::CalculateTotalSizeRequired(outPath.getAbsolutePath(), dualLayer) == -1) - return 1; - LogModule.report(logvisor::Info, _SYS_STR("Generating %s as %s-layer Wii image"), fileOut.c_str(), - dualLayer ? _SYS_STR("dual") : _SYS_STR("single")); - nod::DiscBuilderWii db(fileOut, dualLayer, progFunc); - if (db.buildFromDirectory(outPath.getAbsolutePath()) != nod::EBuildResult::Success) - return 1; - } - } - - return 0; - } + return 0; + } }; #endif - diff --git a/hecl/driver/ToolInit.hpp b/hecl/driver/ToolInit.hpp index 59f1659ab..da6e1334e 100644 --- a/hecl/driver/ToolInit.hpp +++ b/hecl/driver/ToolInit.hpp @@ -3,84 +3,75 @@ #include "ToolBase.hpp" #include -class ToolInit final : public ToolBase -{ - const hecl::SystemString* m_dir = NULL; +class ToolInit final : public ToolBase { + const hecl::SystemString* m_dir = NULL; + public: - ToolInit(const ToolPassInfo& info) - : ToolBase(info) - { - hecl::Sstat theStat; - const hecl::SystemString* dir; - if (info.args.size()) - dir = &info.args.front(); - else - dir = &info.cwd; + ToolInit(const ToolPassInfo& info) : ToolBase(info) { + hecl::Sstat theStat; + const hecl::SystemString* dir; + if (info.args.size()) + dir = &info.args.front(); + else + dir = &info.cwd; - if (hecl::Stat(dir->c_str(), &theStat)) - { - hecl::MakeDir(dir->c_str()); - if (hecl::Stat(dir->c_str(), &theStat)) - { - LogModule.report(logvisor::Fatal, _SYS_STR("unable to stat '%s'"), dir->c_str()); - return; - } - } - if (!S_ISDIR(theStat.st_mode)) - { - LogModule.report(logvisor::Fatal, _SYS_STR("'%s' is not a directory"), dir->c_str()); - return; - } - - hecl::SystemString testPath = *dir + _SYS_STR("/.hecl/beacon"); - if (!hecl::Stat(testPath.c_str(), &theStat)) - { - LogModule.report(logvisor::Fatal, _SYS_STR("project already exists at '%s'"), dir->c_str()); - return; - } - - m_dir = dir; + if (hecl::Stat(dir->c_str(), &theStat)) { + hecl::MakeDir(dir->c_str()); + if (hecl::Stat(dir->c_str(), &theStat)) { + LogModule.report(logvisor::Fatal, _SYS_STR("unable to stat '%s'"), dir->c_str()); + return; + } + } + if (!S_ISDIR(theStat.st_mode)) { + LogModule.report(logvisor::Fatal, _SYS_STR("'%s' is not a directory"), dir->c_str()); + return; } - int run() - { - if (!m_dir) - return 1; - size_t ErrorRef = logvisor::ErrorCount; - hecl::Database::Project proj((hecl::ProjectRootPath(*m_dir))); - if (logvisor::ErrorCount > ErrorRef) - return 1; - LogModule.report(logvisor::Info, _SYS_STR("initialized project at '%s/.hecl'"), m_dir->c_str()); - return 0; + hecl::SystemString testPath = *dir + _SYS_STR("/.hecl/beacon"); + if (!hecl::Stat(testPath.c_str(), &theStat)) { + LogModule.report(logvisor::Fatal, _SYS_STR("project already exists at '%s'"), dir->c_str()); + return; } - static void Help(HelpOutput& help) - { - help.secHead(_SYS_STR("NAME")); - help.beginWrap(); - help.wrap(_SYS_STR("hecl-init - Initialize a brand-new project database\n")); - help.endWrap(); + m_dir = dir; + } - help.secHead(_SYS_STR("SYNOPSIS")); - help.beginWrap(); - help.wrap(_SYS_STR("hecl init []\n")); - help.endWrap(); + int run() { + if (!m_dir) + return 1; + size_t ErrorRef = logvisor::ErrorCount; + hecl::Database::Project proj((hecl::ProjectRootPath(*m_dir))); + if (logvisor::ErrorCount > ErrorRef) + return 1; + LogModule.report(logvisor::Info, _SYS_STR("initialized project at '%s/.hecl'"), m_dir->c_str()); + return 0; + } - help.secHead(_SYS_STR("DESCRIPTION")); - help.beginWrap(); - help.wrap(_SYS_STR("Creates a ")); - help.wrapBold(_SYS_STR(".hecl")); - help.wrap(_SYS_STR(" directory within the selected directory with an initialized database index. ") + static void Help(HelpOutput& help) { + help.secHead(_SYS_STR("NAME")); + help.beginWrap(); + help.wrap(_SYS_STR("hecl-init - Initialize a brand-new project database\n")); + help.endWrap(); + + help.secHead(_SYS_STR("SYNOPSIS")); + help.beginWrap(); + help.wrap(_SYS_STR("hecl init []\n")); + help.endWrap(); + + help.secHead(_SYS_STR("DESCRIPTION")); + help.beginWrap(); + help.wrap(_SYS_STR("Creates a ")); + help.wrapBold(_SYS_STR(".hecl")); + help.wrap(_SYS_STR(" directory within the selected directory with an initialized database index. ") _SYS_STR("This constitutes an empty HECL project, ready for making stuff!!\n")); - help.endWrap(); + help.endWrap(); - help.secHead(_SYS_STR("OPTIONS")); - help.optionHead(_SYS_STR(""), _SYS_STR("group directory path")); - help.beginWrap(); - help.wrap(_SYS_STR("Directory to create new project database in. If not specified, current directory is used.\n")); - help.endWrap(); - } + help.secHead(_SYS_STR("OPTIONS")); + help.optionHead(_SYS_STR(""), _SYS_STR("group directory path")); + help.beginWrap(); + help.wrap(_SYS_STR("Directory to create new project database in. If not specified, current directory is used.\n")); + help.endWrap(); + } - hecl::SystemString toolName() const {return _SYS_STR("init");} + hecl::SystemString toolName() const { return _SYS_STR("init"); } }; - diff --git a/hecl/driver/ToolPackage.hpp b/hecl/driver/ToolPackage.hpp index 162e66782..fb03595f6 100644 --- a/hecl/driver/ToolPackage.hpp +++ b/hecl/driver/ToolPackage.hpp @@ -5,212 +5,181 @@ #include "ToolBase.hpp" #include -class ToolPackage final : public ToolBase -{ - std::vector m_selectedItems; - std::unique_ptr m_fallbackProj; - hecl::Database::Project* m_useProj; - const hecl::Database::DataSpecEntry* m_spec = nullptr; - bool m_fast = false; +class ToolPackage final : public ToolBase { + std::vector m_selectedItems; + std::unique_ptr m_fallbackProj; + hecl::Database::Project* m_useProj; + const hecl::Database::DataSpecEntry* m_spec = nullptr; + bool m_fast = false; - void AddSelectedItem(const hecl::ProjectPath& path) - { - for (const hecl::ProjectPath& item : m_selectedItems) - if (item == path) - return; - m_selectedItems.push_back(path); - } + void AddSelectedItem(const hecl::ProjectPath& path) { + for (const hecl::ProjectPath& item : m_selectedItems) + if (item == path) + return; + m_selectedItems.push_back(path); + } - void CheckFile(const hecl::ProjectPath& path) - { - if (!hecl::StrCmp(path.getLastComponent().data(), _SYS_STR("!world.blend"))) - AddSelectedItem(path); + void CheckFile(const hecl::ProjectPath& path) { + if (!hecl::StrCmp(path.getLastComponent().data(), _SYS_STR("!world.blend"))) + AddSelectedItem(path); #if RUNTIME_ORIGINAL_IDS - else if (!hecl::StrCmp(path.getLastComponent().data(), _SYS_STR("!original_ids.yaml"))) - { - auto pathComps = path.getPathComponents(); - if (pathComps.size() == 2 && pathComps[0] != _SYS_STR("out")) - AddSelectedItem(path); - } + else if (!hecl::StrCmp(path.getLastComponent().data(), _SYS_STR("!original_ids.yaml"))) { + auto pathComps = path.getPathComponents(); + if (pathComps.size() == 2 && pathComps[0] != _SYS_STR("out")) + AddSelectedItem(path); + } #endif + } + + void FindSelectedItems(const hecl::ProjectPath& path, bool checkGeneral) { + if (path.isFile()) { + CheckFile(path); + return; } - void FindSelectedItems(const hecl::ProjectPath& path, bool checkGeneral) - { - if (path.isFile()) - { - CheckFile(path); - return; - } - - size_t origSize = m_selectedItems.size(); - hecl::DirectoryEnumerator dEnum(path.getAbsolutePath(), - hecl::DirectoryEnumerator::Mode::DirsThenFilesSorted, false, false, true); - for (const auto& ent : dEnum) - { - hecl::ProjectPath childPath(path, ent.m_name); - if (ent.m_isDir) - FindSelectedItems(childPath, checkGeneral && childPath.getPathComponents().size() <= 2); - else - CheckFile(childPath); - } - - /* Directory with 2 components not "Shared" or macOS app bundle - * and no nested !world.blend files == General PAK */ - if (checkGeneral && origSize == m_selectedItems.size()) - { - auto pathComps = path.getPathComponents(); - if (pathComps.size() == 2 && pathComps[0] != _SYS_STR("out") && - pathComps[1] != _SYS_STR("Shared") && pathComps[0].find(_SYS_STR(".app")) == hecl::SystemString::npos) - AddSelectedItem(path); - } + size_t origSize = m_selectedItems.size(); + hecl::DirectoryEnumerator dEnum(path.getAbsolutePath(), hecl::DirectoryEnumerator::Mode::DirsThenFilesSorted, false, + false, true); + for (const auto& ent : dEnum) { + hecl::ProjectPath childPath(path, ent.m_name); + if (ent.m_isDir) + FindSelectedItems(childPath, checkGeneral && childPath.getPathComponents().size() <= 2); + else + CheckFile(childPath); } + /* Directory with 2 components not "Shared" or macOS app bundle + * and no nested !world.blend files == General PAK */ + if (checkGeneral && origSize == m_selectedItems.size()) { + auto pathComps = path.getPathComponents(); + if (pathComps.size() == 2 && pathComps[0] != _SYS_STR("out") && pathComps[1] != _SYS_STR("Shared") && + pathComps[0].find(_SYS_STR(".app")) == hecl::SystemString::npos) + AddSelectedItem(path); + } + } + public: - ToolPackage(const ToolPassInfo& info) - : ToolBase(info), m_useProj(info.project) - { - if (!info.project) - LogModule.report(logvisor::Fatal, "hecl package must be ran within a project directory"); + ToolPackage(const ToolPassInfo& info) : ToolBase(info), m_useProj(info.project) { + if (!info.project) + LogModule.report(logvisor::Fatal, "hecl package must be ran within a project directory"); - /* Scan args */ - if (info.args.size()) - { - /* See if project path is supplied via args and use that over the getcwd one */ - m_selectedItems.reserve(info.args.size()); - for (const hecl::SystemString& arg : info.args) - { - if (arg.empty()) - continue; - else if (!arg.compare(_SYS_STR("--fast"))) - { - m_fast = true; - continue; - } - else if (arg.size() >= 8 && !arg.compare(0, 7, _SYS_STR("--spec="))) - { - hecl::SystemString specName(arg.begin() + 7, arg.end()); - for (const hecl::Database::DataSpecEntry* spec : hecl::Database::DATA_SPEC_REGISTRY) - { - if (!hecl::StrCaseCmp(spec->m_name.data(), specName.c_str())) - { - m_spec = spec; - break; - } - } - if (!m_spec) - LogModule.report(logvisor::Fatal, "unable to find data spec '%s'", specName.c_str()); - continue; - } - else if (arg.size() >= 2 && arg[0] == _SYS_STR('-') && arg[1] == _SYS_STR('-')) - continue; - - hecl::SystemString subPath; - hecl::ProjectRootPath root = hecl::SearchForProject(MakePathArgAbsolute(arg, info.cwd), subPath); - - if (root) - { - if (!m_fallbackProj) - { - m_fallbackProj.reset(new hecl::Database::Project(root)); - m_useProj = m_fallbackProj.get(); - } - else if (m_fallbackProj->getProjectRootPath() != root) - LogModule.report(logvisor::Fatal, - _SYS_STR("hecl package can only process multiple items in the same project; ") - _SYS_STR("'%s' and '%s' are different projects"), - m_fallbackProj->getProjectRootPath().getAbsolutePath().data(), - root.getAbsolutePath().data()); - - FindSelectedItems({*m_useProj, subPath}, true); - } + /* Scan args */ + if (info.args.size()) { + /* See if project path is supplied via args and use that over the getcwd one */ + m_selectedItems.reserve(info.args.size()); + for (const hecl::SystemString& arg : info.args) { + if (arg.empty()) + continue; + else if (!arg.compare(_SYS_STR("--fast"))) { + m_fast = true; + continue; + } else if (arg.size() >= 8 && !arg.compare(0, 7, _SYS_STR("--spec="))) { + hecl::SystemString specName(arg.begin() + 7, arg.end()); + for (const hecl::Database::DataSpecEntry* spec : hecl::Database::DATA_SPEC_REGISTRY) { + if (!hecl::StrCaseCmp(spec->m_name.data(), specName.c_str())) { + m_spec = spec; + break; } - } - if (!m_useProj) + } + if (!m_spec) + LogModule.report(logvisor::Fatal, "unable to find data spec '%s'", specName.c_str()); + continue; + } else if (arg.size() >= 2 && arg[0] == _SYS_STR('-') && arg[1] == _SYS_STR('-')) + continue; + + hecl::SystemString subPath; + hecl::ProjectRootPath root = hecl::SearchForProject(MakePathArgAbsolute(arg, info.cwd), subPath); + + if (root) { + if (!m_fallbackProj) { + m_fallbackProj.reset(new hecl::Database::Project(root)); + m_useProj = m_fallbackProj.get(); + } else if (m_fallbackProj->getProjectRootPath() != root) LogModule.report(logvisor::Fatal, - "hecl package must be ran within a project directory or " - "provided a path within a project"); + _SYS_STR("hecl package can only process multiple items in the same project; ") + _SYS_STR("'%s' and '%s' are different projects"), + m_fallbackProj->getProjectRootPath().getAbsolutePath().data(), + root.getAbsolutePath().data()); - /* Default case: recursive at root */ - if (m_selectedItems.empty()) - FindSelectedItems({*m_useProj, _SYS_STR("")}, true); + FindSelectedItems({*m_useProj, subPath}, true); + } + } } + if (!m_useProj) + LogModule.report(logvisor::Fatal, + "hecl package must be ran within a project directory or " + "provided a path within a project"); - static void Help(HelpOutput& help) - { - help.secHead(_SYS_STR("NAME")); - help.beginWrap(); - help.wrap(_SYS_STR("hecl-pack\n") - _SYS_STR("hecl-package - Package objects within the project database\n")); - help.endWrap(); + /* Default case: recursive at root */ + if (m_selectedItems.empty()) + FindSelectedItems({*m_useProj, _SYS_STR("")}, true); + } - help.secHead(_SYS_STR("SYNOPSIS")); - help.beginWrap(); - help.wrap(_SYS_STR("hecl package [--spec=] []\n")); - help.endWrap(); + static void Help(HelpOutput& help) { + help.secHead(_SYS_STR("NAME")); + help.beginWrap(); + help.wrap(_SYS_STR("hecl-pack\n") _SYS_STR("hecl-package - Package objects within the project database\n")); + help.endWrap(); - help.secHead(_SYS_STR("DESCRIPTION")); - help.beginWrap(); - help.wrap(_SYS_STR("This command initiates a packaging pass on the project database. Packaging ") - _SYS_STR("is analogous to linking in software development. All objects necessary to ") - _SYS_STR("generate a complete package are gathered, grouped, and indexed within a .upak file.\n")); - help.endWrap(); + help.secHead(_SYS_STR("SYNOPSIS")); + help.beginWrap(); + help.wrap(_SYS_STR("hecl package [--spec=] []\n")); + help.endWrap(); - help.secHead(_SYS_STR("OPTIONS")); - help.optionHead(_SYS_STR("--spec="), _SYS_STR("data specification")); - help.beginWrap(); - help.wrap(_SYS_STR("Specifies a DataSpec to use when cooking and generating the package. ") + help.secHead(_SYS_STR("DESCRIPTION")); + help.beginWrap(); + help.wrap(_SYS_STR("This command initiates a packaging pass on the project database. Packaging ") + _SYS_STR("is analogous to linking in software development. All objects necessary to ") _SYS_STR( + "generate a complete package are gathered, grouped, and indexed within a .upak file.\n")); + help.endWrap(); + + help.secHead(_SYS_STR("OPTIONS")); + help.optionHead(_SYS_STR("--spec="), _SYS_STR("data specification")); + help.beginWrap(); + help.wrap(_SYS_STR("Specifies a DataSpec to use when cooking and generating the package. ") _SYS_STR("This build of hecl supports the following values of :\n")); - for (const hecl::Database::DataSpecEntry* spec : hecl::Database::DATA_SPEC_REGISTRY) - { - if (!spec->m_factory) - continue; - help.wrap(_SYS_STR(" ")); - help.wrapBold(spec->m_name.data()); - help.wrap(_SYS_STR("\n")); - } - help.endWrap(); + for (const hecl::Database::DataSpecEntry* spec : hecl::Database::DATA_SPEC_REGISTRY) { + if (!spec->m_factory) + continue; + help.wrap(_SYS_STR(" ")); + help.wrapBold(spec->m_name.data()); + help.wrap(_SYS_STR("\n")); + } + help.endWrap(); - help.secHead(_SYS_STR("OPTIONS")); - help.optionHead(_SYS_STR(""), _SYS_STR("input directory")); - help.beginWrap(); - help.wrap(_SYS_STR("Specifies a project subdirectory to root the resulting package from. ") + help.secHead(_SYS_STR("OPTIONS")); + help.optionHead(_SYS_STR(""), _SYS_STR("input directory")); + help.beginWrap(); + help.wrap(_SYS_STR("Specifies a project subdirectory to root the resulting package from. ") _SYS_STR("If any dependent files fall outside this subdirectory, they will be implicitly ") - _SYS_STR("gathered and packaged.\n")); - help.endWrap(); + _SYS_STR("gathered and packaged.\n")); + help.endWrap(); + } + + hecl::SystemString toolName() const { return _SYS_STR("package"); } + + int run() { + if (XTERM_COLOR) + hecl::Printf(_SYS_STR("" GREEN BOLD "ABOUT TO PACKAGE:" NORMAL "\n")); + else + hecl::Printf(_SYS_STR("ABOUT TO PACKAGE:\n")); + + for (auto& item : m_selectedItems) + hecl::Printf(_SYS_STR(" %s\n"), item.getRelativePath().data()); + fflush(stdout); + + if (continuePrompt()) { + hecl::MultiProgressPrinter printer(true); + hecl::ClientProcess cp(&printer); + for (const hecl::ProjectPath& path : m_selectedItems) { + if (!m_useProj->packagePath(path, printer, m_fast, m_spec, &cp)) + LogModule.report(logvisor::Error, _SYS_STR("Unable to package %s"), path.getAbsolutePath().data()); + } + cp.waitUntilComplete(); } - hecl::SystemString toolName() const {return _SYS_STR("package");} + return 0; + } - int run() - { - if (XTERM_COLOR) - hecl::Printf(_SYS_STR("" GREEN BOLD "ABOUT TO PACKAGE:" NORMAL "\n")); - else - hecl::Printf(_SYS_STR("ABOUT TO PACKAGE:\n")); - - for (auto& item : m_selectedItems) - hecl::Printf(_SYS_STR(" %s\n"), item.getRelativePath().data()); - fflush(stdout); - - if (continuePrompt()) - { - hecl::MultiProgressPrinter printer(true); - hecl::ClientProcess cp(&printer); - for (const hecl::ProjectPath& path : m_selectedItems) - { - if (!m_useProj->packagePath(path, printer, m_fast, m_spec, &cp)) - LogModule.report(logvisor::Error, _SYS_STR("Unable to package %s"), path.getAbsolutePath().data()); - } - cp.waitUntilComplete(); - } - - return 0; - } - - void cancel() - { - m_useProj->interruptCook(); - } + void cancel() { m_useProj->interruptCook(); } }; - diff --git a/hecl/driver/ToolSpec.hpp b/hecl/driver/ToolSpec.hpp index 932c80e22..a7f9bc4ad 100644 --- a/hecl/driver/ToolSpec.hpp +++ b/hecl/driver/ToolSpec.hpp @@ -4,153 +4,128 @@ #include #include -class ToolSpec final : public ToolBase -{ - enum Mode - { - MLIST = 0, - MENABLE, - MDISABLE - } mode = MLIST; +class ToolSpec final : public ToolBase { + enum Mode { MLIST = 0, MENABLE, MDISABLE } mode = MLIST; + public: - ToolSpec(const ToolPassInfo& info) - : ToolBase(info) - { - if (info.args.empty()) - return; + ToolSpec(const ToolPassInfo& info) : ToolBase(info) { + if (info.args.empty()) + return; - if (!info.project) - LogModule.report(logvisor::Fatal, - "hecl spec must be ran within a project directory"); + if (!info.project) + LogModule.report(logvisor::Fatal, "hecl spec must be ran within a project directory"); - const auto& specs = info.project->getDataSpecs(); - hecl::SystemString firstArg = info.args.front(); - hecl::ToLower(firstArg); + const auto& specs = info.project->getDataSpecs(); + hecl::SystemString firstArg = info.args.front(); + hecl::ToLower(firstArg); - if (!firstArg.compare(_SYS_STR("enable"))) - mode = MENABLE; - else if (!firstArg.compare(_SYS_STR("disable"))) - mode = MDISABLE; + if (!firstArg.compare(_SYS_STR("enable"))) + mode = MENABLE; + else if (!firstArg.compare(_SYS_STR("disable"))) + mode = MDISABLE; + else + return; + + if (info.args.size() < 2) + LogModule.report(logvisor::Fatal, "Speclist argument required"); + + auto it = info.args.begin(); + ++it; + for (; it != info.args.end(); ++it) { + + bool found = false; + for (auto& spec : specs) { + if (!it->compare(spec.spec.m_name)) { + found = true; + break; + } + } + if (!found) + LogModule.report(logvisor::Fatal, _SYS_STR("'%s' is not found in the dataspec registry"), it->c_str()); + } + } + + static void Help(HelpOutput& help) { + help.secHead(_SYS_STR("NAME")); + help.beginWrap(); + help.wrap(_SYS_STR("hecl-spec - Configure target data options\n")); + help.endWrap(); + + help.secHead(_SYS_STR("SYNOPSIS")); + help.beginWrap(); + help.wrap(_SYS_STR("hecl spec [enable|disable] [...]\n")); + help.endWrap(); + + help.secHead(_SYS_STR("DESCRIPTION")); + help.beginWrap(); + help.wrap( + _SYS_STR("This command configures the HECL project with the user's preferred target DataSpecs.\n\n") + _SYS_STR("Providing enable/disable argument will bulk-set the enable status of the provided spec(s)") + _SYS_STR("list. If enable/disable is not provided, a list of supported DataSpecs is printed.\n\n")); + help.endWrap(); + + help.secHead(_SYS_STR("OPTIONS")); + help.optionHead(_SYS_STR("..."), _SYS_STR("DataSpec name(s)")); + help.beginWrap(); + help.wrap(_SYS_STR("Specifies platform-names to enable/disable")); + help.endWrap(); + } + + hecl::SystemString toolName() const { return _SYS_STR("spec"); } + + int run() { + if (!m_info.project) { + for (const hecl::Database::DataSpecEntry* spec : hecl::Database::DATA_SPEC_REGISTRY) { + if (XTERM_COLOR) + hecl::Printf(_SYS_STR("" BOLD CYAN "%s" NORMAL "\n"), spec->m_name.data()); else - return; - - if (info.args.size() < 2) - LogModule.report(logvisor::Fatal, "Speclist argument required"); - - auto it = info.args.begin(); - ++it; - for (;it != info.args.end(); - ++it) - { - - bool found = false; - for (auto& spec : specs) - { - if (!it->compare(spec.spec.m_name)) - { - found = true; - break; - } - } - if (!found) - LogModule.report(logvisor::Fatal, - _SYS_STR("'%s' is not found in the dataspec registry"), - it->c_str()); - } + hecl::Printf(_SYS_STR("%s\n"), spec->m_name.data()); + hecl::Printf(_SYS_STR(" %s\n"), spec->m_desc.data()); + } + return 0; } - static void Help(HelpOutput& help) - { - help.secHead(_SYS_STR("NAME")); - help.beginWrap(); - help.wrap(_SYS_STR("hecl-spec - Configure target data options\n")); - help.endWrap(); - - help.secHead(_SYS_STR("SYNOPSIS")); - help.beginWrap(); - help.wrap(_SYS_STR("hecl spec [enable|disable] [...]\n")); - help.endWrap(); - - help.secHead(_SYS_STR("DESCRIPTION")); - help.beginWrap(); - help.wrap(_SYS_STR("This command configures the HECL project with the user's preferred target DataSpecs.\n\n") - _SYS_STR("Providing enable/disable argument will bulk-set the enable status of the provided spec(s)") - _SYS_STR("list. If enable/disable is not provided, a list of supported DataSpecs is printed.\n\n")); - help.endWrap(); - - help.secHead(_SYS_STR("OPTIONS")); - help.optionHead(_SYS_STR("..."), _SYS_STR("DataSpec name(s)")); - help.beginWrap(); - help.wrap(_SYS_STR("Specifies platform-names to enable/disable")); - help.endWrap(); + const auto& specs = m_info.project->getDataSpecs(); + if (mode == MLIST) { + for (auto& spec : specs) { + if (XTERM_COLOR) + hecl::Printf(_SYS_STR("" BOLD CYAN "%s" NORMAL ""), spec.spec.m_name.data()); + else + hecl::Printf(_SYS_STR("%s"), spec.spec.m_name.data()); + if (spec.active) { + if (XTERM_COLOR) + hecl::Printf(_SYS_STR(" " BOLD GREEN "[ENABLED]" NORMAL "")); + else + hecl::Printf(_SYS_STR(" [ENABLED]")); + } + hecl::Printf(_SYS_STR("\n %s\n"), spec.spec.m_desc.data()); + } + return 0; } - hecl::SystemString toolName() const {return _SYS_STR("spec");} - - int run() - { - if (!m_info.project) - { - for (const hecl::Database::DataSpecEntry* spec : hecl::Database::DATA_SPEC_REGISTRY) - { - if (XTERM_COLOR) - hecl::Printf(_SYS_STR("" BOLD CYAN "%s" NORMAL "\n"), spec->m_name.data()); - else - hecl::Printf(_SYS_STR("%s\n"), spec->m_name.data()); - hecl::Printf(_SYS_STR(" %s\n"), spec->m_desc.data()); - } - return 0; + std::vector opSpecs; + auto it = m_info.args.begin(); + ++it; + for (; it != m_info.args.end(); ++it) { + hecl::SystemString itName = *it; + hecl::ToLower(itName); + for (auto& spec : specs) { + hecl::SystemString compName(spec.spec.m_name); + hecl::ToLower(compName); + if (!itName.compare(compName)) { + opSpecs.emplace_back(spec.spec.m_name); + break; } - - const auto& specs = m_info.project->getDataSpecs(); - if (mode == MLIST) - { - for (auto& spec : specs) - { - if (XTERM_COLOR) - hecl::Printf(_SYS_STR("" BOLD CYAN "%s" NORMAL ""), spec.spec.m_name.data()); - else - hecl::Printf(_SYS_STR("%s"), spec.spec.m_name.data()); - if (spec.active) - { - if (XTERM_COLOR) - hecl::Printf(_SYS_STR(" " BOLD GREEN "[ENABLED]" NORMAL "")); - else - hecl::Printf(_SYS_STR(" [ENABLED]")); - } - hecl::Printf(_SYS_STR("\n %s\n"), spec.spec.m_desc.data()); - } - return 0; - } - - std::vector opSpecs; - auto it = m_info.args.begin(); - ++it; - for (; it != m_info.args.end() ; ++it) - { - hecl::SystemString itName = *it; - hecl::ToLower(itName); - for (auto& spec : specs) - { - hecl::SystemString compName(spec.spec.m_name); - hecl::ToLower(compName); - if (!itName.compare(compName)) - { - opSpecs.emplace_back(spec.spec.m_name); - break; - } - } - } - - if (opSpecs.size()) - { - if (mode == MENABLE) - m_info.project->enableDataSpecs(opSpecs); - else if (mode == MDISABLE) - m_info.project->disableDataSpecs(opSpecs); - } - - return 0; + } } + + if (opSpecs.size()) { + if (mode == MENABLE) + m_info.project->enableDataSpecs(opSpecs); + else if (mode == MDISABLE) + m_info.project->disableDataSpecs(opSpecs); + } + + return 0; + } }; - diff --git a/hecl/driver/main.cpp b/hecl/driver/main.cpp index 8e5ceed93..b9b723999 100644 --- a/hecl/driver/main.cpp +++ b/hecl/driver/main.cpp @@ -35,7 +35,6 @@ logvisor::Module LogModule("hecl::Driver"); bool XTERM_COLOR = false; - /* #define HECL_GIT 1234567 #define HECL_GIT_S "1234567" @@ -44,49 +43,45 @@ bool XTERM_COLOR = false; */ /* Main usage message */ -static void printHelp(const hecl::SystemChar* pname) -{ - if (XTERM_COLOR) - hecl::Printf(_SYS_STR("" BOLD "HECL" NORMAL "")); - else - hecl::Printf(_SYS_STR("HECL")); +static void printHelp(const hecl::SystemChar* pname) { + if (XTERM_COLOR) + hecl::Printf(_SYS_STR("" BOLD "HECL" NORMAL "")); + else + hecl::Printf(_SYS_STR("HECL")); #if HECL_HAS_NOD -# define TOOL_LIST "extract|init|cook|package|image|help" +#define TOOL_LIST "extract|init|cook|package|image|help" #else -# define TOOL_LIST "extract|init|cook|package|help" +#define TOOL_LIST "extract|init|cook|package|help" #endif #if HECL_GIT - hecl::Printf(_SYS_STR(" Commit " HECL_GIT_S " " HECL_BRANCH_S "\nUsage: %s " TOOL_LIST "\n"), pname); + hecl::Printf(_SYS_STR(" Commit " HECL_GIT_S " " HECL_BRANCH_S "\nUsage: %s " TOOL_LIST "\n"), pname); #elif HECL_VER - hecl::Printf(_SYS_STR(" Version " HECL_VER_S "\nUsage: %s " TOOL_LIST "\n"), pname); + hecl::Printf(_SYS_STR(" Version " HECL_VER_S "\nUsage: %s " TOOL_LIST "\n"), pname); #else - hecl::Printf(_SYS_STR("\nUsage: %s " TOOL_LIST "\n"), pname); + hecl::Printf(_SYS_STR("\nUsage: %s " TOOL_LIST "\n"), pname); #endif } /* Regex patterns */ -static const hecl::SystemRegex regOPEN(_SYS_STR("-o([^\"]*|\\S*)"), std::regex::ECMAScript|std::regex::optimize); +static const hecl::SystemRegex regOPEN(_SYS_STR("-o([^\"]*|\\S*)"), std::regex::ECMAScript | std::regex::optimize); static ToolBase* ToolPtr = nullptr; /* SIGINT will gracefully close blender connections and delete blends in progress */ -static void SIGINTHandler(int sig) -{ - if (ToolPtr) - ToolPtr->cancel(); - hecl::blender::Connection::Shutdown(); - logvisor::KillProcessTree(); - exit(1); +static void SIGINTHandler(int sig) { + if (ToolPtr) + ToolPtr->cancel(); + hecl::blender::Connection::Shutdown(); + logvisor::KillProcessTree(); + exit(1); } static logvisor::Module AthenaLog("Athena"); -static void AthenaExc(athena::error::Level level, const char* file, - const char*, int line, const char* fmt, ...) -{ - va_list ap; - va_start(ap, fmt); - AthenaLog.report(logvisor::Level(level), fmt, ap); - va_end(ap); +static void AthenaExc(athena::error::Level level, const char* file, const char*, int line, const char* fmt, ...) { + va_list ap; + va_start(ap, fmt); + AthenaLog.report(logvisor::Level(level), fmt, ap); + va_end(ap); } static hecl::SystemChar cwdbuf[1024]; @@ -100,232 +95,210 @@ static void SIGWINCHHandler(int sig) {} int main(int argc, const char** argv) #endif { - if (argc > 1 && !hecl::StrCmp(argv[1], _SYS_STR("--dlpackage"))) - { - printf("%s\n", HECL_DLPACKAGE); - return 100; - } + if (argc > 1 && !hecl::StrCmp(argv[1], _SYS_STR("--dlpackage"))) { + printf("%s\n", HECL_DLPACKAGE); + return 100; + } #if _WIN32 - CoInitializeEx(nullptr, COINIT_MULTITHREADED | COINIT_DISABLE_OLE1DDE); + CoInitializeEx(nullptr, COINIT_MULTITHREADED | COINIT_DISABLE_OLE1DDE); #else - std::setlocale(LC_ALL, "en-US.UTF-8"); + std::setlocale(LC_ALL, "en-US.UTF-8"); #endif - /* Xterm check */ + /* Xterm check */ #if _WIN32 - const char* conemuANSI = getenv("ConEmuANSI"); - if (conemuANSI && !strcmp(conemuANSI, "ON")) - XTERM_COLOR = true; + const char* conemuANSI = getenv("ConEmuANSI"); + if (conemuANSI && !strcmp(conemuANSI, "ON")) + XTERM_COLOR = true; #else - const char* term = getenv("TERM"); - if (term && !strncmp(term, "xterm", 5)) - XTERM_COLOR = true; - signal(SIGWINCH, SIGWINCHHandler); + const char* term = getenv("TERM"); + if (term && !strncmp(term, "xterm", 5)) + XTERM_COLOR = true; + signal(SIGWINCH, SIGWINCHHandler); #endif - signal(SIGINT, SIGINTHandler); + signal(SIGINT, SIGINTHandler); - logvisor::RegisterStandardExceptions(); - logvisor::RegisterConsoleLogger(); - atSetExceptionHandler(AthenaExc); + logvisor::RegisterStandardExceptions(); + logvisor::RegisterConsoleLogger(); + atSetExceptionHandler(AthenaExc); - /* Basic usage check */ - if (argc == 1) - { - printHelp(argv[0]); + /* Basic usage check */ + if (argc == 1) { + printHelp(argv[0]); #if WIN_PAUSE - system("PAUSE"); + system("PAUSE"); #endif - return 0; - } - else if (argc == 0) - { - printHelp(_SYS_STR("hecl")); + return 0; + } else if (argc == 0) { + printHelp(_SYS_STR("hecl")); #if WIN_PAUSE - system("PAUSE"); + system("PAUSE"); #endif - return 0; - } + return 0; + } - /* Prepare DataSpecs */ - HECLRegisterDataSpecs(); + /* Prepare DataSpecs */ + HECLRegisterDataSpecs(); - /* Assemble common tool pass info */ - ToolPassInfo info; - info.pname = argv[0]; - if (hecl::Getcwd(cwdbuf, 1024)) - { - info.cwd = cwdbuf; - if (info.cwd.size() && info.cwd.back() != _SYS_STR('/') && info.cwd.back() != _SYS_STR('\\')) + /* Assemble common tool pass info */ + ToolPassInfo info; + info.pname = argv[0]; + if (hecl::Getcwd(cwdbuf, 1024)) { + info.cwd = cwdbuf; + if (info.cwd.size() && info.cwd.back() != _SYS_STR('/') && info.cwd.back() != _SYS_STR('\\')) #if _WIN32 - info.cwd += _SYS_STR('\\'); + info.cwd += _SYS_STR('\\'); #else - info.cwd += _SYS_STR('/'); + info.cwd += _SYS_STR('/'); #endif - if (hecl::PathRelative(argv[0])) - ExeDir = hecl::SystemString(cwdbuf) + _SYS_STR('/'); - hecl::SystemString Argv0(argv[0]); - hecl::SystemString::size_type lastIdx = Argv0.find_last_of(_SYS_STR("/\\")); - if (lastIdx != hecl::SystemString::npos) - ExeDir.insert(ExeDir.end(), Argv0.begin(), Argv0.begin() + lastIdx); + if (hecl::PathRelative(argv[0])) + ExeDir = hecl::SystemString(cwdbuf) + _SYS_STR('/'); + hecl::SystemString Argv0(argv[0]); + hecl::SystemString::size_type lastIdx = Argv0.find_last_of(_SYS_STR("/\\")); + if (lastIdx != hecl::SystemString::npos) + ExeDir.insert(ExeDir.end(), Argv0.begin(), Argv0.begin() + lastIdx); + } + + /* Concatenate args */ + std::vector args; + args.reserve(argc - 2); + for (int i = 2; i < argc; ++i) + args.push_back(hecl::SystemString(argv[i])); + + if (!args.empty()) { + /* Extract output argument */ + for (auto it = args.cbegin(); it != args.cend();) { + const hecl::SystemString& arg = *it; + hecl::SystemRegexMatch oMatch; + if (std::regex_search(arg, oMatch, regOPEN)) { + const hecl::SystemString& token = oMatch[1].str(); + if (token.size()) { + if (info.output.empty()) + info.output = oMatch[1].str(); + it = args.erase(it); + } else { + it = args.erase(it); + if (it == args.end()) + break; + if (info.output.empty()) + info.output = *it; + it = args.erase(it); + } + continue; + } + ++it; } - /* Concatenate args */ - std::vector args; - args.reserve(argc-2); - for (int i=2 ; i project; - if (rootPath) - { - size_t ErrorRef = logvisor::ErrorCount; - hecl::Database::Project* newProj = new hecl::Database::Project(rootPath); - if (logvisor::ErrorCount > ErrorRef) - { -#if WIN_PAUSE - system("PAUSE"); -#endif - delete newProj; - return 1; - } - project.reset(newProj); - info.project = newProj; - } - - /* Construct selected tool */ - hecl::SystemString toolName(argv[1]); - hecl::ToLower(toolName); - std::unique_ptr tool; - - size_t ErrorRef = logvisor::ErrorCount; - if (toolName == _SYS_STR("init")) - tool.reset(new ToolInit(info)); - else if (toolName == _SYS_STR("spec")) - tool.reset(new ToolSpec(info)); - else if (toolName == _SYS_STR("extract")) - tool.reset(new ToolExtract(info)); - else if (toolName == _SYS_STR("cook")) - tool.reset(new ToolCook(info)); - else if (toolName == _SYS_STR("package") || toolName == _SYS_STR("pack")) - tool.reset(new ToolPackage(info)); -#if HECL_HAS_NOD - else if (toolName == _SYS_STR("image")) - tool.reset(new ToolImage(info)); -#endif - else if (toolName == _SYS_STR("help")) - tool.reset(new ToolHelp(info)); - else - { - FILE* fp = hecl::Fopen(argv[1], _SYS_STR("rb")); - if (!fp) - LogModule.report(logvisor::Error, _SYS_STR("unrecognized tool '%s'"), toolName.c_str()); + for (auto chit = arg.cbegin() + 1; chit != arg.cend(); ++chit) { + if (*chit == _SYS_STR('v')) + ++info.verbosityLevel; + else if (*chit == _SYS_STR('f')) + info.force = true; + else if (*chit == _SYS_STR('y')) + info.yes = true; + else if (*chit == _SYS_STR('g')) + info.gui = true; else - { - /* Shortcut-case: implicit extract */ - fclose(fp); - info.args.insert(info.args.begin(), argv[1]); - tool.reset(new ToolExtract(info)); - } + info.flags.push_back(*chit); + } + + it = args.erase(it); } - if (logvisor::ErrorCount > ErrorRef) - { + /* Gather remaining args */ + info.args.reserve(args.size()); + for (const hecl::SystemString& arg : args) + info.args.push_back(arg); + } + + /* Attempt to find hecl project */ + hecl::ProjectRootPath rootPath = hecl::SearchForProject(info.cwd); + std::unique_ptr project; + if (rootPath) { + size_t ErrorRef = logvisor::ErrorCount; + hecl::Database::Project* newProj = new hecl::Database::Project(rootPath); + if (logvisor::ErrorCount > ErrorRef) { #if WIN_PAUSE - system("PAUSE"); + system("PAUSE"); #endif - return 1; + delete newProj; + return 1; } + project.reset(newProj); + info.project = newProj; + } - if (info.verbosityLevel) - LogModule.report(logvisor::Info, _SYS_STR("Constructed tool '%s' %d\n"), - tool->toolName().c_str(), info.verbosityLevel); + /* Construct selected tool */ + hecl::SystemString toolName(argv[1]); + hecl::ToLower(toolName); + std::unique_ptr tool; - /* Run tool */ - ErrorRef = logvisor::ErrorCount; - ToolPtr = tool.get(); - int retval = tool->run(); - ToolPtr = nullptr; - if (logvisor::ErrorCount > ErrorRef) - { - hecl::blender::Connection::Shutdown(); + size_t ErrorRef = logvisor::ErrorCount; + if (toolName == _SYS_STR("init")) + tool.reset(new ToolInit(info)); + else if (toolName == _SYS_STR("spec")) + tool.reset(new ToolSpec(info)); + else if (toolName == _SYS_STR("extract")) + tool.reset(new ToolExtract(info)); + else if (toolName == _SYS_STR("cook")) + tool.reset(new ToolCook(info)); + else if (toolName == _SYS_STR("package") || toolName == _SYS_STR("pack")) + tool.reset(new ToolPackage(info)); +#if HECL_HAS_NOD + else if (toolName == _SYS_STR("image")) + tool.reset(new ToolImage(info)); +#endif + else if (toolName == _SYS_STR("help")) + tool.reset(new ToolHelp(info)); + else { + FILE* fp = hecl::Fopen(argv[1], _SYS_STR("rb")); + if (!fp) + LogModule.report(logvisor::Error, _SYS_STR("unrecognized tool '%s'"), toolName.c_str()); + else { + /* Shortcut-case: implicit extract */ + fclose(fp); + info.args.insert(info.args.begin(), argv[1]); + tool.reset(new ToolExtract(info)); + } + } + + if (logvisor::ErrorCount > ErrorRef) { #if WIN_PAUSE - system("PAUSE"); + system("PAUSE"); #endif - return 1; - } + return 1; + } + if (info.verbosityLevel) + LogModule.report(logvisor::Info, _SYS_STR("Constructed tool '%s' %d\n"), tool->toolName().c_str(), + info.verbosityLevel); + + /* Run tool */ + ErrorRef = logvisor::ErrorCount; + ToolPtr = tool.get(); + int retval = tool->run(); + ToolPtr = nullptr; + if (logvisor::ErrorCount > ErrorRef) { hecl::blender::Connection::Shutdown(); #if WIN_PAUSE system("PAUSE"); #endif - return retval; + return 1; + } + + hecl::blender::Connection::Shutdown(); +#if WIN_PAUSE + system("PAUSE"); +#endif + return retval; } - - diff --git a/hecl/extern/athena b/hecl/extern/athena index e1b29fda7..7243c687a 160000 --- a/hecl/extern/athena +++ b/hecl/extern/athena @@ -1 +1 @@ -Subproject commit e1b29fda7acf3a17a297a02a63a5f11e94eb2328 +Subproject commit 7243c687a82eef87a4df604eae6725fae2570573 diff --git a/hecl/extern/boo b/hecl/extern/boo index 2c2c72bfd..058ea23a0 160000 --- a/hecl/extern/boo +++ b/hecl/extern/boo @@ -1 +1 @@ -Subproject commit 2c2c72bfd1e59815bfb90041974ef1e9f57325cb +Subproject commit 058ea23a00ce01ac93bf9ad369fa80858b185a00 diff --git a/hecl/include/hecl/Backend/Backend.hpp b/hecl/include/hecl/Backend/Backend.hpp index a67b0ae01..96667dbf2 100644 --- a/hecl/include/hecl/Backend/Backend.hpp +++ b/hecl/include/hecl/Backend/Backend.hpp @@ -2,8 +2,7 @@ #include "hecl/Frontend.hpp" -namespace hecl::Backend -{ +namespace hecl::Backend { struct ExtensionSlot; using IR = Frontend::IR; @@ -11,286 +10,271 @@ using Diagnostics = Frontend::Diagnostics; using SourceLocation = Frontend::SourceLocation; using ArithmeticOp = IR::Instruction::ArithmeticOpType; -enum class TexGenSrc : uint8_t -{ - Position, - Normal, - UV +enum class TexGenSrc : uint8_t { Position, Normal, UV }; + +enum class BlendFactor : uint8_t { + Zero, + One, + SrcColor, + InvSrcColor, + DstColor, + InvDstColor, + SrcAlpha, + InvSrcAlpha, + DstAlpha, + InvDstAlpha, + SrcColor1, + InvSrcColor1, + Original = 0xff }; -enum class BlendFactor : uint8_t -{ - Zero, - One, - SrcColor, - InvSrcColor, - DstColor, - InvDstColor, - SrcAlpha, - InvSrcAlpha, - DstAlpha, - InvDstAlpha, - SrcColor1, - InvSrcColor1, - Original = 0xff +enum class ZTest : uint8_t { None, LEqual, Greater, Equal, GEqual, Original = 0xff }; + +enum class CullMode : uint8_t { None, Backface, Frontface, Original = 0xff }; + +struct TextureInfo { + TexGenSrc src; + int mapIdx; + int uvIdx; + int mtxIdx; + bool normalize; }; -enum class ZTest : uint8_t -{ - None, - LEqual, - Greater, - Equal, - GEqual, - Original = 0xff -}; +enum class ReflectionType { None, Simple, Indirect }; -enum class CullMode : uint8_t -{ - None, - Backface, - Frontface, - Original = 0xff -}; - -struct TextureInfo -{ - TexGenSrc src; - int mapIdx; - int uvIdx; - int mtxIdx; - bool normalize; -}; - -enum class ReflectionType -{ - None, - Simple, - Indirect -}; - -class IBackend -{ +class IBackend { public: - virtual void reset(const IR& ir, Diagnostics& diag)=0; + virtual void reset(const IR& ir, Diagnostics& diag) = 0; }; /** * @brief Hash subclass for identifying shaders and their metadata */ -class ShaderTag : public Hash -{ - union - { - uint64_t m_meta = 0; - struct - { - uint8_t m_colorCount; - uint8_t m_uvCount; - uint8_t m_weightCount; - uint8_t m_skinSlotCount; - uint8_t m_primitiveType; - uint8_t m_reflectionType; - bool m_depthTest:1; - bool m_depthWrite:1; - bool m_backfaceCulling:1; - bool m_alphaTest:1; - }; +class ShaderTag : public Hash { + union { + uint64_t m_meta = 0; + struct { + uint8_t m_colorCount; + uint8_t m_uvCount; + uint8_t m_weightCount; + uint8_t m_skinSlotCount; + uint8_t m_primitiveType; + uint8_t m_reflectionType; + bool m_depthTest : 1; + bool m_depthWrite : 1; + bool m_backfaceCulling : 1; + bool m_alphaTest : 1; }; + }; + public: - ShaderTag() = default; - ShaderTag(std::string_view source, uint8_t c, uint8_t u, uint8_t w, uint8_t s, boo::Primitive pt, - Backend::ReflectionType reflectionType, bool depthTest, bool depthWrite, bool backfaceCulling, - bool alphaTest) - : Hash(source), m_colorCount(c), m_uvCount(u), m_weightCount(w), m_skinSlotCount(s), - m_primitiveType(uint8_t(pt)), m_reflectionType(uint8_t(reflectionType)), - m_depthTest(depthTest), m_depthWrite(depthWrite), m_backfaceCulling(backfaceCulling), - m_alphaTest(alphaTest) - {hash ^= m_meta;} - ShaderTag(const hecl::Frontend::IR& ir, uint8_t c, uint8_t u, uint8_t w, uint8_t s, boo::Primitive pt, - Backend::ReflectionType reflectionType, bool depthTest, bool depthWrite, bool backfaceCulling, - bool alphaTest) - : Hash(ir.m_hash), m_colorCount(c), m_uvCount(u), m_weightCount(w), m_skinSlotCount(s), - m_primitiveType(uint8_t(pt)), m_reflectionType(uint8_t(reflectionType)), - m_depthTest(depthTest), m_depthWrite(depthWrite), m_backfaceCulling(backfaceCulling), - m_alphaTest(alphaTest) - {hash ^= m_meta;} - ShaderTag(uint64_t hashin, uint8_t c, uint8_t u, uint8_t w, uint8_t s, boo::Primitive pt, - Backend::ReflectionType reflectionType, bool depthTest, bool depthWrite, bool backfaceCulling, - bool alphaTest) - : Hash(hashin), m_colorCount(c), m_uvCount(u), m_weightCount(w), m_skinSlotCount(s), - m_primitiveType(uint8_t(pt)), m_reflectionType(uint8_t(reflectionType)), - m_depthTest(depthTest), m_depthWrite(depthWrite), m_backfaceCulling(backfaceCulling), - m_alphaTest(alphaTest) - {hash ^= m_meta;} - ShaderTag(uint64_t comphashin, uint64_t meta) - : Hash(comphashin), m_meta(meta) {} - ShaderTag(const ShaderTag& other) : Hash(other), m_meta(other.m_meta) {} - uint8_t getColorCount() const {return m_colorCount;} - uint8_t getUvCount() const {return m_uvCount;} - uint8_t getWeightCount() const {return m_weightCount;} - uint8_t getSkinSlotCount() const {return m_skinSlotCount;} - boo::Primitive getPrimType() const {return boo::Primitive(m_primitiveType);} - Backend::ReflectionType getReflectionType() const {return Backend::ReflectionType(m_reflectionType);} - bool getDepthTest() const {return m_depthTest;} - bool getDepthWrite() const {return m_depthWrite;} - bool getBackfaceCulling() const {return m_backfaceCulling;} - bool getAlphaTest() const {return m_alphaTest;} - uint64_t getMetaData() const {return m_meta;} + ShaderTag() = default; + ShaderTag(std::string_view source, uint8_t c, uint8_t u, uint8_t w, uint8_t s, boo::Primitive pt, + Backend::ReflectionType reflectionType, bool depthTest, bool depthWrite, bool backfaceCulling, + bool alphaTest) + : Hash(source) + , m_colorCount(c) + , m_uvCount(u) + , m_weightCount(w) + , m_skinSlotCount(s) + , m_primitiveType(uint8_t(pt)) + , m_reflectionType(uint8_t(reflectionType)) + , m_depthTest(depthTest) + , m_depthWrite(depthWrite) + , m_backfaceCulling(backfaceCulling) + , m_alphaTest(alphaTest) { + hash ^= m_meta; + } + ShaderTag(const hecl::Frontend::IR& ir, uint8_t c, uint8_t u, uint8_t w, uint8_t s, boo::Primitive pt, + Backend::ReflectionType reflectionType, bool depthTest, bool depthWrite, bool backfaceCulling, + bool alphaTest) + : Hash(ir.m_hash) + , m_colorCount(c) + , m_uvCount(u) + , m_weightCount(w) + , m_skinSlotCount(s) + , m_primitiveType(uint8_t(pt)) + , m_reflectionType(uint8_t(reflectionType)) + , m_depthTest(depthTest) + , m_depthWrite(depthWrite) + , m_backfaceCulling(backfaceCulling) + , m_alphaTest(alphaTest) { + hash ^= m_meta; + } + ShaderTag(uint64_t hashin, uint8_t c, uint8_t u, uint8_t w, uint8_t s, boo::Primitive pt, + Backend::ReflectionType reflectionType, bool depthTest, bool depthWrite, bool backfaceCulling, + bool alphaTest) + : Hash(hashin) + , m_colorCount(c) + , m_uvCount(u) + , m_weightCount(w) + , m_skinSlotCount(s) + , m_primitiveType(uint8_t(pt)) + , m_reflectionType(uint8_t(reflectionType)) + , m_depthTest(depthTest) + , m_depthWrite(depthWrite) + , m_backfaceCulling(backfaceCulling) + , m_alphaTest(alphaTest) { + hash ^= m_meta; + } + ShaderTag(uint64_t comphashin, uint64_t meta) : Hash(comphashin), m_meta(meta) {} + ShaderTag(const ShaderTag& other) : Hash(other), m_meta(other.m_meta) {} + uint8_t getColorCount() const { return m_colorCount; } + uint8_t getUvCount() const { return m_uvCount; } + uint8_t getWeightCount() const { return m_weightCount; } + uint8_t getSkinSlotCount() const { return m_skinSlotCount; } + boo::Primitive getPrimType() const { return boo::Primitive(m_primitiveType); } + Backend::ReflectionType getReflectionType() const { return Backend::ReflectionType(m_reflectionType); } + bool getDepthTest() const { return m_depthTest; } + bool getDepthWrite() const { return m_depthWrite; } + bool getBackfaceCulling() const { return m_backfaceCulling; } + bool getAlphaTest() const { return m_alphaTest; } + uint64_t getMetaData() const { return m_meta; } - std::vector vertexFormat() const - { - std::vector ret; - size_t elemCount = 2 + m_colorCount + m_uvCount + m_weightCount; - ret.resize(elemCount); + std::vector vertexFormat() const { + std::vector ret; + size_t elemCount = 2 + m_colorCount + m_uvCount + m_weightCount; + ret.resize(elemCount); - ret[0].semantic = boo::VertexSemantic::Position3; - ret[1].semantic = boo::VertexSemantic::Normal3; - size_t e = 2; + ret[0].semantic = boo::VertexSemantic::Position3; + ret[1].semantic = boo::VertexSemantic::Normal3; + size_t e = 2; - for (size_t i=0 ; i blendFactors) const; + for (size_t i = 0; i < m_uvCount; ++i, ++e) { + ret[e].semantic = boo::VertexSemantic::UV2; + ret[e].semanticIdx = i; + } + + for (size_t i = 0; i < m_weightCount; ++i, ++e) { + ret[e].semantic = boo::VertexSemantic::Weight; + ret[e].semanticIdx = i; + } + + return ret; + } + + boo::AdditionalPipelineInfo additionalInfo(const ExtensionSlot& ext, + std::pair blendFactors) const; }; -struct Function -{ - std::string_view m_source; - std::string_view m_entry; - Function() = default; - Function(std::string_view source, std::string_view entry) - : m_source(source), m_entry(entry) {} +struct Function { + std::string_view m_source; + std::string_view m_entry; + Function() = default; + Function(std::string_view source, std::string_view entry) : m_source(source), m_entry(entry) {} }; -struct ExtensionSlot -{ - Function lighting; - Function post; - size_t blockCount = 0; - const char** blockNames = nullptr; - size_t texCount = 0; - const Backend::TextureInfo* texs = nullptr; - Backend::BlendFactor srcFactor = Backend::BlendFactor::Original; - Backend::BlendFactor dstFactor = Backend::BlendFactor::Original; - Backend::ZTest depthTest = Backend::ZTest::Original; - Backend::CullMode cullMode = Backend::CullMode::Backface; - bool noDepthWrite = false; - bool noColorWrite = false; - bool noAlphaWrite = false; - bool noAlphaOverwrite = false; - bool noReflection = false; - bool forceAlphaTest = false; +struct ExtensionSlot { + Function lighting; + Function post; + size_t blockCount = 0; + const char** blockNames = nullptr; + size_t texCount = 0; + const Backend::TextureInfo* texs = nullptr; + Backend::BlendFactor srcFactor = Backend::BlendFactor::Original; + Backend::BlendFactor dstFactor = Backend::BlendFactor::Original; + Backend::ZTest depthTest = Backend::ZTest::Original; + Backend::CullMode cullMode = Backend::CullMode::Backface; + bool noDepthWrite = false; + bool noColorWrite = false; + bool noAlphaWrite = false; + bool noAlphaOverwrite = false; + bool noReflection = false; + bool forceAlphaTest = false; - ExtensionSlot(size_t blockCount = 0, - const char** blockNames = nullptr, - size_t texCount = 0, - const Backend::TextureInfo* texs = nullptr, - Backend::BlendFactor srcFactor = Backend::BlendFactor::Original, - Backend::BlendFactor dstFactor = Backend::BlendFactor::Original, - Backend::ZTest depthTest = Backend::ZTest::Original, - Backend::CullMode cullMode = Backend::CullMode::Backface, - bool noDepthWrite = false, - bool noColorWrite = false, - bool noAlphaWrite = false, - bool noAlphaOverwrite = false, - bool noReflection = false, - bool forceAlphaTest = false) - : blockCount(blockCount), blockNames(blockNames), texCount(texCount), texs(texs), - srcFactor(srcFactor), dstFactor(dstFactor), depthTest(depthTest), cullMode(cullMode), - noDepthWrite(noDepthWrite), noColorWrite(noColorWrite), noAlphaWrite(noAlphaWrite), - noAlphaOverwrite(noAlphaOverwrite), noReflection(noReflection), forceAlphaTest(forceAlphaTest) {} + ExtensionSlot(size_t blockCount = 0, const char** blockNames = nullptr, size_t texCount = 0, + const Backend::TextureInfo* texs = nullptr, + Backend::BlendFactor srcFactor = Backend::BlendFactor::Original, + Backend::BlendFactor dstFactor = Backend::BlendFactor::Original, + Backend::ZTest depthTest = Backend::ZTest::Original, + Backend::CullMode cullMode = Backend::CullMode::Backface, bool noDepthWrite = false, + bool noColorWrite = false, bool noAlphaWrite = false, bool noAlphaOverwrite = false, + bool noReflection = false, bool forceAlphaTest = false) + : blockCount(blockCount) + , blockNames(blockNames) + , texCount(texCount) + , texs(texs) + , srcFactor(srcFactor) + , dstFactor(dstFactor) + , depthTest(depthTest) + , cullMode(cullMode) + , noDepthWrite(noDepthWrite) + , noColorWrite(noColorWrite) + , noAlphaWrite(noAlphaWrite) + , noAlphaOverwrite(noAlphaOverwrite) + , noReflection(noReflection) + , forceAlphaTest(forceAlphaTest) {} - mutable uint64_t m_hash = 0; - void calculateHash() const - { - XXH64_state_t st; - XXH64_reset(&st, 0); - if (!lighting.m_source.empty()) - XXH64_update(&st, lighting.m_source.data(), lighting.m_source.size()); - if (!post.m_source.empty()) - XXH64_update(&st, post.m_source.data(), post.m_source.size()); - for (size_t i = 0; i < texCount; ++i) - { - const Backend::TextureInfo& tinfo = texs[i]; - XXH64_update(&st, &tinfo, sizeof(tinfo)); - } - XXH64_update(&st, &srcFactor, offsetof(ExtensionSlot, m_hash) - offsetof(ExtensionSlot, srcFactor)); - m_hash = XXH64_digest(&st); - } - uint64_t hash() const - { - if (m_hash == 0) - calculateHash(); - return m_hash; + mutable uint64_t m_hash = 0; + void calculateHash() const { + XXH64_state_t st; + XXH64_reset(&st, 0); + if (!lighting.m_source.empty()) + XXH64_update(&st, lighting.m_source.data(), lighting.m_source.size()); + if (!post.m_source.empty()) + XXH64_update(&st, post.m_source.data(), post.m_source.size()); + for (size_t i = 0; i < texCount; ++i) { + const Backend::TextureInfo& tinfo = texs[i]; + XXH64_update(&st, &tinfo, sizeof(tinfo)); } + XXH64_update(&st, &srcFactor, offsetof(ExtensionSlot, m_hash) - offsetof(ExtensionSlot, srcFactor)); + m_hash = XXH64_digest(&st); + } + uint64_t hash() const { + if (m_hash == 0) + calculateHash(); + return m_hash; + } }; inline boo::AdditionalPipelineInfo ShaderTag::additionalInfo(const ExtensionSlot& ext, - std::pair blendFactors) const -{ - boo::ZTest zTest; - switch (ext.depthTest) - { - case hecl::Backend::ZTest::Original: - default: - zTest = getDepthTest() ? boo::ZTest::LEqual : boo::ZTest::None; - break; - case hecl::Backend::ZTest::None: - zTest = boo::ZTest::None; - break; - case hecl::Backend::ZTest::LEqual: - zTest = boo::ZTest::LEqual; - break; - case hecl::Backend::ZTest::Greater: - zTest = boo::ZTest::Greater; - break; - case hecl::Backend::ZTest::Equal: - zTest = boo::ZTest::Equal; - break; - case hecl::Backend::ZTest::GEqual: - zTest = boo::ZTest::GEqual; - break; - } + std::pair blendFactors) const { + boo::ZTest zTest; + switch (ext.depthTest) { + case hecl::Backend::ZTest::Original: + default: + zTest = getDepthTest() ? boo::ZTest::LEqual : boo::ZTest::None; + break; + case hecl::Backend::ZTest::None: + zTest = boo::ZTest::None; + break; + case hecl::Backend::ZTest::LEqual: + zTest = boo::ZTest::LEqual; + break; + case hecl::Backend::ZTest::Greater: + zTest = boo::ZTest::Greater; + break; + case hecl::Backend::ZTest::Equal: + zTest = boo::ZTest::Equal; + break; + case hecl::Backend::ZTest::GEqual: + zTest = boo::ZTest::GEqual; + break; + } - return { - boo::BlendFactor((ext.srcFactor == BlendFactor::Original) ? blendFactors.first : ext.srcFactor), - boo::BlendFactor((ext.dstFactor == BlendFactor::Original) ? blendFactors.second : ext.dstFactor), - getPrimType(), zTest, ext.noDepthWrite ? false : getDepthWrite(), - !ext.noColorWrite, !ext.noAlphaWrite, - (ext.cullMode == hecl::Backend::CullMode::Original) ? - (getBackfaceCulling() ? boo::CullMode::Backface : boo::CullMode::None) : - boo::CullMode(ext.cullMode), !ext.noAlphaOverwrite - }; + return {boo::BlendFactor((ext.srcFactor == BlendFactor::Original) ? blendFactors.first : ext.srcFactor), + boo::BlendFactor((ext.dstFactor == BlendFactor::Original) ? blendFactors.second : ext.dstFactor), + getPrimType(), + zTest, + ext.noDepthWrite ? false : getDepthWrite(), + !ext.noColorWrite, + !ext.noAlphaWrite, + (ext.cullMode == hecl::Backend::CullMode::Original) + ? (getBackfaceCulling() ? boo::CullMode::Backface : boo::CullMode::None) + : boo::CullMode(ext.cullMode), + !ext.noAlphaOverwrite}; } -} +} // namespace hecl::Backend -namespace std -{ -template <> struct hash -{ - size_t operator()(const hecl::Backend::ShaderTag& val) const noexcept - {return val.valSizeT();} +namespace std { +template <> +struct hash { + size_t operator()(const hecl::Backend::ShaderTag& val) const noexcept { return val.valSizeT(); } }; -} - +} // namespace std diff --git a/hecl/include/hecl/Backend/GLSL.hpp b/hecl/include/hecl/Backend/GLSL.hpp index 1b09713c3..b29b94ed3 100644 --- a/hecl/include/hecl/Backend/GLSL.hpp +++ b/hecl/include/hecl/Backend/GLSL.hpp @@ -2,51 +2,39 @@ #include "ProgrammableCommon.hpp" -namespace hecl::Backend -{ +namespace hecl::Backend { #define HECL_GLSL_VERT_UNIFORM_BLOCK_NAME "HECLVertUniform" #define HECL_GLSL_TEXMTX_UNIFORM_BLOCK_NAME "HECLTexMtxUniform" -struct GLSL : ProgrammableCommon -{ - void reset(const IR& ir, Diagnostics& diag); - std::string makeVert(unsigned col, unsigned uv, unsigned w, - unsigned skinSlots, size_t extTexCount, - const TextureInfo* extTexs, ReflectionType reflectionType) const; - std::string makeFrag(size_t blockCount, const char** blockNames, - bool alphaTest, ReflectionType reflectionType, - BlendFactor srcFactor, BlendFactor dstFactor, - const Function& lighting=Function()) const; - std::string makeFrag(size_t blockCount, const char** blockNames, - bool alphaTest, - ReflectionType reflectionType, - BlendFactor srcFactor, BlendFactor dstFactor, - const Function& lighting, - const Function& post, - size_t extTexCount, const TextureInfo* extTexs) const; +struct GLSL : ProgrammableCommon { + void reset(const IR& ir, Diagnostics& diag); + std::string makeVert(unsigned col, unsigned uv, unsigned w, unsigned skinSlots, size_t extTexCount, + const TextureInfo* extTexs, ReflectionType reflectionType) const; + std::string makeFrag(size_t blockCount, const char** blockNames, bool alphaTest, ReflectionType reflectionType, + BlendFactor srcFactor, BlendFactor dstFactor, const Function& lighting = Function()) const; + std::string makeFrag(size_t blockCount, const char** blockNames, bool alphaTest, ReflectionType reflectionType, + BlendFactor srcFactor, BlendFactor dstFactor, const Function& lighting, const Function& post, + size_t extTexCount, const TextureInfo* extTexs) const; private: - std::string GenerateVertInStruct(unsigned col, unsigned uv, unsigned w) const; - std::string GenerateVertToFragStruct(size_t extTexCount, bool reflectionCoords) const; - std::string GenerateVertUniformStruct(unsigned skinSlots, bool reflectionCoords) const; - std::string GenerateAlphaTest() const; - std::string GenerateReflectionExpr(ReflectionType type) const; + std::string GenerateVertInStruct(unsigned col, unsigned uv, unsigned w) const; + std::string GenerateVertToFragStruct(size_t extTexCount, bool reflectionCoords) const; + std::string GenerateVertUniformStruct(unsigned skinSlots, bool reflectionCoords) const; + std::string GenerateAlphaTest() const; + std::string GenerateReflectionExpr(ReflectionType type) const; - std::string EmitVec3(const atVec4f& vec) const - { - athena::simd_floats f(vec.simd); - return hecl::Format("vec3(%g,%g,%g)", f[0], f[1], f[2]); - } + std::string EmitVec3(const atVec4f& vec) const { + athena::simd_floats f(vec.simd); + return hecl::Format("vec3(%g,%g,%g)", f[0], f[1], f[2]); + } - std::string EmitVec3(const std::string& a, const std::string& b, const std::string& c) const - { - return hecl::Format("vec3(%s,%s,%s)", a.c_str(), b.c_str(), c.c_str()); - } + std::string EmitVec3(const std::string& a, const std::string& b, const std::string& c) const { + return hecl::Format("vec3(%s,%s,%s)", a.c_str(), b.c_str(), c.c_str()); + } - std::string EmitTexGenSource2(TexGenSrc src, int uvIdx) const; - std::string EmitTexGenSource4(TexGenSrc src, int uvIdx) const; + std::string EmitTexGenSource2(TexGenSrc src, int uvIdx) const; + std::string EmitTexGenSource4(TexGenSrc src, int uvIdx) const; }; -} - +} // namespace hecl::Backend diff --git a/hecl/include/hecl/Backend/GX.hpp b/hecl/include/hecl/Backend/GX.hpp index 22ad95ccd..1fa294bf9 100644 --- a/hecl/include/hecl/Backend/GX.hpp +++ b/hecl/include/hecl/Backend/GX.hpp @@ -9,588 +9,505 @@ #undef min #undef max -namespace hecl::Backend -{ +namespace hecl::Backend { -struct GX final : IBackend -{ - enum AttrType - { - NONE, - DIRECT, - INDEX8, - INDEX16 - }; +struct GX final : IBackend { + enum AttrType { NONE, DIRECT, INDEX8, INDEX16 }; - enum TevOp - { - TEV_ADD = 0, - TEV_SUB = 1, - TEV_COMP_R8_GT = 8, - TEV_COMP_R8_EQ = 9, - TEV_COMP_GR16_GT = 10, - TEV_COMP_GR16_EQ = 11, - TEV_COMP_BGR24_GT = 12, - TEV_COMP_BGR24_EQ = 13, - TEV_COMP_RGB8_GT = 14, - TEV_COMP_RGB8_EQ = 15, - TEV_COMP_A8_GT = TEV_COMP_RGB8_GT, // for alpha channel - TEV_COMP_A8_EQ = TEV_COMP_RGB8_EQ // for alpha channel - }; + enum TevOp { + TEV_ADD = 0, + TEV_SUB = 1, + TEV_COMP_R8_GT = 8, + TEV_COMP_R8_EQ = 9, + TEV_COMP_GR16_GT = 10, + TEV_COMP_GR16_EQ = 11, + TEV_COMP_BGR24_GT = 12, + TEV_COMP_BGR24_EQ = 13, + TEV_COMP_RGB8_GT = 14, + TEV_COMP_RGB8_EQ = 15, + TEV_COMP_A8_GT = TEV_COMP_RGB8_GT, // for alpha channel + TEV_COMP_A8_EQ = TEV_COMP_RGB8_EQ // for alpha channel + }; - enum TevBias - { - TB_ZERO = 0, - TB_ADDHALF = 1, - TB_SUBHALF = 2, - }; + enum TevBias { + TB_ZERO = 0, + TB_ADDHALF = 1, + TB_SUBHALF = 2, + }; - enum TevScale - { - CS_SCALE_1 = 0, - CS_SCALE_2 = 1, - CS_SCALE_4 = 2, - CS_DIVIDE_2 = 3 - }; + enum TevScale { CS_SCALE_1 = 0, CS_SCALE_2 = 1, CS_SCALE_4 = 2, CS_DIVIDE_2 = 3 }; - enum TexGenType - { - TG_MTX3x4 = 0, - TG_MTX2x4, - TG_BUMP0, - TG_BUMP1, - TG_BUMP2, - TG_BUMP3, - TG_BUMP4, - TG_BUMP5, - TG_BUMP6, - TG_BUMP7, - TG_SRTG - }; + enum TexGenType { + TG_MTX3x4 = 0, + TG_MTX2x4, + TG_BUMP0, + TG_BUMP1, + TG_BUMP2, + TG_BUMP3, + TG_BUMP4, + TG_BUMP5, + TG_BUMP6, + TG_BUMP7, + TG_SRTG + }; - enum TevRegID - { - TEVPREV = 0, - TEVREG0 = 1, - TEVREG1 = 2, - TEVREG2 = 3, - TEVLAZY = 5 - }; + enum TevRegID { TEVPREV = 0, TEVREG0 = 1, TEVREG1 = 2, TEVREG2 = 3, TEVLAZY = 5 }; - enum TevColorArg - { - CC_CPREV = 0, /*!< Use the color value from previous TEV stage */ - CC_APREV = 1, /*!< Use the alpha value from previous TEV stage */ - CC_C0 = 2, /*!< Use the color value from the color/output register 0 */ - CC_A0 = 3, /*!< Use the alpha value from the color/output register 0 */ - CC_C1 = 4, /*!< Use the color value from the color/output register 1 */ - CC_A1 = 5, /*!< Use the alpha value from the color/output register 1 */ - CC_C2 = 6, /*!< Use the color value from the color/output register 2 */ - CC_A2 = 7, /*!< Use the alpha value from the color/output register 2 */ - CC_TEXC = 8, /*!< Use the color value from texture */ - CC_TEXA = 9, /*!< Use the alpha value from texture */ - CC_RASC = 10, /*!< Use the color value from rasterizer */ - CC_RASA = 11, /*!< Use the alpha value from rasterizer */ - CC_ONE = 12, - CC_HALF = 13, - CC_KONST = 14, - CC_ZERO = 15, /*!< Use to pass zero value */ + enum TevColorArg { + CC_CPREV = 0, /*!< Use the color value from previous TEV stage */ + CC_APREV = 1, /*!< Use the alpha value from previous TEV stage */ + CC_C0 = 2, /*!< Use the color value from the color/output register 0 */ + CC_A0 = 3, /*!< Use the alpha value from the color/output register 0 */ + CC_C1 = 4, /*!< Use the color value from the color/output register 1 */ + CC_A1 = 5, /*!< Use the alpha value from the color/output register 1 */ + CC_C2 = 6, /*!< Use the color value from the color/output register 2 */ + CC_A2 = 7, /*!< Use the alpha value from the color/output register 2 */ + CC_TEXC = 8, /*!< Use the color value from texture */ + CC_TEXA = 9, /*!< Use the alpha value from texture */ + CC_RASC = 10, /*!< Use the color value from rasterizer */ + CC_RASA = 11, /*!< Use the alpha value from rasterizer */ + CC_ONE = 12, + CC_HALF = 13, + CC_KONST = 14, + CC_ZERO = 15, /*!< Use to pass zero value */ - /* Non-GX */ - CC_LAZY /*!< Lazy register allocation */ - }; + /* Non-GX */ + CC_LAZY /*!< Lazy register allocation */ + }; - enum TevAlphaArg - { - CA_APREV = 0, /*!< Use the alpha value from previous TEV stage */ - CA_A0 = 1, /*!< Use the alpha value from the color/output register 0 */ - CA_A1 = 2, /*!< Use the alpha value from the color/output register 1 */ - CA_A2 = 3, /*!< Use the alpha value from the color/output register 2 */ - CA_TEXA = 4, /*!< Use the alpha value from texture */ - CA_RASA = 5, /*!< Use the alpha value from rasterizer */ - CA_KONST = 6, - CA_ZERO = 7, /*!< Use to pass zero value */ + enum TevAlphaArg { + CA_APREV = 0, /*!< Use the alpha value from previous TEV stage */ + CA_A0 = 1, /*!< Use the alpha value from the color/output register 0 */ + CA_A1 = 2, /*!< Use the alpha value from the color/output register 1 */ + CA_A2 = 3, /*!< Use the alpha value from the color/output register 2 */ + CA_TEXA = 4, /*!< Use the alpha value from texture */ + CA_RASA = 5, /*!< Use the alpha value from rasterizer */ + CA_KONST = 6, + CA_ZERO = 7, /*!< Use to pass zero value */ - /* Non-GX */ - CA_LAZY /*!< Lazy register allocation */ - }; + /* Non-GX */ + CA_LAZY /*!< Lazy register allocation */ + }; - enum TevKColorSel - { - TEV_KCSEL_8_8 = 0x00, - TEV_KCSEL_7_8 = 0x01, - TEV_KCSEL_6_8 = 0x02, - TEV_KCSEL_5_8 = 0x03, - TEV_KCSEL_4_8 = 0x04, - TEV_KCSEL_3_8 = 0x05, - TEV_KCSEL_2_8 = 0x06, - TEV_KCSEL_1_8 = 0x07, + enum TevKColorSel { + TEV_KCSEL_8_8 = 0x00, + TEV_KCSEL_7_8 = 0x01, + TEV_KCSEL_6_8 = 0x02, + TEV_KCSEL_5_8 = 0x03, + TEV_KCSEL_4_8 = 0x04, + TEV_KCSEL_3_8 = 0x05, + TEV_KCSEL_2_8 = 0x06, + TEV_KCSEL_1_8 = 0x07, - TEV_KCSEL_1 = TEV_KCSEL_8_8, - TEV_KCSEL_3_4 = TEV_KCSEL_6_8, - TEV_KCSEL_1_2 = TEV_KCSEL_4_8, - TEV_KCSEL_1_4 = TEV_KCSEL_2_8, + TEV_KCSEL_1 = TEV_KCSEL_8_8, + TEV_KCSEL_3_4 = TEV_KCSEL_6_8, + TEV_KCSEL_1_2 = TEV_KCSEL_4_8, + TEV_KCSEL_1_4 = TEV_KCSEL_2_8, - TEV_KCSEL_K0 = 0x0C, - TEV_KCSEL_K1 = 0x0D, - TEV_KCSEL_K2 = 0x0E, - TEV_KCSEL_K3 = 0x0F, - TEV_KCSEL_K0_R = 0x10, - TEV_KCSEL_K1_R = 0x11, - TEV_KCSEL_K2_R = 0x12, - TEV_KCSEL_K3_R = 0x13, - TEV_KCSEL_K0_G = 0x14, - TEV_KCSEL_K1_G = 0x15, - TEV_KCSEL_K2_G = 0x16, - TEV_KCSEL_K3_G = 0x17, - TEV_KCSEL_K0_B = 0x18, - TEV_KCSEL_K1_B = 0x19, - TEV_KCSEL_K2_B = 0x1A, - TEV_KCSEL_K3_B = 0x1B, - TEV_KCSEL_K0_A = 0x1C, - TEV_KCSEL_K1_A = 0x1D, - TEV_KCSEL_K2_A = 0x1E, - TEV_KCSEL_K3_A = 0x1F - }; + TEV_KCSEL_K0 = 0x0C, + TEV_KCSEL_K1 = 0x0D, + TEV_KCSEL_K2 = 0x0E, + TEV_KCSEL_K3 = 0x0F, + TEV_KCSEL_K0_R = 0x10, + TEV_KCSEL_K1_R = 0x11, + TEV_KCSEL_K2_R = 0x12, + TEV_KCSEL_K3_R = 0x13, + TEV_KCSEL_K0_G = 0x14, + TEV_KCSEL_K1_G = 0x15, + TEV_KCSEL_K2_G = 0x16, + TEV_KCSEL_K3_G = 0x17, + TEV_KCSEL_K0_B = 0x18, + TEV_KCSEL_K1_B = 0x19, + TEV_KCSEL_K2_B = 0x1A, + TEV_KCSEL_K3_B = 0x1B, + TEV_KCSEL_K0_A = 0x1C, + TEV_KCSEL_K1_A = 0x1D, + TEV_KCSEL_K2_A = 0x1E, + TEV_KCSEL_K3_A = 0x1F + }; - enum TevKAlphaSel - { - TEV_KASEL_8_8 = 0x00, - TEV_KASEL_7_8 = 0x01, - TEV_KASEL_6_8 = 0x02, - TEV_KASEL_5_8 = 0x03, - TEV_KASEL_4_8 = 0x04, - TEV_KASEL_3_8 = 0x05, - TEV_KASEL_2_8 = 0x06, - TEV_KASEL_1_8 = 0x07, + enum TevKAlphaSel { + TEV_KASEL_8_8 = 0x00, + TEV_KASEL_7_8 = 0x01, + TEV_KASEL_6_8 = 0x02, + TEV_KASEL_5_8 = 0x03, + TEV_KASEL_4_8 = 0x04, + TEV_KASEL_3_8 = 0x05, + TEV_KASEL_2_8 = 0x06, + TEV_KASEL_1_8 = 0x07, - TEV_KASEL_1 = TEV_KASEL_8_8, - TEV_KASEL_3_4 = TEV_KASEL_6_8, - TEV_KASEL_1_2 = TEV_KASEL_4_8, - TEV_KASEL_1_4 = TEV_KASEL_2_8, + TEV_KASEL_1 = TEV_KASEL_8_8, + TEV_KASEL_3_4 = TEV_KASEL_6_8, + TEV_KASEL_1_2 = TEV_KASEL_4_8, + TEV_KASEL_1_4 = TEV_KASEL_2_8, - TEV_KASEL_K0_R = 0x10, - TEV_KASEL_K1_R = 0x11, - TEV_KASEL_K2_R = 0x12, - TEV_KASEL_K3_R = 0x13, - TEV_KASEL_K0_G = 0x14, - TEV_KASEL_K1_G = 0x15, - TEV_KASEL_K2_G = 0x16, - TEV_KASEL_K3_G = 0x17, - TEV_KASEL_K0_B = 0x18, - TEV_KASEL_K1_B = 0x19, - TEV_KASEL_K2_B = 0x1A, - TEV_KASEL_K3_B = 0x1B, - TEV_KASEL_K0_A = 0x1C, - TEV_KASEL_K1_A = 0x1D, - TEV_KASEL_K2_A = 0x1E, - TEV_KASEL_K3_A = 0x1F - }; + TEV_KASEL_K0_R = 0x10, + TEV_KASEL_K1_R = 0x11, + TEV_KASEL_K2_R = 0x12, + TEV_KASEL_K3_R = 0x13, + TEV_KASEL_K0_G = 0x14, + TEV_KASEL_K1_G = 0x15, + TEV_KASEL_K2_G = 0x16, + TEV_KASEL_K3_G = 0x17, + TEV_KASEL_K0_B = 0x18, + TEV_KASEL_K1_B = 0x19, + TEV_KASEL_K2_B = 0x1A, + TEV_KASEL_K3_B = 0x1B, + TEV_KASEL_K0_A = 0x1C, + TEV_KASEL_K1_A = 0x1D, + TEV_KASEL_K2_A = 0x1E, + TEV_KASEL_K3_A = 0x1F + }; - enum ChannelID - { - GX_COLOR0, - GX_COLOR1, - GX_ALPHA0, - GX_ALPHA1, - GX_COLOR0A0, - GX_COLOR1A1, - GX_COLOR_ZERO, - GX_ALPHA_BUMP, - GX_ALPHA_BUMPN, - GX_COLOR_NULL = 0xff - }; + enum ChannelID { + GX_COLOR0, + GX_COLOR1, + GX_ALPHA0, + GX_ALPHA1, + GX_COLOR0A0, + GX_COLOR1A1, + GX_COLOR_ZERO, + GX_ALPHA_BUMP, + GX_ALPHA_BUMPN, + GX_COLOR_NULL = 0xff + }; - enum TexGenSrc - { - TG_POS = 0, - TG_NRM, - TG_BINRM, - TG_TANGENT, - TG_TEX0, - TG_TEX1, - TG_TEX2, - TG_TEX3, - TG_TEX4, - TG_TEX5, - TG_TEX6, - TG_TEX7, - TG_TEXCOORD0, - TG_TEXCOORD1, - TG_TEXCOORD2, - TG_TEXCOORD3, - TG_TEXCOORD4, - TG_TEXCOORD5, - TG_TEXCOORD6, - TG_COLOR0, - TG_COLOR1 - }; + enum TexGenSrc { + TG_POS = 0, + TG_NRM, + TG_BINRM, + TG_TANGENT, + TG_TEX0, + TG_TEX1, + TG_TEX2, + TG_TEX3, + TG_TEX4, + TG_TEX5, + TG_TEX6, + TG_TEX7, + TG_TEXCOORD0, + TG_TEXCOORD1, + TG_TEXCOORD2, + TG_TEXCOORD3, + TG_TEXCOORD4, + TG_TEXCOORD5, + TG_TEXCOORD6, + TG_COLOR0, + TG_COLOR1 + }; - enum TexMtx - { - TEXMTX0 = 30, - TEXMTX1 = 33, - TEXMTX2 = 36, - TEXMTX3 = 39, - TEXMTX4 = 42, - TEXMTX5 = 45, - TEXMTX6 = 48, - TEXMTX7 = 51, - TEXMTX8 = 54, - TEXMTX9 = 57, - IDENTITY = 60 - }; + enum TexMtx { + TEXMTX0 = 30, + TEXMTX1 = 33, + TEXMTX2 = 36, + TEXMTX3 = 39, + TEXMTX4 = 42, + TEXMTX5 = 45, + TEXMTX6 = 48, + TEXMTX7 = 51, + TEXMTX8 = 54, + TEXMTX9 = 57, + IDENTITY = 60 + }; - enum PTTexMtx - { - PTTEXMTX0 = 64, - PTTEXMTX1 = 67, - PTTEXMTX2 = 70, - PTTEXMTX3 = 73, - PTTEXMTX4 = 76, - PTTEXMTX5 = 79, - PTTEXMTX6 = 82, - PTTEXMTX7 = 85, - PTTEXMTX8 = 88, - PTTEXMTX9 = 91, - PTTEXMTX10 = 94, - PTTEXMTX11 = 97, - PTTEXMTX12 = 100, - PTTEXMTX13 = 103, - PTTEXMTX14 = 106, - PTTEXMTX15 = 109, - PTTEXMTX16 = 112, - PTTEXMTX17 = 115, - PTTEXMTX18 = 118, - PTTEXMTX19 = 121, - PTIDENTITY = 125 - }; + enum PTTexMtx { + PTTEXMTX0 = 64, + PTTEXMTX1 = 67, + PTTEXMTX2 = 70, + PTTEXMTX3 = 73, + PTTEXMTX4 = 76, + PTTEXMTX5 = 79, + PTTEXMTX6 = 82, + PTTEXMTX7 = 85, + PTTEXMTX8 = 88, + PTTEXMTX9 = 91, + PTTEXMTX10 = 94, + PTTEXMTX11 = 97, + PTTEXMTX12 = 100, + PTTEXMTX13 = 103, + PTTEXMTX14 = 106, + PTTEXMTX15 = 109, + PTTEXMTX16 = 112, + PTTEXMTX17 = 115, + PTTEXMTX18 = 118, + PTTEXMTX19 = 121, + PTIDENTITY = 125 + }; - enum DiffuseFn - { - DF_NONE = 0, - DF_SIGN, - DF_CLAMP - }; + enum DiffuseFn { DF_NONE = 0, DF_SIGN, DF_CLAMP }; - enum AttnFn - { - AF_SPEC = 0, - AF_SPOT = 1, - AF_NONE - }; + enum AttnFn { AF_SPEC = 0, AF_SPOT = 1, AF_NONE }; - enum Primitive - { - POINTS = 0xb8, - LINES = 0xa8, - LINESTRIP = 0xb0, - TRIANGLES = 0x90, - TRIANGLESTRIP = 0x98, - TRIANGLEFAN = 0xa0, - QUADS = 0x80 - }; + enum Primitive { + POINTS = 0xb8, + LINES = 0xa8, + LINESTRIP = 0xb0, + TRIANGLES = 0x90, + TRIANGLESTRIP = 0x98, + TRIANGLEFAN = 0xa0, + QUADS = 0x80 + }; - struct TexCoordGen - { - TexGenSrc m_src = TG_TEX0; - TexMtx m_mtx = IDENTITY; - bool m_norm = false; - PTTexMtx m_pmtx = PTIDENTITY; + struct TexCoordGen { + TexGenSrc m_src = TG_TEX0; + TexMtx m_mtx = IDENTITY; + bool m_norm = false; + PTTexMtx m_pmtx = PTIDENTITY; - /* Not actually part of GX, but a way to relate out-of-band - * texmtx animation parameters */ - std::string m_gameFunction; - std::vector m_gameArgs; - }; - unsigned m_tcgCount = 0; - TexCoordGen m_tcgs[8]; + /* Not actually part of GX, but a way to relate out-of-band + * texmtx animation parameters */ + std::string m_gameFunction; + std::vector m_gameArgs; + }; + unsigned m_tcgCount = 0; + TexCoordGen m_tcgs[8]; - unsigned m_texMtxCount = 0; - TexCoordGen* m_texMtxRefs[8]; + unsigned m_texMtxCount = 0; + TexCoordGen* m_texMtxRefs[8]; - struct TEVStage - { - TevOp m_cop = TEV_ADD; - TevOp m_aop = TEV_ADD; - TevColorArg m_color[4] = {CC_ZERO, CC_ZERO, CC_ZERO, CC_ZERO}; - TevAlphaArg m_alpha[4] = {CA_ZERO, CA_ZERO, CA_ZERO, CA_ZERO}; - TevKColorSel m_kColor = TEV_KCSEL_1; - TevKAlphaSel m_kAlpha = TEV_KASEL_1; - TevRegID m_cRegOut = TEVPREV; - TevRegID m_aRegOut = TEVPREV; - int m_lazyCInIdx = -1; - int m_lazyAInIdx = -1; - int m_lazyCOutIdx = -1; - int m_lazyAOutIdx = -1; - int m_texMapIdx = -1; - int m_texGenIdx = -1; + struct TEVStage { + TevOp m_cop = TEV_ADD; + TevOp m_aop = TEV_ADD; + TevColorArg m_color[4] = {CC_ZERO, CC_ZERO, CC_ZERO, CC_ZERO}; + TevAlphaArg m_alpha[4] = {CA_ZERO, CA_ZERO, CA_ZERO, CA_ZERO}; + TevKColorSel m_kColor = TEV_KCSEL_1; + TevKAlphaSel m_kAlpha = TEV_KASEL_1; + TevRegID m_cRegOut = TEVPREV; + TevRegID m_aRegOut = TEVPREV; + int m_lazyCInIdx = -1; + int m_lazyAInIdx = -1; + int m_lazyCOutIdx = -1; + int m_lazyAOutIdx = -1; + int m_texMapIdx = -1; + int m_texGenIdx = -1; - /* Convenience Links */ - TEVStage* m_prev = nullptr; - TEVStage* m_next = nullptr; + /* Convenience Links */ + TEVStage* m_prev = nullptr; + TEVStage* m_next = nullptr; - /* Remember this for debugging */ - SourceLocation m_loc; - }; - unsigned m_tevCount = 0; - TEVStage m_tevs[16]; + /* Remember this for debugging */ + SourceLocation m_loc; + }; + unsigned m_tevCount = 0; + TEVStage m_tevs[16]; - int getStageIdx(const TEVStage* stage) const - { - for (int i=0 ; i= 0; --i) + if (!(regMask & (1 << i))) + return i; - int m_aRegMask = 0; - int m_aRegLazy = 0; + diag.reportBackendErr(loc, "TEV C Register overflow"); + return -1; + } - int pickCLazy(Diagnostics& diag, const SourceLocation& loc, int stageIdx) const - { - int regMask = m_cRegMask; - for (int i=stageIdx+1 ; i=0 ; --i) - if (!(regMask & (1 << i))) - return i; - - diag.reportBackendErr(loc, "TEV C Register overflow"); - return -1; + int pickALazy(Diagnostics& diag, const SourceLocation& loc, int stageIdx) const { + int regMask = m_aRegMask; + for (int i = stageIdx + 1; i < int(m_tevCount); ++i) { + const TEVStage& stage = m_tevs[i]; + for (int c = 0; c < 4; ++c) { + if (stage.m_color[c] == CC_A0 || stage.m_alpha[c] == CA_A0) + regMask |= 1; + if (stage.m_color[c] == CC_A1 || stage.m_alpha[c] == CA_A1) + regMask |= 2; + if (stage.m_color[c] == CC_A2 || stage.m_alpha[c] == CA_A2) + regMask |= 4; + } } - int pickALazy(Diagnostics& diag, const SourceLocation& loc, int stageIdx) const - { - int regMask = m_aRegMask; - for (int i=stageIdx+1 ; i= 0; --i) + if (!(regMask & (1 << i))) + return i; - /* Allocate from back for compatibility with Retro's - * extended shader arithmetic use */ - for (int i=2 ; i>=0 ; --i) - if (!(regMask & (1 << i))) - return i; + diag.reportBackendErr(loc, "TEV A Register overflow"); + return -1; + } - diag.reportBackendErr(loc, "TEV A Register overflow"); - return -1; - } + enum BlendFactor : uint16_t { + BL_ZERO, + BL_ONE, + BL_SRCCLR, + BL_INVSRCCLR, + BL_SRCALPHA, + BL_INVSRCALPHA, + BL_DSTALPHA, + BL_INVDSTALPHA + }; + BlendFactor m_blendSrc; + BlendFactor m_blendDst; - enum BlendFactor : uint16_t - { - BL_ZERO, - BL_ONE, - BL_SRCCLR, - BL_INVSRCCLR, - BL_SRCALPHA, - BL_INVSRCALPHA, - BL_DSTALPHA, - BL_INVDSTALPHA + struct Color : athena::io::DNA { + union { + uint8_t color[4]; + uint32_t num = 0; }; - BlendFactor m_blendSrc; - BlendFactor m_blendDst; - - struct Color : athena::io::DNA - { - union - { - uint8_t color[4]; - uint32_t num = 0; - }; - Color() = default; - Color& operator=(const atVec4f& vec) - { - athena::simd_floats f(vec.simd); - color[0] = uint8_t(std::min(std::max(f[0] * 255.f, 0.f), 255.f)); - color[1] = uint8_t(std::min(std::max(f[1] * 255.f, 0.f), 255.f)); - color[2] = uint8_t(std::min(std::max(f[2] * 255.f, 0.f), 255.f)); - color[3] = uint8_t(std::min(std::max(f[3] * 255.f, 0.f), 255.f)); - return *this; - } - Color& operator=(const atVec3f& vec) - { - athena::simd_floats f(vec.simd); - color[0] = uint8_t(std::min(std::max(f[0] * 255.f, 0.f), 255.f)); - color[1] = uint8_t(std::min(std::max(f[1] * 255.f, 0.f), 255.f)); - color[2] = uint8_t(std::min(std::max(f[2] * 255.f, 0.f), 255.f)); - color[3] = 0xff; - return *this; - } - Color& operator=(uint8_t val) - { - color[0] = val; - color[1] = val; - color[2] = val; - color[3] = val; - return *this; - } - atVec4f toVec4f() const - { - atVec4f out; - athena::simd_floats f; - f[0] = color[0] / 255.f; - f[1] = color[1] / 255.f; - f[2] = color[2] / 255.f; - f[3] = color[3] / 255.f; - out.simd.copy_from(f); - return out; - } - Color(const atVec4f& vec) {*this = vec;} - Color(const atVec3f& vec) {*this = vec;} - Color(uint8_t val) {*this = val;} - bool operator==(const Color& other) const {return num == other.num;} - bool operator!=(const Color& other) const {return num != other.num;} - uint8_t operator[](size_t idx) const {return color[idx];} - uint8_t& operator[](size_t idx) {return color[idx];} - AT_DECL_EXPLICIT_DNA - }; - unsigned m_kcolorCount = 0; - Color m_kcolors[4]; - - int m_alphaTraceStage = -1; - - bool operator==(const GX& other) const - { - if (m_tcgCount != other.m_tcgCount) - return false; - if (m_tevCount != other.m_tevCount) - return false; - if (m_blendSrc != other.m_blendSrc) - return false; - if (m_blendDst != other.m_blendDst) - return false; - if (m_kcolorCount != other.m_kcolorCount) - return false; - for (unsigned i=0 ; i #include -namespace hecl::Backend -{ +namespace hecl::Backend { -struct ProgrammableCommon : IBackend -{ - std::string m_colorExpr; - std::string m_alphaExpr; - BlendFactor m_blendSrc; - BlendFactor m_blendDst; - bool m_lighting = false; +struct ProgrammableCommon : IBackend { + std::string m_colorExpr; + std::string m_alphaExpr; + BlendFactor m_blendSrc; + BlendFactor m_blendDst; + bool m_lighting = false; - struct TexSampling - { - int mapIdx = -1; - int tcgIdx = -1; - }; - std::vector m_texSamplings; - unsigned m_texMapEnd = 0; - unsigned m_extMapStart = 8; + struct TexSampling { + int mapIdx = -1; + int tcgIdx = -1; + }; + std::vector m_texSamplings; + unsigned m_texMapEnd = 0; + unsigned m_extMapStart = 8; - struct TexCoordGen - { - TexGenSrc m_src; - int m_uvIdx = 0; - int m_mtx = -1; - bool m_norm = false; - std::string m_gameFunction; - std::vector m_gameArgs; - }; - std::vector m_tcgs; - std::vector m_texMtxRefs; + struct TexCoordGen { + TexGenSrc m_src; + int m_uvIdx = 0; + int m_mtx = -1; + bool m_norm = false; + std::string m_gameFunction; + std::vector m_gameArgs; + }; + std::vector m_tcgs; + std::vector m_texMtxRefs; - using IBackend::reset; - void reset(const IR& ir, Diagnostics& diag, const char* backendName); + using IBackend::reset; + void reset(const IR& ir, Diagnostics& diag, const char* backendName); - static const char* BlendFactorToDefine(BlendFactor factor, BlendFactor defaultFactor); + static const char* BlendFactorToDefine(BlendFactor factor, BlendFactor defaultFactor); private: - unsigned addTexCoordGen(TexGenSrc src, int uvIdx, int mtx, bool normalize); - unsigned addTexSampling(unsigned mapIdx, unsigned tcgIdx); - std::string RecursiveTraceColor(const IR& ir, Diagnostics& diag, - const IR::Instruction& inst, bool toSwizzle); - std::string RecursiveTraceAlpha(const IR& ir, Diagnostics& diag, - const IR::Instruction& inst, bool toSwizzle); - unsigned RecursiveTraceTexGen(const IR& ir, Diagnostics& diag, - const IR::Instruction& inst, - int mtx, bool normalize); + unsigned addTexCoordGen(TexGenSrc src, int uvIdx, int mtx, bool normalize); + unsigned addTexSampling(unsigned mapIdx, unsigned tcgIdx); + std::string RecursiveTraceColor(const IR& ir, Diagnostics& diag, const IR::Instruction& inst, bool toSwizzle); + std::string RecursiveTraceAlpha(const IR& ir, Diagnostics& diag, const IR::Instruction& inst, bool toSwizzle); + unsigned RecursiveTraceTexGen(const IR& ir, Diagnostics& diag, const IR::Instruction& inst, int mtx, bool normalize); - std::string EmitSamplingUseRaw(unsigned samplingIdx) const - { - return hecl::Format("sampling%u", samplingIdx); - } + std::string EmitSamplingUseRaw(unsigned samplingIdx) const { return hecl::Format("sampling%u", samplingIdx); } - std::string EmitSamplingUseRGB(unsigned samplingIdx) const - { - return hecl::Format("sampling%u.rgb", samplingIdx); - } + std::string EmitSamplingUseRGB(unsigned samplingIdx) const { return hecl::Format("sampling%u.rgb", samplingIdx); } - std::string EmitSamplingUseAlpha(unsigned samplingIdx) const - { - return hecl::Format("sampling%u.a", samplingIdx); - } + std::string EmitSamplingUseAlpha(unsigned samplingIdx) const { return hecl::Format("sampling%u.a", samplingIdx); } - std::string EmitColorRegUseRaw(unsigned idx) const - { - return hecl::Format("colorReg%u", idx); - } + std::string EmitColorRegUseRaw(unsigned idx) const { return hecl::Format("colorReg%u", idx); } - std::string EmitColorRegUseRGB(unsigned idx) const - { - return hecl::Format("colorReg%u.rgb", idx); - } + std::string EmitColorRegUseRGB(unsigned idx) const { return hecl::Format("colorReg%u.rgb", idx); } - std::string EmitColorRegUseAlpha(unsigned idx) const - { - return hecl::Format("colorReg%u.a", idx); - } + std::string EmitColorRegUseAlpha(unsigned idx) const { return hecl::Format("colorReg%u.a", idx); } - std::string EmitLightingRaw() const - { - return std::string("lighting"); - } + std::string EmitLightingRaw() const { return std::string("lighting"); } - std::string EmitLightingRGB() const - { - return std::string("lighting.rgb"); - } + std::string EmitLightingRGB() const { return std::string("lighting.rgb"); } - std::string EmitLightingAlpha() const - { - return std::string("lighting.a"); - } + std::string EmitLightingAlpha() const { return std::string("lighting.a"); } - virtual std::string EmitVec3(const atVec4f& vec) const=0; - virtual std::string EmitVec3(const std::string& a, const std::string& b, const std::string& c) const=0; + virtual std::string EmitVec3(const atVec4f& vec) const = 0; + virtual std::string EmitVec3(const std::string& a, const std::string& b, const std::string& c) const = 0; - std::string EmitVal(float val) const - { - return hecl::Format("%g", val); - } + std::string EmitVal(float val) const { return hecl::Format("%g", val); } - std::string EmitAdd(const std::string& a, const std::string& b) const - { - return '(' + a + '+' + b + ')'; - } + std::string EmitAdd(const std::string& a, const std::string& b) const { return '(' + a + '+' + b + ')'; } - std::string EmitSub(const std::string& a, const std::string& b) const - { - return '(' + a + '-' + b + ')'; - } + std::string EmitSub(const std::string& a, const std::string& b) const { return '(' + a + '-' + b + ')'; } - std::string EmitMult(const std::string& a, const std::string& b) const - { - return '(' + a + '*' + b + ')'; - } + std::string EmitMult(const std::string& a, const std::string& b) const { return '(' + a + '*' + b + ')'; } - std::string EmitDiv(const std::string& a, const std::string& b) const - { - return '(' + a + '/' + b + ')'; - } + std::string EmitDiv(const std::string& a, const std::string& b) const { return '(' + a + '/' + b + ')'; } - std::string EmitSwizzle3(Diagnostics& diag, const SourceLocation& loc, - const std::string& a, const atInt8 swiz[4]) const; + std::string EmitSwizzle3(Diagnostics& diag, const SourceLocation& loc, const std::string& a, + const atInt8 swiz[4]) const; - std::string EmitSwizzle1(Diagnostics& diag, const SourceLocation& loc, - const std::string& a, const atInt8 swiz[4]) const; + std::string EmitSwizzle1(Diagnostics& diag, const SourceLocation& loc, const std::string& a, + const atInt8 swiz[4]) const; }; -} - +} // namespace hecl::Backend diff --git a/hecl/include/hecl/BitVector.hpp b/hecl/include/hecl/BitVector.hpp index d0ac5ff90..acd1916fc 100644 --- a/hecl/include/hecl/BitVector.hpp +++ b/hecl/include/hecl/BitVector.hpp @@ -29,12 +29,11 @@ class BitVector { enum { BITWORD_SIZE = (unsigned)sizeof(BitWord) * CHAR_BIT }; - static_assert(BITWORD_SIZE == 64 || BITWORD_SIZE == 32, - "Unsupported word size"); + static_assert(BITWORD_SIZE == 64 || BITWORD_SIZE == 32, "Unsupported word size"); - BitWord *Bits; // Actual bits. - unsigned Size; // Size of bitvector in bits. - unsigned Capacity; // Number of BitWords allocated in the Bits array. + BitWord* Bits; // Actual bits. + unsigned Size; // Size of bitvector in bits. + unsigned Capacity; // Number of BitWords allocated in the Bits array. public: typedef unsigned size_type; @@ -42,20 +41,20 @@ public: class reference { friend class BitVector; - BitWord *WordRef; + BitWord* WordRef; unsigned BitPos; - reference(); // Undefined + reference(); // Undefined public: - reference(BitVector &b, unsigned Idx) { + reference(BitVector& b, unsigned Idx) { WordRef = &b.Bits[Idx / BITWORD_SIZE]; BitPos = Idx % BITWORD_SIZE; } reference(const reference&) = default; - reference &operator=(reference t) { + reference& operator=(reference t) { *this = bool(t); return *this; } @@ -68,29 +67,24 @@ public: return *this; } - operator bool() const { - return ((*WordRef) & (BitWord(1) << BitPos)) != 0; - } + operator bool() const { return ((*WordRef) & (BitWord(1) << BitPos)) != 0; } }; - /// BitVector default ctor - Creates an empty bitvector. - BitVector() : Size(0), Capacity(0) { - Bits = nullptr; - } + BitVector() : Size(0), Capacity(0) { Bits = nullptr; } /// BitVector ctor - Creates a bitvector of specified number of bits. All /// bits are initialized to the specified value. explicit BitVector(unsigned s, bool t = false) : Size(s) { Capacity = NumBitWords(s); - Bits = (BitWord *)std::malloc(Capacity * sizeof(BitWord)); + Bits = (BitWord*)std::malloc(Capacity * sizeof(BitWord)); init_words(Bits, Capacity, t); if (t) clear_unused_bits(); } /// BitVector copy ctor. - BitVector(const BitVector &RHS) : Size(RHS.size()) { + BitVector(const BitVector& RHS) : Size(RHS.size()) { if (Size == 0) { Bits = nullptr; Capacity = 0; @@ -98,19 +92,16 @@ public: } Capacity = NumBitWords(RHS.size()); - Bits = (BitWord *)std::malloc(Capacity * sizeof(BitWord)); + Bits = (BitWord*)std::malloc(Capacity * sizeof(BitWord)); std::memcpy(Bits, RHS.Bits, Capacity * sizeof(BitWord)); } - BitVector(BitVector &&RHS) - : Bits(RHS.Bits), Size(RHS.Size), Capacity(RHS.Capacity) { + BitVector(BitVector&& RHS) : Bits(RHS.Bits), Size(RHS.Size), Capacity(RHS.Capacity) { RHS.Bits = nullptr; RHS.Size = RHS.Capacity = 0; } - ~BitVector() { - std::free(Bits); - } + ~BitVector() { std::free(Bits); } /// empty - Tests whether there are no bits in this bitvector. bool empty() const { return Size == 0; } @@ -148,9 +139,7 @@ public: } /// none - Returns true if none of the bits are set. - bool none() const { - return !any(); - } + bool none() const { return !any(); } /// find_first - Returns the index of the first set bit, -1 if none /// of the bits are set. @@ -178,7 +167,7 @@ public: return WordPos * BITWORD_SIZE + countTrailingZeros(Copy); // Check subsequent words. - for (unsigned i = WordPos+1; i < NumBitWords(size()); ++i) + for (unsigned i = WordPos + 1; i < NumBitWords(size()); ++i) if (Bits[i] != 0) return i * BITWORD_SIZE + countTrailingZeros(Bits[i]); return -1; @@ -199,8 +188,7 @@ public: break; } } - if (good) - { + if (good) { unsigned space = BucketSz - (idx % BucketSz); if (space >= Length) return idx; @@ -210,16 +198,14 @@ public: } /// clear - Clear all bits. - void clear() { - Size = 0; - } + void clear() { Size = 0; } /// resize - Grow or shrink the bitvector. void resize(unsigned N, bool t = false) { if (N > Capacity * BITWORD_SIZE) { unsigned OldCapacity = Capacity; grow(N); - init_words(&Bits[OldCapacity], (Capacity-OldCapacity), t); + init_words(&Bits[OldCapacity], (Capacity - OldCapacity), t); } // Set any old unused bits that are now included in the BitVector. This @@ -241,24 +227,25 @@ public: } // Set, reset, flip - BitVector &set() { + BitVector& set() { init_words(Bits, Capacity, true); clear_unused_bits(); return *this; } - BitVector &set(unsigned Idx) { + BitVector& set(unsigned Idx) { assert(Bits && "Bits never allocated"); Bits[Idx / BITWORD_SIZE] |= BitWord(1) << (Idx % BITWORD_SIZE); return *this; } /// set - Efficiently set a range of bits in [I, E) - BitVector &set(unsigned I, unsigned E) { + BitVector& set(unsigned I, unsigned E) { assert(I <= E && "Attempted to set backwards range!"); assert(E <= size() && "Attempted to set out-of-bounds range!"); - if (I == E) return *this; + if (I == E) + return *this; if (I / BITWORD_SIZE == E / BITWORD_SIZE) { BitWord EMask = 1UL << (E % BITWORD_SIZE); @@ -282,22 +269,23 @@ public: return *this; } - BitVector &reset() { + BitVector& reset() { init_words(Bits, Capacity, false); return *this; } - BitVector &reset(unsigned Idx) { + BitVector& reset(unsigned Idx) { Bits[Idx / BITWORD_SIZE] &= ~(BitWord(1) << (Idx % BITWORD_SIZE)); return *this; } /// reset - Efficiently reset a range of bits in [I, E) - BitVector &reset(unsigned I, unsigned E) { + BitVector& reset(unsigned I, unsigned E) { assert(I <= E && "Attempted to reset backwards range!"); assert(E <= size() && "Attempted to reset out-of-bounds range!"); - if (I == E) return *this; + if (I == E) + return *this; if (I / BITWORD_SIZE == E / BITWORD_SIZE) { BitWord EMask = 1UL << (E % BITWORD_SIZE); @@ -321,38 +309,36 @@ public: return *this; } - BitVector &flip() { + BitVector& flip() { for (unsigned i = 0; i < NumBitWords(size()); ++i) Bits[i] = ~Bits[i]; clear_unused_bits(); return *this; } - BitVector &flip(unsigned Idx) { + BitVector& flip(unsigned Idx) { Bits[Idx / BITWORD_SIZE] ^= BitWord(1) << (Idx % BITWORD_SIZE); return *this; } // Indexing. reference operator[](unsigned Idx) { - assert (Idx < Size && "Out-of-bounds Bit access."); + assert(Idx < Size && "Out-of-bounds Bit access."); return reference(*this, Idx); } bool operator[](unsigned Idx) const { - assert (Idx < Size && "Out-of-bounds Bit access."); + assert(Idx < Size && "Out-of-bounds Bit access."); BitWord Mask = BitWord(1) << (Idx % BITWORD_SIZE); return (Bits[Idx / BITWORD_SIZE] & Mask) != 0; } - bool test(unsigned Idx) const { - return (*this)[Idx]; - } + bool test(unsigned Idx) const { return (*this)[Idx]; } /// Test if any common bits are set. - bool anyCommon(const BitVector &RHS) const { + bool anyCommon(const BitVector& RHS) const { unsigned ThisWords = NumBitWords(size()); - unsigned RHSWords = NumBitWords(RHS.size()); + unsigned RHSWords = NumBitWords(RHS.size()); for (unsigned i = 0, e = std::min(ThisWords, RHSWords); i != e; ++i) if (Bits[i] & RHS.Bits[i]) return true; @@ -360,9 +346,9 @@ public: } // Comparison operators. - bool operator==(const BitVector &RHS) const { + bool operator==(const BitVector& RHS) const { unsigned ThisWords = NumBitWords(size()); - unsigned RHSWords = NumBitWords(RHS.size()); + unsigned RHSWords = NumBitWords(RHS.size()); unsigned i; for (i = 0; i != std::min(ThisWords, RHSWords); ++i) if (Bits[i] != RHS.Bits[i]) @@ -381,14 +367,12 @@ public: return true; } - bool operator!=(const BitVector &RHS) const { - return !(*this == RHS); - } + bool operator!=(const BitVector& RHS) const { return !(*this == RHS); } /// Intersection, union, disjoint union. - BitVector &operator&=(const BitVector &RHS) { + BitVector& operator&=(const BitVector& RHS) { unsigned ThisWords = NumBitWords(size()); - unsigned RHSWords = NumBitWords(RHS.size()); + unsigned RHSWords = NumBitWords(RHS.size()); unsigned i; for (i = 0; i != std::min(ThisWords, RHSWords); ++i) Bits[i] &= RHS.Bits[i]; @@ -403,9 +387,9 @@ public: } /// reset - Reset bits that are set in RHS. Same as *this &= ~RHS. - BitVector &reset(const BitVector &RHS) { + BitVector& reset(const BitVector& RHS) { unsigned ThisWords = NumBitWords(size()); - unsigned RHSWords = NumBitWords(RHS.size()); + unsigned RHSWords = NumBitWords(RHS.size()); unsigned i; for (i = 0; i != std::min(ThisWords, RHSWords); ++i) Bits[i] &= ~RHS.Bits[i]; @@ -414,22 +398,22 @@ public: /// test - Check if (This - RHS) is zero. /// This is the same as reset(RHS) and any(). - bool test(const BitVector &RHS) const { + bool test(const BitVector& RHS) const { unsigned ThisWords = NumBitWords(size()); - unsigned RHSWords = NumBitWords(RHS.size()); + unsigned RHSWords = NumBitWords(RHS.size()); unsigned i; for (i = 0; i != std::min(ThisWords, RHSWords); ++i) if ((Bits[i] & ~RHS.Bits[i]) != 0) return true; - for (; i != ThisWords ; ++i) + for (; i != ThisWords; ++i) if (Bits[i] != 0) return true; return false; } - BitVector &operator|=(const BitVector &RHS) { + BitVector& operator|=(const BitVector& RHS) { if (size() < RHS.size()) resize(RHS.size()); for (size_t i = 0, e = NumBitWords(RHS.size()); i != e; ++i) @@ -437,7 +421,7 @@ public: return *this; } - BitVector &operator^=(const BitVector &RHS) { + BitVector& operator^=(const BitVector& RHS) { if (size() < RHS.size()) resize(RHS.size()); for (size_t i = 0, e = NumBitWords(RHS.size()); i != e; ++i) @@ -446,8 +430,9 @@ public: } // Assignment operator. - const BitVector &operator=(const BitVector &RHS) { - if (this == &RHS) return *this; + const BitVector& operator=(const BitVector& RHS) { + if (this == &RHS) + return *this; Size = RHS.size(); unsigned RHSWords = NumBitWords(Size); @@ -461,7 +446,7 @@ public: // Grow the bitvector to have enough elements. Capacity = RHSWords; assert(Capacity > 0 && "negative capacity?"); - BitWord *NewBits = (BitWord *)std::malloc(Capacity * sizeof(BitWord)); + BitWord* NewBits = (BitWord*)std::malloc(Capacity * sizeof(BitWord)); std::memcpy(NewBits, RHS.Bits, Capacity * sizeof(BitWord)); // Destroy the old bits. @@ -471,8 +456,9 @@ public: return *this; } - const BitVector &operator=(BitVector &&RHS) { - if (this == &RHS) return *this; + const BitVector& operator=(BitVector&& RHS) { + if (this == &RHS) + return *this; std::free(Bits); Bits = RHS.Bits; @@ -485,7 +471,7 @@ public: return *this; } - void swap(BitVector &RHS) { + void swap(BitVector& RHS) { std::swap(Bits, RHS.Bits); std::swap(Size, RHS.Size); std::swap(Capacity, RHS.Capacity); @@ -505,70 +491,56 @@ public: /// setBitsInMask - Add '1' bits from Mask to this vector. Don't resize. /// This computes "*this |= Mask". - void setBitsInMask(const uint32_t *Mask, unsigned MaskWords = ~0u) { - applyMask(Mask, MaskWords); - } + void setBitsInMask(const uint32_t* Mask, unsigned MaskWords = ~0u) { applyMask(Mask, MaskWords); } /// clearBitsInMask - Clear any bits in this vector that are set in Mask. /// Don't resize. This computes "*this &= ~Mask". - void clearBitsInMask(const uint32_t *Mask, unsigned MaskWords = ~0u) { - applyMask(Mask, MaskWords); - } + void clearBitsInMask(const uint32_t* Mask, unsigned MaskWords = ~0u) { applyMask(Mask, MaskWords); } /// setBitsNotInMask - Add a bit to this vector for every '0' bit in Mask. /// Don't resize. This computes "*this |= ~Mask". - void setBitsNotInMask(const uint32_t *Mask, unsigned MaskWords = ~0u) { - applyMask(Mask, MaskWords); - } + void setBitsNotInMask(const uint32_t* Mask, unsigned MaskWords = ~0u) { applyMask(Mask, MaskWords); } /// clearBitsNotInMask - Clear a bit in this vector for every '0' bit in Mask. /// Don't resize. This computes "*this &= Mask". - void clearBitsNotInMask(const uint32_t *Mask, unsigned MaskWords = ~0u) { - applyMask(Mask, MaskWords); - } + void clearBitsNotInMask(const uint32_t* Mask, unsigned MaskWords = ~0u) { applyMask(Mask, MaskWords); } private: - unsigned NumBitWords(unsigned S) const { - return (S + BITWORD_SIZE-1) / BITWORD_SIZE; - } + unsigned NumBitWords(unsigned S) const { return (S + BITWORD_SIZE - 1) / BITWORD_SIZE; } // Set the unused bits in the high words. void set_unused_bits(bool t = true) { // Set high words first. unsigned UsedWords = NumBitWords(Size); if (Capacity > UsedWords) - init_words(&Bits[UsedWords], (Capacity-UsedWords), t); + init_words(&Bits[UsedWords], (Capacity - UsedWords), t); // Then set any stray high bits of the last used word. unsigned ExtraBits = Size % BITWORD_SIZE; if (ExtraBits) { BitWord ExtraBitMask = ~0UL << ExtraBits; if (t) - Bits[UsedWords-1] |= ExtraBitMask; + Bits[UsedWords - 1] |= ExtraBitMask; else - Bits[UsedWords-1] &= ~ExtraBitMask; + Bits[UsedWords - 1] &= ~ExtraBitMask; } } // Clear the unused bits in the high words. - void clear_unused_bits() { - set_unused_bits(false); - } + void clear_unused_bits() { set_unused_bits(false); } void grow(unsigned NewSize) { Capacity = std::max(NumBitWords(NewSize), Capacity * 2); assert(Capacity > 0 && "realloc-ing zero space"); - Bits = (BitWord *)std::realloc(Bits, Capacity * sizeof(BitWord)); + Bits = (BitWord*)std::realloc(Bits, Capacity * sizeof(BitWord)); clear_unused_bits(); } - void init_words(BitWord *B, unsigned NumWords, bool t) { - memset(B, 0 - (int)t, NumWords*sizeof(BitWord)); - } + void init_words(BitWord* B, unsigned NumWords, bool t) { memset(B, 0 - (int)t, NumWords * sizeof(BitWord)); } - template - void applyMask(const uint32_t *Mask, unsigned MaskWords) { + template + void applyMask(const uint32_t* Mask, unsigned MaskWords) { static_assert(BITWORD_SIZE % 32 == 0, "Unsupported BitWord size."); MaskWords = std::min(MaskWords, (size() + 31) / 32); const unsigned Scale = BITWORD_SIZE / 32; @@ -578,17 +550,23 @@ private: // This inner loop should unroll completely when BITWORD_SIZE > 32. for (unsigned b = 0; b != BITWORD_SIZE; b += 32) { uint32_t M = *Mask++; - if (InvertMask) M = ~M; - if (AddBits) BW |= BitWord(M) << b; - else BW &= ~(BitWord(M) << b); + if (InvertMask) + M = ~M; + if (AddBits) + BW |= BitWord(M) << b; + else + BW &= ~(BitWord(M) << b); } Bits[i] = BW; } for (unsigned b = 0; MaskWords; b += 32, --MaskWords) { uint32_t M = *Mask++; - if (InvertMask) M = ~M; - if (AddBits) Bits[i] |= BitWord(M) << b; - else Bits[i] &= ~(BitWord(M) << b); + if (InvertMask) + M = ~M; + if (AddBits) + Bits[i] |= BitWord(M) << b; + else + Bits[i] &= ~(BitWord(M) << b); } if (AddBits) clear_unused_bits(); @@ -599,18 +577,12 @@ public: size_t getMemorySize() const { return Capacity * sizeof(BitWord); } }; -static inline size_t capacity_in_bytes(const BitVector &X) { - return X.getMemorySize(); -} +static inline size_t capacity_in_bytes(const BitVector& X) { return X.getMemorySize(); } } // end namespace llvm } // end namespace hecl namespace std { - /// Implement std::swap in terms of BitVector swap. - inline void - swap(hecl::llvm::BitVector &LHS, hecl::llvm::BitVector &RHS) { - LHS.swap(RHS); - } +/// Implement std::swap in terms of BitVector swap. +inline void swap(hecl::llvm::BitVector& LHS, hecl::llvm::BitVector& RHS) { LHS.swap(RHS); } } // end namespace std - diff --git a/hecl/include/hecl/Blender/Connection.hpp b/hecl/include/hecl/Blender/Connection.hpp index 43a7af070..a56f10777 100644 --- a/hecl/include/hecl/Blender/Connection.hpp +++ b/hecl/include/hecl/Blender/Connection.hpp @@ -28,698 +28,634 @@ #include "optional.hpp" #include "Token.hpp" -namespace hecl::blender -{ +namespace hecl::blender { extern logvisor::Module BlenderLog; class HMDLBuffers; class Connection; -struct PoolSkinIndex -{ - size_t m_poolSz = 0; - std::unique_ptr m_poolToSkinIndex; +struct PoolSkinIndex { + size_t m_poolSz = 0; + std::unique_ptr m_poolToSkinIndex; - void allocate(size_t poolSz) - { - m_poolSz = poolSz; - if (poolSz) - m_poolToSkinIndex.reset(new uint32_t[poolSz]); - } + void allocate(size_t poolSz) { + m_poolSz = poolSz; + if (poolSz) + m_poolToSkinIndex.reset(new uint32_t[poolSz]); + } }; -enum class ANIMCurveType -{ - Rotate, - Translate, - Scale -}; +enum class ANIMCurveType { Rotate, Translate, Scale }; + +class ANIMOutStream { + Connection* m_parent; + unsigned m_curCount = 0; + unsigned m_totalCount = 0; + bool m_inCurve = false; -class ANIMOutStream -{ - Connection* m_parent; - unsigned m_curCount = 0; - unsigned m_totalCount = 0; - bool m_inCurve = false; public: - using CurveType = ANIMCurveType; - ANIMOutStream(Connection* parent); - ~ANIMOutStream(); - void changeCurve(CurveType type, unsigned crvIdx, unsigned keyCount); - void write(unsigned frame, float val); + using CurveType = ANIMCurveType; + ANIMOutStream(Connection* parent); + ~ANIMOutStream(); + void changeCurve(CurveType type, unsigned crvIdx, unsigned keyCount); + void write(unsigned frame, float val); }; -class PyOutStream : public std::ostream -{ - friend class Connection; - Connection* m_parent; - struct StreamBuf : std::streambuf - { - PyOutStream& m_parent; - std::string m_lineBuf; - bool m_deleteOnError; - StreamBuf(PyOutStream& parent, bool deleteOnError) - : m_parent(parent), m_deleteOnError(deleteOnError) {} - StreamBuf(const StreamBuf& other) = delete; - StreamBuf(StreamBuf&& other) = default; - int_type overflow(int_type ch); - } m_sbuf; - PyOutStream(Connection* parent, bool deleteOnError); +class PyOutStream : public std::ostream { + friend class Connection; + Connection* m_parent; + struct StreamBuf : std::streambuf { + PyOutStream& m_parent; + std::string m_lineBuf; + bool m_deleteOnError; + StreamBuf(PyOutStream& parent, bool deleteOnError) : m_parent(parent), m_deleteOnError(deleteOnError) {} + StreamBuf(const StreamBuf& other) = delete; + StreamBuf(StreamBuf&& other) = default; + int_type overflow(int_type ch); + } m_sbuf; + PyOutStream(Connection* parent, bool deleteOnError); + public: - PyOutStream(const PyOutStream& other) = delete; - PyOutStream(PyOutStream&& other) - : std::ostream(&m_sbuf), m_parent(other.m_parent), m_sbuf(std::move(other.m_sbuf)) - {other.m_parent = nullptr;} - ~PyOutStream() {close();} - void close(); + PyOutStream(const PyOutStream& other) = delete; + PyOutStream(PyOutStream&& other) : std::ostream(&m_sbuf), m_parent(other.m_parent), m_sbuf(std::move(other.m_sbuf)) { + other.m_parent = nullptr; + } + ~PyOutStream() { close(); } + void close(); #if __GNUC__ - __attribute__((__format__ (__printf__, 2, 3))) + __attribute__((__format__(__printf__, 2, 3))) #endif - void format(const char* fmt, ...); - void linkBlend(const char* target, const char* objName, bool link=true); - void linkBackground(const char* target, const char* sceneName=nullptr); - void AABBToBMesh(const atVec3f& min, const atVec3f& max); - void centerView(); + void + format(const char* fmt, ...); + void linkBlend(const char* target, const char* objName, bool link = true); + void linkBackground(const char* target, const char* sceneName = nullptr); + void AABBToBMesh(const atVec3f& min, const atVec3f& max); + void centerView(); - ANIMOutStream beginANIMCurve() - { - return ANIMOutStream(m_parent); - } - Connection& getConnection() {return *m_parent;} + ANIMOutStream beginANIMCurve() { return ANIMOutStream(m_parent); } + Connection& getConnection() { return *m_parent; } }; /* Vector types with integrated stream reading constructor */ -struct Vector2f -{ - atVec2f val; - Vector2f() = default; - void read(Connection& conn); - Vector2f(Connection& conn) {read(conn);} - operator const atVec2f&() const {return val;} +struct Vector2f { + atVec2f val; + Vector2f() = default; + void read(Connection& conn); + Vector2f(Connection& conn) { read(conn); } + operator const atVec2f&() const { return val; } }; -struct Vector3f -{ - atVec3f val; - Vector3f() = default; - void read(Connection& conn); - Vector3f(Connection& conn) {read(conn);} - operator const atVec3f&() const {return val;} +struct Vector3f { + atVec3f val; + Vector3f() = default; + void read(Connection& conn); + Vector3f(Connection& conn) { read(conn); } + operator const atVec3f&() const { return val; } }; -struct Vector4f -{ - atVec4f val; - Vector4f() = default; - void read(Connection& conn); - Vector4f(Connection& conn) {read(conn);} - operator const atVec4f&() const {return val;} +struct Vector4f { + atVec4f val; + Vector4f() = default; + void read(Connection& conn); + Vector4f(Connection& conn) { read(conn); } + operator const atVec4f&() const { return val; } }; -struct Matrix3f -{ - atVec3f m[3]; - inline atVec3f& operator[](size_t idx) {return m[idx];} - inline const atVec3f& operator[](size_t idx) const {return m[idx];} +struct Matrix3f { + atVec3f m[3]; + inline atVec3f& operator[](size_t idx) { return m[idx]; } + inline const atVec3f& operator[](size_t idx) const { return m[idx]; } }; -struct Matrix4f -{ - atVec4f val[4]; - Matrix4f() = default; - void read(Connection& conn); - Matrix4f(Connection& conn) {read(conn);} - const atVec4f& operator[] (size_t idx) const {return val[idx];} +struct Matrix4f { + atVec4f val[4]; + Matrix4f() = default; + void read(Connection& conn); + Matrix4f(Connection& conn) { read(conn); } + const atVec4f& operator[](size_t idx) const { return val[idx]; } }; -struct Index -{ - uint32_t val; - Index() = default; - void read(Connection& conn); - Index(Connection& conn) {read(conn);} - operator const uint32_t&() const {return val;} +struct Index { + uint32_t val; + Index() = default; + void read(Connection& conn); + Index(Connection& conn) { read(conn); } + operator const uint32_t&() const { return val; } }; atVec3f MtxVecMul4RM(const Matrix4f& mtx, const Vector3f& vec); atVec3f MtxVecMul3RM(const Matrix4f& mtx, const Vector3f& vec); /** HECL source and metadata of each material */ -struct Material -{ - std::string name; - std::string source; - std::vector texs; - std::unordered_map iprops; - bool transparent; +struct Material { + std::string name; + std::string source; + std::vector texs; + std::unordered_map iprops; + bool transparent; - Material(Connection& conn); - bool operator==(const Material& other) const - { - return source == other.source && texs == other.texs && iprops == other.iprops; - } + Material(Connection& conn); + bool operator==(const Material& other) const { + return source == other.source && texs == other.texs && iprops == other.iprops; + } }; /** Intermediate mesh representation prepared by blender from a single mesh object */ -struct Mesh -{ - HMDLTopology topology; +struct Mesh { + HMDLTopology topology; - /* Object transform in scene */ - Matrix4f sceneXf; + /* Object transform in scene */ + Matrix4f sceneXf; - /* Cumulative AABB */ + /* Cumulative AABB */ + Vector3f aabbMin; + Vector3f aabbMax; + + std::vector> materialSets; + + /* Vertex buffer data */ + std::vector pos; + std::vector norm; + uint32_t colorLayerCount = 0; + std::vector color; + uint32_t uvLayerCount = 0; + std::vector uv; + uint32_t luvLayerCount = 0; + std::vector luv; + + /* Skinning data */ + std::vector boneNames; + struct SkinBind { + uint32_t boneIdx; + float weight; + SkinBind(Connection& conn); + }; + std::vector> skins; + std::vector contiguousSkinVertCounts; + + void normalizeSkinBinds(); + + /** Islands of the same material/skinBank are represented here */ + struct Surface { + Vector3f centroid; + Index materialIdx; Vector3f aabbMin; Vector3f aabbMax; + Vector3f reflectionNormal; + uint32_t skinBankIdx; - std::vector> materialSets; + /** Vertex indexing data (all primitives joined as degenerate tri-strip) */ + struct Vert { + uint32_t iPos = 0xffffffff; + uint32_t iNorm = 0xffffffff; + uint32_t iColor[4] = {0xffffffff}; + uint32_t iUv[8] = {0xffffffff}; + uint32_t iSkin = 0xffffffff; + uint32_t iBankSkin = 0xffffffff; - /* Vertex buffer data */ - std::vector pos; - std::vector norm; - uint32_t colorLayerCount = 0; - std::vector color; - uint32_t uvLayerCount = 0; - std::vector uv; - uint32_t luvLayerCount = 0; - std::vector luv; - - /* Skinning data */ - std::vector boneNames; - struct SkinBind - { - uint32_t boneIdx; - float weight; - SkinBind(Connection& conn); + Vert(Connection& conn, const Mesh& parent); + bool operator==(const Vert& other) const; }; - std::vector> skins; - std::vector contiguousSkinVertCounts; + std::vector verts; - void normalizeSkinBinds(); + Surface(Connection& conn, Mesh& parent, int skinSlotCount); + }; + std::vector surfaces; - /** Islands of the same material/skinBank are represented here */ - struct Surface - { - Vector3f centroid; - Index materialIdx; - Vector3f aabbMin; - Vector3f aabbMax; - Vector3f reflectionNormal; - uint32_t skinBankIdx; + std::unordered_map customProps; - /** Vertex indexing data (all primitives joined as degenerate tri-strip) */ - struct Vert - { - uint32_t iPos = 0xffffffff; - uint32_t iNorm = 0xffffffff; - uint32_t iColor[4] = {0xffffffff}; - uint32_t iUv[8] = {0xffffffff}; - uint32_t iSkin = 0xffffffff; - uint32_t iBankSkin = 0xffffffff; + struct SkinBanks { + struct Bank { + std::vector m_skinIdxs; + std::vector m_boneIdxs; - Vert(Connection& conn, const Mesh& parent); - bool operator==(const Vert& other) const; - }; - std::vector verts; - - Surface(Connection& conn, Mesh& parent, int skinSlotCount); + void addSkins(const Mesh& parent, const std::vector& skinIdxs); + size_t lookupLocalBoneIdx(uint32_t boneIdx) const; }; - std::vector surfaces; + std::vector banks; + std::vector::iterator addSkinBank(int skinSlotCount); + uint32_t addSurface(const Mesh& mesh, const Surface& surf, int skinSlotCount); + } skinBanks; - std::unordered_map customProps; + using SurfProgFunc = std::function; + Mesh(Connection& conn, HMDLTopology topology, int skinSlotCount, SurfProgFunc& surfProg); - struct SkinBanks - { - struct Bank - { - std::vector m_skinIdxs; - std::vector m_boneIdxs; + Mesh getContiguousSkinningVersion() const; - void addSkins(const Mesh& parent, const std::vector& skinIdxs); - size_t lookupLocalBoneIdx(uint32_t boneIdx) const; - }; - std::vector banks; - std::vector::iterator addSkinBank(int skinSlotCount); - uint32_t addSurface(const Mesh& mesh, const Surface& surf, int skinSlotCount); - } skinBanks; - - using SurfProgFunc = std::function; - Mesh(Connection& conn, HMDLTopology topology, int skinSlotCount, SurfProgFunc& surfProg); - - Mesh getContiguousSkinningVersion() const; - - /** Prepares mesh representation for indexed access on modern APIs. - * Mesh must remain resident for accessing reference members - */ - HMDLBuffers getHMDLBuffers(bool absoluteCoords, PoolSkinIndex& poolSkinIndex) const; + /** Prepares mesh representation for indexed access on modern APIs. + * Mesh must remain resident for accessing reference members + */ + HMDLBuffers getHMDLBuffers(bool absoluteCoords, PoolSkinIndex& poolSkinIndex) const; }; /** Intermediate collision mesh representation prepared by blender from a single mesh object */ -struct ColMesh -{ - /** HECL source and metadata of each material */ - struct Material - { - std::string name; - bool unknown; - bool surfaceStone; - bool surfaceMetal; - bool surfaceGrass; - bool surfaceIce; - bool pillar; - bool surfaceMetalGrating; - bool surfacePhazon; - bool surfaceDirt; - bool surfaceLava; - bool surfaceSPMetal; - bool surfaceLavaStone; - bool surfaceSnow; - bool surfaceMudSlow; - bool surfaceFabric; - bool halfPipe; - bool surfaceMud; - bool surfaceGlass; - bool unused3; - bool unused4; - bool surfaceShield; - bool surfaceSand; - bool surfaceMothOrSeedOrganics; - bool surfaceWeb; - bool projPassthrough; - bool solid; - bool noPlatformCollision; - bool camPassthrough; - bool surfaceWood; - bool surfaceOrganic; - bool noEdgeCollision; - bool surfaceRubber; - bool seeThrough; - bool scanPassthrough; - bool aiPassthrough; - bool ceiling; - bool wall; - bool floor; - bool aiBlock; - bool jumpNotAllowed; - bool spiderBall; - bool screwAttackWallJump; +struct ColMesh { + /** HECL source and metadata of each material */ + struct Material { + std::string name; + bool unknown; + bool surfaceStone; + bool surfaceMetal; + bool surfaceGrass; + bool surfaceIce; + bool pillar; + bool surfaceMetalGrating; + bool surfacePhazon; + bool surfaceDirt; + bool surfaceLava; + bool surfaceSPMetal; + bool surfaceLavaStone; + bool surfaceSnow; + bool surfaceMudSlow; + bool surfaceFabric; + bool halfPipe; + bool surfaceMud; + bool surfaceGlass; + bool unused3; + bool unused4; + bool surfaceShield; + bool surfaceSand; + bool surfaceMothOrSeedOrganics; + bool surfaceWeb; + bool projPassthrough; + bool solid; + bool noPlatformCollision; + bool camPassthrough; + bool surfaceWood; + bool surfaceOrganic; + bool noEdgeCollision; + bool surfaceRubber; + bool seeThrough; + bool scanPassthrough; + bool aiPassthrough; + bool ceiling; + bool wall; + bool floor; + bool aiBlock; + bool jumpNotAllowed; + bool spiderBall; + bool screwAttackWallJump; - Material(Connection& conn); - }; - std::vector materials; + Material(Connection& conn); + }; + std::vector materials; - std::vector verts; + std::vector verts; - struct Edge - { - uint32_t verts[2]; - bool seam; - Edge(Connection& conn); - }; - std::vector edges; + struct Edge { + uint32_t verts[2]; + bool seam; + Edge(Connection& conn); + }; + std::vector edges; - struct Triangle - { - uint32_t edges[3]; - uint32_t matIdx; - bool flip; - Triangle(Connection& conn); - }; - std::vector trianges; + struct Triangle { + uint32_t edges[3]; + uint32_t matIdx; + bool flip; + Triangle(Connection& conn); + }; + std::vector trianges; - ColMesh(Connection& conn); + ColMesh(Connection& conn); }; /** Intermediate world representation */ -struct World -{ - struct Area - { - ProjectPath path; - Vector3f aabb[2]; - Matrix4f transform; - struct Dock - { - Vector3f verts[4]; - Index targetArea; - Index targetDock; - Dock(Connection& conn); - }; - std::vector docks; - Area(Connection& conn); +struct World { + struct Area { + ProjectPath path; + Vector3f aabb[2]; + Matrix4f transform; + struct Dock { + Vector3f verts[4]; + Index targetArea; + Index targetDock; + Dock(Connection& conn); }; - std::vector areas; - World(Connection& conn); + std::vector docks; + Area(Connection& conn); + }; + std::vector areas; + World(Connection& conn); }; /** Intermediate lamp representation */ -struct Light -{ - /* Object transform in scene */ - Matrix4f sceneXf; - Vector3f color; +struct Light { + /* Object transform in scene */ + Matrix4f sceneXf; + Vector3f color; - uint32_t layer; + uint32_t layer; - enum class Type : uint32_t - { - Ambient, - Directional, - Custom, - Spot - } type; + enum class Type : uint32_t { Ambient, Directional, Custom, Spot } type; - float energy; - float spotCutoff; - float constant; - float linear; - float quadratic; - bool shadow; + float energy; + float spotCutoff; + float constant; + float linear; + float quadratic; + bool shadow; - std::string name; + std::string name; - Light(Connection& conn); + Light(Connection& conn); }; /** Intermediate MapArea representation */ -struct MapArea -{ - Index visType; - std::vector verts; - std::vector indices; - struct Surface - { - Vector3f normal; - Vector3f centerOfMass; - Index start; - Index count; - std::vector> borders; - Surface(Connection& conn); - }; - std::vector surfaces; - struct POI - { - uint32_t type; - uint32_t visMode; - uint32_t objid; - Matrix4f xf; - POI(Connection& conn); - }; - std::vector pois; - MapArea(Connection& conn); +struct MapArea { + Index visType; + std::vector verts; + std::vector indices; + struct Surface { + Vector3f normal; + Vector3f centerOfMass; + Index start; + Index count; + std::vector> borders; + Surface(Connection& conn); + }; + std::vector surfaces; + struct POI { + uint32_t type; + uint32_t visMode; + uint32_t objid; + Matrix4f xf; + POI(Connection& conn); + }; + std::vector pois; + MapArea(Connection& conn); }; /** Intermediate MapUniverse representation */ -struct MapUniverse -{ - hecl::ProjectPath hexagonPath; - struct World - { - std::string name; - Matrix4f xf; - std::vector hexagons; - Vector4f color; - hecl::ProjectPath worldPath; - World(Connection& conn); - }; - std::vector worlds; - MapUniverse(Connection& conn); +struct MapUniverse { + hecl::ProjectPath hexagonPath; + struct World { + std::string name; + Matrix4f xf; + std::vector hexagons; + Vector4f color; + hecl::ProjectPath worldPath; + World(Connection& conn); + }; + std::vector worlds; + MapUniverse(Connection& conn); }; /** Intermediate bone representation used in Armature */ -struct Bone -{ - std::string name; - Vector3f origin; - int32_t parent = -1; - std::vector children; - Bone(Connection& conn); +struct Bone { + std::string name; + Vector3f origin; + int32_t parent = -1; + std::vector children; + Bone(Connection& conn); }; /** Intermediate armature representation used in Actor */ -struct Armature -{ - std::string name; - std::vector bones; - const Bone* lookupBone(const char* name) const; - const Bone* getParent(const Bone* bone) const; - const Bone* getChild(const Bone* bone, size_t child) const; - const Bone* getRoot() const; - Armature(Connection& conn); +struct Armature { + std::string name; + std::vector bones; + const Bone* lookupBone(const char* name) const; + const Bone* getParent(const Bone* bone) const; + const Bone* getChild(const Bone* bone, size_t child) const; + const Bone* getRoot() const; + Armature(Connection& conn); }; /** Intermediate action representation used in Actor */ -struct Action -{ - std::string name; - float interval; - bool additive; - bool looping; - std::vector frames; - struct Channel - { - std::string boneName; - uint32_t attrMask; - struct Key - { - Vector4f rotation; - Vector3f position; - Vector3f scale; - Key(Connection& conn, uint32_t attrMask); - }; - std::vector keys; - Channel(Connection& conn); +struct Action { + std::string name; + float interval; + bool additive; + bool looping; + std::vector frames; + struct Channel { + std::string boneName; + uint32_t attrMask; + struct Key { + Vector4f rotation; + Vector3f position; + Vector3f scale; + Key(Connection& conn, uint32_t attrMask); }; - std::vector channels; - std::vector> subtypeAABBs; - Action(Connection& conn); + std::vector keys; + Channel(Connection& conn); + }; + std::vector channels; + std::vector> subtypeAABBs; + Action(Connection& conn); }; /** Intermediate actor representation prepared by blender from a single HECL actor blend */ -struct Actor -{ - std::vector armatures; +struct Actor { + std::vector armatures; - struct Subtype - { - std::string name; - ProjectPath mesh; - int32_t armature = -1; - std::vector> overlayMeshes; - Subtype(Connection& conn); - }; - std::vector subtypes; - struct Attachment - { - std::string name; - ProjectPath mesh; - int32_t armature = -1; - Attachment(Connection& conn); - }; - std::vector attachments; - std::vector actions; + struct Subtype { + std::string name; + ProjectPath mesh; + int32_t armature = -1; + std::vector> overlayMeshes; + Subtype(Connection& conn); + }; + std::vector subtypes; + struct Attachment { + std::string name; + ProjectPath mesh; + int32_t armature = -1; + Attachment(Connection& conn); + }; + std::vector attachments; + std::vector actions; - Actor(Connection& conn); + Actor(Connection& conn); }; /** Intermediate pathfinding representation prepared by blender */ -struct PathMesh -{ - std::vector data; - PathMesh(Connection& conn); +struct PathMesh { + std::vector data; + PathMesh(Connection& conn); }; -class DataStream -{ - friend class Connection; - Connection* m_parent; - DataStream(Connection* parent); +class DataStream { + friend class Connection; + Connection* m_parent; + DataStream(Connection* parent); + public: - DataStream(const DataStream& other) = delete; - DataStream(DataStream&& other) - : m_parent(other.m_parent) {other.m_parent = nullptr;} - ~DataStream() {close();} - void close(); - std::vector getMeshList(); - std::vector getLightList(); - std::pair getMeshAABB(); - static const char* MeshOutputModeString(HMDLTopology topology); + DataStream(const DataStream& other) = delete; + DataStream(DataStream&& other) : m_parent(other.m_parent) { other.m_parent = nullptr; } + ~DataStream() { close(); } + void close(); + std::vector getMeshList(); + std::vector getLightList(); + std::pair getMeshAABB(); + static const char* MeshOutputModeString(HMDLTopology topology); - /** Compile mesh by context (MESH blends only) */ - Mesh compileMesh(HMDLTopology topology, int skinSlotCount=10, - Mesh::SurfProgFunc surfProg=[](int){}); + /** Compile mesh by context (MESH blends only) */ + Mesh compileMesh(HMDLTopology topology, int skinSlotCount = 10, Mesh::SurfProgFunc surfProg = [](int) {}); - /** Compile mesh by name (AREA blends only) */ - Mesh compileMesh(std::string_view name, HMDLTopology topology, int skinSlotCount=10, bool useLuv=false, - Mesh::SurfProgFunc surfProg=[](int){}); + /** Compile mesh by name (AREA blends only) */ + Mesh compileMesh(std::string_view name, HMDLTopology topology, int skinSlotCount = 10, bool useLuv = false, + Mesh::SurfProgFunc surfProg = [](int) {}); - /** Compile collision mesh by name (AREA blends only) */ - ColMesh compileColMesh(std::string_view name); + /** Compile collision mesh by name (AREA blends only) */ + ColMesh compileColMesh(std::string_view name); - /** Compile all meshes as collision meshes (CMESH blends only) */ - std::vector compileColMeshes(); + /** Compile all meshes as collision meshes (CMESH blends only) */ + std::vector compileColMeshes(); - /** Compile all meshes into one (AREA blends only) */ - Mesh compileAllMeshes(HMDLTopology topology, int skinSlotCount=10, float maxOctantLength=5.0, - Mesh::SurfProgFunc surfProg=[](int){}); + /** Compile all meshes into one (AREA blends only) */ + Mesh compileAllMeshes(HMDLTopology topology, int skinSlotCount = 10, float maxOctantLength = 5.0, + Mesh::SurfProgFunc surfProg = [](int) {}); - /** Compile world intermediate (WORLD blends only) */ - World compileWorld(); + /** Compile world intermediate (WORLD blends only) */ + World compileWorld(); - /** Gather all lights in scene (AREA blends only) */ - std::vector compileLights(); + /** Gather all lights in scene (AREA blends only) */ + std::vector compileLights(); - /** Get PathMesh from scene (PATH blends only) */ - PathMesh compilePathMesh(); + /** Get PathMesh from scene (PATH blends only) */ + PathMesh compilePathMesh(); - /** Compile GUI into FRME data (FRAME blends only) */ - std::vector compileGuiFrame(int version); + /** Compile GUI into FRME data (FRAME blends only) */ + std::vector compileGuiFrame(int version); - /** Gather all texture paths in scene */ - std::vector getTextures(); + /** Gather all texture paths in scene */ + std::vector getTextures(); - Actor compileActor(); - Actor compileActorCharacterOnly(); - Action compileActionChannelsOnly(std::string_view name); - std::vector getArmatureNames(); - std::vector getSubtypeNames(); - std::vector getActionNames(); - std::vector getSubtypeOverlayNames(std::string_view name); - std::vector getAttachmentNames(); + Actor compileActor(); + Actor compileActorCharacterOnly(); + Action compileActionChannelsOnly(std::string_view name); + std::vector getArmatureNames(); + std::vector getSubtypeNames(); + std::vector getActionNames(); + std::vector getSubtypeOverlayNames(std::string_view name); + std::vector getAttachmentNames(); - std::unordered_map getBoneMatrices(std::string_view name); + std::unordered_map getBoneMatrices(std::string_view name); - bool renderPvs(std::string_view path, const atVec3f& location); - bool renderPvsLight(std::string_view path, std::string_view lightName); + bool renderPvs(std::string_view path, const atVec3f& location); + bool renderPvsLight(std::string_view path, std::string_view lightName); - MapArea compileMapArea(); - MapUniverse compileMapUniverse(); + MapArea compileMapArea(); + MapUniverse compileMapUniverse(); }; -class Connection -{ - friend class DataStream; - friend class PyOutStream; - friend class ANIMOutStream; - friend struct PyOutStream::StreamBuf; - friend struct Mesh; - friend struct Material; - friend struct ColMesh; - friend struct World; - friend struct Light; - friend struct MapArea; - friend struct MapUniverse; - friend struct Actor; - friend struct Armature; - friend struct Action; - friend struct Bone; - friend struct PathMesh; - friend struct Vector2f; - friend struct Vector3f; - friend struct Vector4f; - friend struct Matrix3f; - friend struct Matrix4f; - friend struct Index; +class Connection { + friend class DataStream; + friend class PyOutStream; + friend class ANIMOutStream; + friend struct PyOutStream::StreamBuf; + friend struct Mesh; + friend struct Material; + friend struct ColMesh; + friend struct World; + friend struct Light; + friend struct MapArea; + friend struct MapUniverse; + friend struct Actor; + friend struct Armature; + friend struct Action; + friend struct Bone; + friend struct PathMesh; + friend struct Vector2f; + friend struct Vector3f; + friend struct Vector4f; + friend struct Matrix3f; + friend struct Matrix4f; + friend struct Index; - std::atomic_bool m_lock = {false}; - bool m_pyStreamActive = false; - bool m_dataStreamActive = false; + std::atomic_bool m_lock = {false}; + bool m_pyStreamActive = false; + bool m_dataStreamActive = false; #if _WIN32 - PROCESS_INFORMATION m_pinfo = {}; - std::thread m_consoleThread; - bool m_consoleThreadRunning = true; + PROCESS_INFORMATION m_pinfo = {}; + std::thread m_consoleThread; + bool m_consoleThreadRunning = true; #else - pid_t m_blenderProc = 0; + pid_t m_blenderProc = 0; #endif - int m_readpipe[2]; - int m_writepipe[2]; - bool m_hasSlerp; - BlendType m_loadedType = BlendType::None; - bool m_loadedRigged = false; - ProjectPath m_loadedBlend; - std::string m_startupBlend; - hecl::SystemString m_errPath; - uint32_t _readStr(char* buf, uint32_t bufSz); - 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) { return _writeStr(str, strlen(str)); } - size_t _readBuf(void* buf, size_t len); - size_t _writeBuf(const void* buf, size_t len); - void _closePipe(); - void _blenderDied(); + int m_readpipe[2]; + int m_writepipe[2]; + bool m_hasSlerp; + BlendType m_loadedType = BlendType::None; + bool m_loadedRigged = false; + ProjectPath m_loadedBlend; + std::string m_startupBlend; + hecl::SystemString m_errPath; + uint32_t _readStr(char* buf, uint32_t bufSz); + 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) { return _writeStr(str, strlen(str)); } + size_t _readBuf(void* buf, size_t len); + size_t _writeBuf(const void* buf, size_t len); + void _closePipe(); + void _blenderDied(); public: - Connection(int verbosityLevel=1); - ~Connection(); + Connection(int verbosityLevel = 1); + ~Connection(); - Connection(const Connection&)=delete; - Connection& operator=(const Connection&)=delete; - Connection(Connection&&)=delete; - Connection& operator=(Connection&&)=delete; + Connection(const Connection&) = delete; + Connection& operator=(const Connection&) = delete; + Connection(Connection&&) = delete; + Connection& operator=(Connection&&) = delete; - bool hasSLERP() const {return m_hasSlerp;} + bool hasSLERP() const { return m_hasSlerp; } - bool createBlend(const ProjectPath& path, BlendType type); - BlendType getBlendType() const {return m_loadedType;} - const ProjectPath& getBlendPath() const {return m_loadedBlend;} - bool getRigged() const {return m_loadedRigged;} - bool openBlend(const ProjectPath& path, bool force=false); - bool saveBlend(); - void deleteBlend(); + bool createBlend(const ProjectPath& path, BlendType type); + BlendType getBlendType() const { return m_loadedType; } + const ProjectPath& getBlendPath() const { return m_loadedBlend; } + bool getRigged() const { return m_loadedRigged; } + bool openBlend(const ProjectPath& path, bool force = false); + bool saveBlend(); + void deleteBlend(); - PyOutStream beginPythonOut(bool deleteOnError=false) - { - bool expect = false; - if (!m_lock.compare_exchange_strong(expect, true)) - BlenderLog.report(logvisor::Fatal, "lock already held for blender::Connection::beginPythonOut()"); - return PyOutStream(this, deleteOnError); - } + PyOutStream beginPythonOut(bool deleteOnError = false) { + bool expect = false; + if (!m_lock.compare_exchange_strong(expect, true)) + BlenderLog.report(logvisor::Fatal, "lock already held for blender::Connection::beginPythonOut()"); + return PyOutStream(this, deleteOnError); + } - DataStream beginData() - { - bool expect = false; - if (!m_lock.compare_exchange_strong(expect, true)) - BlenderLog.report(logvisor::Fatal, "lock already held for blender::Connection::beginDataIn()"); - return DataStream(this); - } + DataStream beginData() { + bool expect = false; + if (!m_lock.compare_exchange_strong(expect, true)) + BlenderLog.report(logvisor::Fatal, "lock already held for blender::Connection::beginDataIn()"); + return DataStream(this); + } - void quitBlender(); + void quitBlender(); - void closeStream() - { - if (m_lock) - deleteBlend(); - } + void closeStream() { + if (m_lock) + deleteBlend(); + } - static Connection& SharedConnection(); - static void Shutdown(); + static Connection& SharedConnection(); + static void Shutdown(); }; -class HMDLBuffers -{ +class HMDLBuffers { public: - struct Surface; + struct Surface; + private: - friend struct Mesh; - HMDLBuffers(HMDLMeta&& meta, - size_t vboSz, const std::vector& iboData, - std::vector&& surfaces, - const Mesh::SkinBanks& skinBanks); + friend struct Mesh; + HMDLBuffers(HMDLMeta&& meta, size_t vboSz, const std::vector& iboData, std::vector&& surfaces, + const Mesh::SkinBanks& skinBanks); + public: - HMDLMeta m_meta; - size_t m_vboSz; - std::unique_ptr m_vboData; - size_t m_iboSz; - std::unique_ptr m_iboData; + HMDLMeta m_meta; + size_t m_vboSz; + std::unique_ptr m_vboData; + size_t m_iboSz; + std::unique_ptr m_iboData; - struct Surface - { - Surface(const Mesh::Surface& origSurf, - atUint32 start, atUint32 count) - : m_origSurf(origSurf), m_start(start), m_count(count) {} - const Mesh::Surface& m_origSurf; - atUint32 m_start; - atUint32 m_count; - }; - std::vector m_surfaces; + struct Surface { + Surface(const Mesh::Surface& origSurf, atUint32 start, atUint32 count) + : m_origSurf(origSurf), m_start(start), m_count(count) {} + const Mesh::Surface& m_origSurf; + atUint32 m_start; + atUint32 m_count; + }; + std::vector m_surfaces; - const Mesh::SkinBanks& m_skinBanks; + const Mesh::SkinBanks& m_skinBanks; }; -} - +} // namespace hecl::blender diff --git a/hecl/include/hecl/Blender/SDNARead.hpp b/hecl/include/hecl/Blender/SDNARead.hpp index 12c4f8149..7cb664516 100644 --- a/hecl/include/hecl/Blender/SDNARead.hpp +++ b/hecl/include/hecl/Blender/SDNARead.hpp @@ -4,69 +4,64 @@ #include "athena/DNA.hpp" #include "athena/MemoryReader.hpp" -namespace hecl::blender -{ +namespace hecl::blender { -struct SDNABlock : public athena::io::DNA -{ +struct SDNABlock : public athena::io::DNA { + AT_DECL_DNA + DNAFourCC magic; + DNAFourCC nameMagic; + Value numNames; + Vector, AT_DNA_COUNT(numNames)> names; + Align<4> align1; + DNAFourCC typeMagic; + Value numTypes; + Vector, AT_DNA_COUNT(numTypes)> types; + Align<4> align2; + DNAFourCC tlenMagic; + Vector, AT_DNA_COUNT(numTypes)> tlens; + Align<4> align3; + DNAFourCC strcMagic; + Value numStrcs; + struct SDNAStruct : public athena::io::DNA { AT_DECL_DNA - DNAFourCC magic; - DNAFourCC nameMagic; - Value numNames; - Vector, AT_DNA_COUNT(numNames)> names; - Align<4> align1; - DNAFourCC typeMagic; - Value numTypes; - Vector, AT_DNA_COUNT(numTypes)> types; - Align<4> align2; - DNAFourCC tlenMagic; - Vector, AT_DNA_COUNT(numTypes)> tlens; - Align<4> align3; - DNAFourCC strcMagic; - Value numStrcs; - struct SDNAStruct : public athena::io::DNA - { - AT_DECL_DNA - Value type; - Value numFields; - struct SDNAField : public athena::io::DNA - { - AT_DECL_DNA - Value type; - Value name; - atUint32 offset; - }; - Vector fields; - - void computeOffsets(const SDNABlock& block); - const SDNAField* lookupField(const SDNABlock& block, const char* n) const; + Value type; + Value numFields; + struct SDNAField : public athena::io::DNA { + AT_DECL_DNA + Value type; + Value name; + atUint32 offset; }; - Vector strcs; + Vector fields; - const SDNAStruct* lookupStruct(const char* n, int& idx) const; + void computeOffsets(const SDNABlock& block); + const SDNAField* lookupField(const SDNABlock& block, const char* n) const; + }; + Vector strcs; + + const SDNAStruct* lookupStruct(const char* n, int& idx) const; }; -struct FileBlock : public athena::io::DNA -{ - AT_DECL_DNA - DNAFourCC type; - Value size; - Value ptr; - Value sdnaIdx; - Value count; +struct FileBlock : public athena::io::DNA { + AT_DECL_DNA + DNAFourCC type; + Value size; + Value ptr; + Value sdnaIdx; + Value count; }; -class SDNARead -{ - std::vector m_data; - SDNABlock m_sdnaBlock; +class SDNARead { + std::vector m_data; + SDNABlock m_sdnaBlock; + public: - explicit SDNARead(SystemStringView path); - operator bool() const { return !m_data.empty(); } - const SDNABlock& sdnaBlock() const { return m_sdnaBlock; } - void enumerate(const std::function& func) const; + explicit SDNARead(SystemStringView path); + operator bool() const { return !m_data.empty(); } + const SDNABlock& sdnaBlock() const { return m_sdnaBlock; } + void enumerate(const std::function& func) const; }; BlendType GetBlendType(SystemStringView path); -} +} // namespace hecl::blender diff --git a/hecl/include/hecl/Blender/Token.hpp b/hecl/include/hecl/Blender/Token.hpp index 3d6b214fe..59859b7e9 100644 --- a/hecl/include/hecl/Blender/Token.hpp +++ b/hecl/include/hecl/Blender/Token.hpp @@ -2,24 +2,22 @@ #include -namespace hecl::blender -{ +namespace hecl::blender { class Connection; -class Token -{ - std::unique_ptr m_conn; -public: - Connection& getBlenderConnection(); - void shutdown(); +class Token { + std::unique_ptr m_conn; - Token() = default; - ~Token(); - Token(const Token&)=delete; - Token& operator=(const Token&)=delete; - Token(Token&&)=default; - Token& operator=(Token&&)=default; +public: + Connection& getBlenderConnection(); + void shutdown(); + + Token() = default; + ~Token(); + Token(const Token&) = delete; + Token& operator=(const Token&) = delete; + Token(Token&&) = default; + Token& operator=(Token&&) = default; }; -} - +} // namespace hecl::blender diff --git a/hecl/include/hecl/CVar.hpp b/hecl/include/hecl/CVar.hpp old mode 100755 new mode 100644 index 3e7868a3f..65d30a7f5 --- a/hecl/include/hecl/CVar.hpp +++ b/hecl/include/hecl/CVar.hpp @@ -6,154 +6,146 @@ #include #include -namespace hecl -{ -namespace DNACVAR -{ -enum class EType : atUint8 -{ - Boolean, - Integer, - Float, - Literal, - Vec4f -}; +namespace hecl { +namespace DNACVAR { +enum class EType : atUint8 { Boolean, Integer, Float, Literal, Vec4f }; -enum EFlags -{ - None = -1, - System = (1 << 0), - Game = (1 << 1), - Editor = (1 << 2), - Gui = (1 << 3), - Cheat = (1 << 4), - Hidden = (1 << 5), - ReadOnly = (1 << 6), - Archive = (1 << 7), - InternalArchivable = (1 << 8), - Modified = (1 << 9), - ModifyRestart = (1 << 10) /*!< If this bit is set, any modification will inform the user that a restart is required */ +enum EFlags { + None = -1, + System = (1 << 0), + Game = (1 << 1), + Editor = (1 << 2), + Gui = (1 << 3), + Cheat = (1 << 4), + Hidden = (1 << 5), + ReadOnly = (1 << 6), + Archive = (1 << 7), + InternalArchivable = (1 << 8), + Modified = (1 << 9), + ModifyRestart = (1 << 10) /*!< If this bit is set, any modification will inform the user that a restart is required */ }; ENABLE_BITWISE_ENUM(EFlags) -class CVar : public athena::io::DNA -{ +class CVar : public athena::io::DNA { public: - AT_DECL_DNA - String<-1> m_name; - String<-1> m_value; + AT_DECL_DNA + String<-1> m_name; + String<-1> m_value; }; -struct CVarContainer : public athena::io::DNA -{ - AT_DECL_DNA - Value magic = 'CVAR'; - Value cvarCount; - Vector cvars; +struct CVarContainer : public athena::io::DNA { + AT_DECL_DNA + Value magic = 'CVAR'; + Value cvarCount; + Vector cvars; }; -} +} // namespace DNACVAR class CVarManager; -class CVar : protected DNACVAR::CVar -{ - friend class CVarManager; - Delete _d; +class CVar : protected DNACVAR::CVar { + friend class CVarManager; + Delete _d; public: - typedef std::function ListenerFunc; + typedef std::function ListenerFunc; - using EType = DNACVAR::EType; - using EFlags = DNACVAR::EFlags; + using EType = DNACVAR::EType; + using EFlags = DNACVAR::EFlags; - CVar(std::string_view name, std::string_view value, std::string_view help, EType type, EFlags flags, CVarManager& parent); - CVar(std::string_view name, std::string_view value, std::string_view help, EFlags flags, CVarManager& parent); - CVar(std::string_view name, float value, std::string_view help, EFlags flags, CVarManager& parent); - CVar(std::string_view name, bool value, std::string_view help, EFlags flags, CVarManager& parent); - CVar(std::string_view name, int value, std::string_view help, EFlags flags, CVarManager& parent); - CVar(std::string_view name, const atVec4f& value, std::string_view help, EFlags flags, CVarManager& parent); + CVar(std::string_view name, std::string_view value, std::string_view help, EType type, EFlags flags, + CVarManager& parent); + CVar(std::string_view name, std::string_view value, std::string_view help, EFlags flags, CVarManager& parent); + CVar(std::string_view name, float value, std::string_view help, EFlags flags, CVarManager& parent); + CVar(std::string_view name, bool value, std::string_view help, EFlags flags, CVarManager& parent); + CVar(std::string_view name, int value, std::string_view help, EFlags flags, CVarManager& parent); + CVar(std::string_view name, const atVec4f& value, std::string_view help, EFlags flags, CVarManager& parent); + std::string_view name() const { return m_name; } + std::string_view rawHelp() const { return m_help; } + std::string help() const; + std::string value() const { return m_value; } - std::string_view name() const { return m_name; } - std::string_view rawHelp() const { return m_help; } - std::string help() const; - std::string value() const { return m_value; } + atVec4f toVec4f(bool* isValid = nullptr) const; + float toFloat(bool* isValid = nullptr) const; + bool toBoolean(bool* isValid = nullptr) const; + int toInteger(bool* isValid = nullptr) const; + const std::wstring toWideLiteral(bool* isValid = nullptr) const; + const std::string toLiteral(bool* isValid = nullptr) const; - atVec4f toVec4f(bool* isValid = nullptr) const; - float toFloat(bool* isValid = nullptr) const; - bool toBoolean(bool* isValid = nullptr) const; - int toInteger(bool* isValid = nullptr) const; - const std::wstring toWideLiteral(bool* isValid = nullptr) const; - const std::string toLiteral(bool* isValid = nullptr) const; + bool fromVec4f(const atVec4f& val); + bool fromFloat(float val); + bool fromBoolean(bool val); + bool fromInteger(int val); + bool fromLiteral(std::string_view val); + bool fromLiteral(std::wstring_view val); + bool fromLiteralToType(std::string_view val, bool setDefault = false); + bool fromLiteralToType(std::wstring_view val, bool setDefault = false); - bool fromVec4f(const atVec4f& val); - bool fromFloat(float val); - bool fromBoolean(bool val); - bool fromInteger(int val); - bool fromLiteral(std::string_view val); - bool fromLiteral(std::wstring_view val); - bool fromLiteralToType(std::string_view val, bool setDefault = false); - bool fromLiteralToType(std::wstring_view val, bool setDefault = false); + bool isFloat() const { return m_type == EType::Float; } + bool isBoolean() const { return m_type == EType::Boolean; } + bool isInteger() const { return m_type == EType::Integer; } + bool isLiteral() const { return m_type == EType::Literal; } + bool isVec4f() const { return m_type == EType::Vec4f; } + bool isModified() const; + bool modificationRequiresRestart() const; + bool isReadOnly() const; + bool isCheat() const; + bool isHidden() const; + bool isArchive() const; + bool isInternalArchivable() const; + bool wasDeserialized() const; + bool hasDefaultValue() const; + void clearModified(); + void setModified(); - bool isFloat() const { return m_type == EType::Float; } - bool isBoolean() const { return m_type == EType::Boolean; } - bool isInteger() const { return m_type == EType::Integer; } - bool isLiteral() const { return m_type == EType::Literal; } - bool isVec4f() const { return m_type == EType::Vec4f; } - bool isModified() const; - bool modificationRequiresRestart() const; - bool isReadOnly() const; - bool isCheat() const; - bool isHidden() const; - bool isArchive() const; - bool isInternalArchivable() const; - bool wasDeserialized() const; - bool hasDefaultValue() const; - void clearModified(); - void setModified(); + EType type() const { return m_type; } + EFlags flags() const { return (m_unlocked ? m_oldFlags : m_flags); } - EType type() const { return m_type; } - EFlags flags() const { return (m_unlocked ? m_oldFlags : m_flags); } + /*! + * \brief Unlocks the CVar for writing if it is ReadOnly. + * Handle with care!!! if you use unlock(), make sure + * you lock the cvar using lock() + * \see lock + */ + void unlock(); - /*! - * \brief Unlocks the CVar for writing if it is ReadOnly. - * Handle with care!!! if you use unlock(), make sure - * you lock the cvar using lock() - * \see lock - */ - void unlock(); + /*! + * \brief Locks the CVar to prevent writing if it is ReadOnly. + * Unlike its partner function unlock, lock is harmless + * \see unlock + */ + void lock(); - /*! - * \brief Locks the CVar to prevent writing if it is ReadOnly. - * Unlike its partner function unlock, lock is harmless - * \see unlock - */ - void lock(); - - void addListener(ListenerFunc func) { m_listeners.push_back(func); } + void addListener(ListenerFunc func) { m_listeners.push_back(func); } private: - void dispatch(); - EType m_type; - std::string m_help; - std::string m_defaultValue; - EFlags m_flags; - EFlags m_oldFlags; - bool m_unlocked = false; - bool m_wasDeserialized = false; + void dispatch(); + EType m_type; + std::string m_help; + std::string m_defaultValue; + EFlags m_flags; + EFlags m_oldFlags; + bool m_unlocked = false; + bool m_wasDeserialized = false; - CVarManager& m_mgr; + CVarManager& m_mgr; - std::vector m_listeners; + std::vector m_listeners; }; -class CVarUnlocker -{ - CVar* m_cvar; +class CVarUnlocker { + CVar* m_cvar; + public: - CVarUnlocker(CVar* cvar) : m_cvar(cvar) { if (m_cvar) m_cvar->unlock(); } - ~CVarUnlocker() { if (m_cvar) m_cvar->lock(); } + CVarUnlocker(CVar* cvar) : m_cvar(cvar) { + if (m_cvar) + m_cvar->unlock(); + } + ~CVarUnlocker() { + if (m_cvar) + m_cvar->lock(); + } }; -} - +} // namespace hecl diff --git a/hecl/include/hecl/CVarCommons.hpp b/hecl/include/hecl/CVarCommons.hpp index c631181bd..026177b95 100644 --- a/hecl/include/hecl/CVarCommons.hpp +++ b/hecl/include/hecl/CVarCommons.hpp @@ -5,8 +5,7 @@ #undef min #undef max -namespace hecl -{ +namespace hecl { using namespace std::literals; @@ -18,75 +17,45 @@ using namespace std::literals; #define DEFAULT_GRAPHICS_API "OpenGL"sv #endif -struct CVarCommons -{ - CVarManager& m_mgr; - CVar* m_graphicsApi = nullptr; - CVar* m_drawSamples = nullptr; - CVar* m_texAnisotropy = nullptr; - CVar* m_deepColor = nullptr; +struct CVarCommons { + CVarManager& m_mgr; + CVar* m_graphicsApi = nullptr; + CVar* m_drawSamples = nullptr; + CVar* m_texAnisotropy = nullptr; + CVar* m_deepColor = nullptr; - CVarCommons(CVarManager& manager) : m_mgr(manager) - { - m_graphicsApi = m_mgr.findOrMakeCVar("graphicsApi"sv, - "API to use for rendering graphics"sv, - DEFAULT_GRAPHICS_API, hecl::CVar::EFlags::System | hecl::CVar::EFlags::Archive | hecl::CVar::EFlags::ModifyRestart); - m_drawSamples = m_mgr.findOrMakeCVar("drawSamples"sv, - "Number of MSAA samples to use for render targets"sv, - 1, hecl::CVar::EFlags::System | hecl::CVar::EFlags::Archive | hecl::CVar::EFlags::ModifyRestart); - m_texAnisotropy = m_mgr.findOrMakeCVar("texAnisotropy"sv, - "Number of anisotropic samples to use for sampling textures"sv, - 1, hecl::CVar::EFlags::System | hecl::CVar::EFlags::Archive | hecl::CVar::EFlags::ModifyRestart); - m_deepColor = m_mgr.findOrMakeCVar("deepColor"sv, - "Allow framebuffer with color depth greater-then 24-bits"sv, - false, hecl::CVar::EFlags::System | hecl::CVar::EFlags::Archive | hecl::CVar::EFlags::ModifyRestart); - } + CVarCommons(CVarManager& manager) : m_mgr(manager) { + m_graphicsApi = m_mgr.findOrMakeCVar("graphicsApi"sv, "API to use for rendering graphics"sv, DEFAULT_GRAPHICS_API, + hecl::CVar::EFlags::System | hecl::CVar::EFlags::Archive | + hecl::CVar::EFlags::ModifyRestart); + m_drawSamples = m_mgr.findOrMakeCVar("drawSamples"sv, "Number of MSAA samples to use for render targets"sv, 1, + hecl::CVar::EFlags::System | hecl::CVar::EFlags::Archive | + hecl::CVar::EFlags::ModifyRestart); + m_texAnisotropy = m_mgr.findOrMakeCVar( + "texAnisotropy"sv, "Number of anisotropic samples to use for sampling textures"sv, 1, + hecl::CVar::EFlags::System | hecl::CVar::EFlags::Archive | hecl::CVar::EFlags::ModifyRestart); + m_deepColor = m_mgr.findOrMakeCVar( + "deepColor"sv, "Allow framebuffer with color depth greater-then 24-bits"sv, false, + hecl::CVar::EFlags::System | hecl::CVar::EFlags::Archive | hecl::CVar::EFlags::ModifyRestart); + } - std::string getGraphicsApi() const - { - return m_graphicsApi->toLiteral(); - } + std::string getGraphicsApi() const { return m_graphicsApi->toLiteral(); } - void setGraphicsApi(std::string_view api) - { - m_graphicsApi->fromLiteral(api); - } + void setGraphicsApi(std::string_view api) { m_graphicsApi->fromLiteral(api); } - uint32_t getSamples() const - { - return std::max(uint32_t(1), uint32_t(m_drawSamples->toInteger())); - } + uint32_t getSamples() const { return std::max(uint32_t(1), uint32_t(m_drawSamples->toInteger())); } - void setSamples(uint32_t v) - { - m_drawSamples->fromInteger(std::max(uint32_t(1), v)); - } + void setSamples(uint32_t v) { m_drawSamples->fromInteger(std::max(uint32_t(1), v)); } - uint32_t getAnisotropy() const - { - return std::max(uint32_t(1), uint32_t(m_texAnisotropy->toInteger())); - } + uint32_t getAnisotropy() const { return std::max(uint32_t(1), uint32_t(m_texAnisotropy->toInteger())); } - void setAnisotropy(uint32_t v) - { - m_texAnisotropy->fromInteger(std::max(uint32_t(1), v)); - } + void setAnisotropy(uint32_t v) { m_texAnisotropy->fromInteger(std::max(uint32_t(1), v)); } - bool getDeepColor() const - { - return m_deepColor->toBoolean(); - } + bool getDeepColor() const { return m_deepColor->toBoolean(); } - void setDeepColor(bool b) - { - m_deepColor->fromBoolean(b); - } + void setDeepColor(bool b) { m_deepColor->fromBoolean(b); } - void serialize() - { - m_mgr.serialize(); - } + void serialize() { m_mgr.serialize(); } }; -} - +} // namespace hecl diff --git a/hecl/include/hecl/CVarManager.hpp b/hecl/include/hecl/CVarManager.hpp old mode 100755 new mode 100644 index 1576b2ad1..95cea1ae3 --- a/hecl/include/hecl/CVarManager.hpp +++ b/hecl/include/hecl/CVarManager.hpp @@ -5,86 +5,85 @@ #include "CVar.hpp" #include "hecl/SystemChar.hpp" -namespace hecl -{ -namespace Runtime -{ +namespace hecl { +namespace Runtime { class FileStoreManager; } extern CVar* com_developer; extern CVar* com_configfile; extern CVar* com_enableCheats; -class CVarManager final -{ - using CVarContainer = DNACVAR::CVarContainer; - template - CVar* _newCVar(std::string_view name, std::string_view help, const T& value, CVar::EFlags flags) - { - if (CVar* ret = registerCVar(std::make_unique(name, value, help, flags, *this))) - { - deserialize(ret); - return ret; - } - return nullptr; +class CVarManager final { + using CVarContainer = DNACVAR::CVarContainer; + template + CVar* _newCVar(std::string_view name, std::string_view help, const T& value, CVar::EFlags flags) { + if (CVar* ret = registerCVar(std::make_unique(name, value, help, flags, *this))) { + deserialize(ret); + return ret; } + return nullptr; + } + + hecl::Runtime::FileStoreManager& m_store; + bool m_useBinary; + static CVarManager* m_instance; - hecl::Runtime::FileStoreManager& m_store; - bool m_useBinary; - static CVarManager* m_instance; public: - CVarManager() = delete; - CVarManager(const CVarManager&) = delete; - CVarManager& operator=(const CVarManager&) = delete; - CVarManager& operator=(const CVarManager&&) = delete; - CVarManager(hecl::Runtime::FileStoreManager& store, bool useBinary = false); - ~CVarManager(); + CVarManager() = delete; + CVarManager(const CVarManager&) = delete; + CVarManager& operator=(const CVarManager&) = delete; + CVarManager& operator=(const CVarManager&&) = delete; + CVarManager(hecl::Runtime::FileStoreManager& store, bool useBinary = false); + ~CVarManager(); - CVar* newCVar(std::string_view name, std::string_view help, const atVec4f& value, CVar::EFlags flags) - { return _newCVar(name, help, value, flags); } - CVar* newCVar(std::string_view name, std::string_view help, std::string_view value, CVar::EFlags flags) - { return _newCVar(name, help, value, flags); } - CVar* newCVar(std::string_view name, std::string_view help, bool value, CVar::EFlags flags) - { return _newCVar(name, help, value, flags); } - CVar* newCVar(std::string_view name, std::string_view help, float value, CVar::EFlags flags) - { return _newCVar(name, help, value, flags); } - CVar* newCVar(std::string_view name, std::string_view help, int value, CVar::EFlags flags) - { return _newCVar(name, help, value, flags); } + CVar* newCVar(std::string_view name, std::string_view help, const atVec4f& value, CVar::EFlags flags) { + return _newCVar(name, help, value, flags); + } + CVar* newCVar(std::string_view name, std::string_view help, std::string_view value, CVar::EFlags flags) { + return _newCVar(name, help, value, flags); + } + CVar* newCVar(std::string_view name, std::string_view help, bool value, CVar::EFlags flags) { + return _newCVar(name, help, value, flags); + } + CVar* newCVar(std::string_view name, std::string_view help, float value, CVar::EFlags flags) { + return _newCVar(name, help, value, flags); + } + CVar* newCVar(std::string_view name, std::string_view help, int value, CVar::EFlags flags) { + return _newCVar(name, help, value, flags); + } - CVar* registerCVar(std::unique_ptr&& cvar); + CVar* registerCVar(std::unique_ptr&& cvar); - CVar* findCVar(std::string_view name); - template - CVar* findOrMakeCVar(std::string_view name, _Args&&... args) - { - if (CVar* cv = findCVar(name)) - return cv; - return newCVar(name, std::forward<_Args>(args)...); - } + CVar* findCVar(std::string_view name); + template + CVar* findOrMakeCVar(std::string_view name, _Args&&... args) { + if (CVar* cv = findCVar(name)) + return cv; + return newCVar(name, std::forward<_Args>(args)...); + } - std::vector archivedCVars() const; - std::vector cvars(CVar::EFlags filter = CVar::EFlags::None) const; + std::vector archivedCVars() const; + std::vector cvars(CVar::EFlags filter = CVar::EFlags::None) const; - void deserialize(CVar* cvar); - void serialize(); + void deserialize(CVar* cvar); + void serialize(); - static CVarManager* instance(); + static CVarManager* instance(); - void list(class Console* con, const std::vector& args); - void setCVar(class Console* con, const std::vector& args); - void getCVar(class Console* con, const std::vector& args); + void list(class Console* con, const std::vector& args); + void setCVar(class Console* con, const std::vector& args); + void getCVar(class Console* con, const std::vector& args); + void setDeveloperMode(bool v, bool setDeserialized = false); + bool restartRequired() const; - void setDeveloperMode(bool v, bool setDeserialized=false); - bool restartRequired() const; + void parseCommandLine(const std::vector& args); - void parseCommandLine(const std::vector& args); private: - bool suppressDeveloper(); - void restoreDeveloper(bool oldDeveloper); + bool suppressDeveloper(); + void restoreDeveloper(bool oldDeveloper); - std::unordered_map> m_cvars; - std::unordered_map m_deferedCVars; + std::unordered_map> m_cvars; + std::unordered_map m_deferedCVars; }; -} - +} // namespace hecl diff --git a/hecl/include/hecl/ClientProcess.hpp b/hecl/include/hecl/ClientProcess.hpp index 7a05fde3f..92418819e 100644 --- a/hecl/include/hecl/ClientProcess.hpp +++ b/hecl/include/hecl/ClientProcess.hpp @@ -9,111 +9,89 @@ #include #include -namespace hecl -{ +namespace hecl { -class ClientProcess -{ - std::mutex m_mutex; - std::condition_variable m_cv; - std::condition_variable m_initCv; - std::condition_variable m_waitCv; - const MultiProgressPrinter* m_progPrinter; - int m_completedCooks = 0; - int m_addedCooks = 0; +class ClientProcess { + std::mutex m_mutex; + std::condition_variable m_cv; + std::condition_variable m_initCv; + std::condition_variable m_waitCv; + const MultiProgressPrinter* m_progPrinter; + int m_completedCooks = 0; + int m_addedCooks = 0; public: - struct Transaction - { - ClientProcess& m_parent; - enum class Type - { - Buffer, - Cook, - Lambda - } m_type; - bool m_complete = false; - virtual void run(blender::Token& btok)=0; - Transaction(ClientProcess& parent, Type tp) : m_parent(parent), m_type(tp) {} - }; - struct BufferTransaction final : Transaction - { - ProjectPath m_path; - void* m_targetBuf; - size_t m_maxLen; - size_t m_offset; - void run(blender::Token& btok); - BufferTransaction(ClientProcess& parent, const ProjectPath& path, - void* target, size_t maxLen, size_t offset) - : Transaction(parent, Type::Buffer), - m_path(path), m_targetBuf(target), - m_maxLen(maxLen), m_offset(offset) {} - }; - struct CookTransaction final : Transaction - { - ProjectPath m_path; - Database::IDataSpec* m_dataSpec; - bool m_returnResult = false; - bool m_force; - bool m_fast; - void run(blender::Token& btok); - CookTransaction(ClientProcess& parent, const ProjectPath& path, - bool force, bool fast, Database::IDataSpec* spec) - : Transaction(parent, Type::Cook), m_path(path), m_dataSpec(spec), - m_force(force), m_fast(fast) {} - }; - struct LambdaTransaction final : Transaction - { - std::function m_func; - void run(blender::Token& btok); - LambdaTransaction(ClientProcess& parent, std::function&& func) - : Transaction(parent, Type::Lambda), m_func(std::move(func)) {} - }; + struct Transaction { + ClientProcess& m_parent; + enum class Type { Buffer, Cook, Lambda } m_type; + bool m_complete = false; + virtual void run(blender::Token& btok) = 0; + Transaction(ClientProcess& parent, Type tp) : m_parent(parent), m_type(tp) {} + }; + struct BufferTransaction final : Transaction { + ProjectPath m_path; + void* m_targetBuf; + size_t m_maxLen; + size_t m_offset; + void run(blender::Token& btok); + BufferTransaction(ClientProcess& parent, const ProjectPath& path, void* target, size_t maxLen, size_t offset) + : Transaction(parent, Type::Buffer), m_path(path), m_targetBuf(target), m_maxLen(maxLen), m_offset(offset) {} + }; + struct CookTransaction final : Transaction { + ProjectPath m_path; + Database::IDataSpec* m_dataSpec; + bool m_returnResult = false; + bool m_force; + bool m_fast; + void run(blender::Token& btok); + CookTransaction(ClientProcess& parent, const ProjectPath& path, bool force, bool fast, Database::IDataSpec* spec) + : Transaction(parent, Type::Cook), m_path(path), m_dataSpec(spec), m_force(force), m_fast(fast) {} + }; + struct LambdaTransaction final : Transaction { + std::function m_func; + void run(blender::Token& btok); + LambdaTransaction(ClientProcess& parent, std::function&& func) + : Transaction(parent, Type::Lambda), m_func(std::move(func)) {} + }; + private: - std::list> m_pendingQueue; - std::list> m_completedQueue; - int m_inProgress = 0; - bool m_running = true; + std::list> m_pendingQueue; + std::list> m_completedQueue; + int m_inProgress = 0; + bool m_running = true; - struct Worker - { - ClientProcess& m_proc; - int m_idx; - std::thread m_thr; - blender::Token m_blendTok; - bool m_didInit = false; - Worker(ClientProcess& proc, int idx); - void proc(); - }; - std::vector m_workers; - static ThreadLocalPtr ThreadWorker; + struct Worker { + ClientProcess& m_proc; + int m_idx; + std::thread m_thr; + blender::Token m_blendTok; + bool m_didInit = false; + Worker(ClientProcess& proc, int idx); + void proc(); + }; + std::vector m_workers; + static ThreadLocalPtr ThreadWorker; public: - ClientProcess(const MultiProgressPrinter* progPrinter=nullptr); - ~ClientProcess() {shutdown();} - std::shared_ptr - addBufferTransaction(const hecl::ProjectPath& path, void* target, - size_t maxLen, size_t offset); - std::shared_ptr - addCookTransaction(const hecl::ProjectPath& path, bool force, - bool fast, Database::IDataSpec* spec); - std::shared_ptr - addLambdaTransaction(std::function&& func); - bool syncCook(const hecl::ProjectPath& path, Database::IDataSpec* spec, blender::Token& btok, - bool force, bool fast); - void swapCompletedQueue(std::list>& queue); - void waitUntilComplete(); - void shutdown(); - bool isBusy() const { return m_pendingQueue.size() || m_inProgress; } + ClientProcess(const MultiProgressPrinter* progPrinter = nullptr); + ~ClientProcess() { shutdown(); } + std::shared_ptr addBufferTransaction(const hecl::ProjectPath& path, void* target, + size_t maxLen, size_t offset); + std::shared_ptr addCookTransaction(const hecl::ProjectPath& path, bool force, bool fast, + Database::IDataSpec* spec); + std::shared_ptr addLambdaTransaction(std::function&& func); + bool syncCook(const hecl::ProjectPath& path, Database::IDataSpec* spec, blender::Token& btok, bool force, bool fast); + void swapCompletedQueue(std::list>& queue); + void waitUntilComplete(); + void shutdown(); + bool isBusy() const { return m_pendingQueue.size() || m_inProgress; } - static int GetThreadWorkerIdx() - { - Worker* w = ThreadWorker.get(); - if (w) - return w->m_idx; - return -1; - } + static int GetThreadWorkerIdx() { + Worker* w = ThreadWorker.get(); + if (w) + return w->m_idx; + return -1; + } }; -} - +} // namespace hecl diff --git a/hecl/include/hecl/Compilers.hpp b/hecl/include/hecl/Compilers.hpp index f5b32c9b1..aff1eb18d 100644 --- a/hecl/include/hecl/Compilers.hpp +++ b/hecl/include/hecl/Compilers.hpp @@ -5,66 +5,87 @@ #include "boo/graphicsdev/D3D.hpp" #include "boo/graphicsdev/Metal.hpp" -namespace hecl -{ +namespace hecl { -namespace PlatformType -{ +namespace PlatformType { using PlatformEnum = boo::IGraphicsDataFactory::Platform; struct Null {}; -struct OpenGL { static constexpr PlatformEnum Enum = PlatformEnum::OpenGL; static const char* Name; +struct OpenGL { + static constexpr PlatformEnum Enum = PlatformEnum::OpenGL; + static const char* Name; #if BOO_HAS_GL -using Context = boo::GLDataFactory::Context; + using Context = boo::GLDataFactory::Context; #endif }; -struct D3D11 { static constexpr PlatformEnum Enum = PlatformEnum::D3D11; static const char* Name; +struct D3D11 { + static constexpr PlatformEnum Enum = PlatformEnum::D3D11; + static const char* Name; #if _WIN32 -using Context = boo::D3D11DataFactory::Context; + using Context = boo::D3D11DataFactory::Context; #endif }; -struct Metal { static constexpr PlatformEnum Enum = PlatformEnum::Metal; static const char* Name; +struct Metal { + static constexpr PlatformEnum Enum = PlatformEnum::Metal; + static const char* Name; #if BOO_HAS_METAL -using Context = boo::MetalDataFactory::Context; + using Context = boo::MetalDataFactory::Context; #endif }; -struct Vulkan { static constexpr PlatformEnum Enum = PlatformEnum::Vulkan; static const char* Name; +struct Vulkan { + static constexpr PlatformEnum Enum = PlatformEnum::Vulkan; + static const char* Name; #if BOO_HAS_VULKAN -using Context = boo::VulkanDataFactory::Context; + using Context = boo::VulkanDataFactory::Context; #endif }; -struct NX { static constexpr PlatformEnum Enum = PlatformEnum::NX; static const char* Name; +struct NX { + static constexpr PlatformEnum Enum = PlatformEnum::NX; + static const char* Name; #if BOO_HAS_NX -using Context = boo::NXDataFactory::Context; + using Context = boo::NXDataFactory::Context; #endif }; -} +} // namespace PlatformType -namespace PipelineStage -{ +namespace PipelineStage { using StageEnum = boo::PipelineStage; -struct Null { static constexpr StageEnum Enum = StageEnum::Null; static const char* Name; }; -struct Vertex { static constexpr StageEnum Enum = StageEnum::Vertex; static const char* Name; }; -struct Fragment { static constexpr StageEnum Enum = StageEnum::Fragment; static const char* Name; }; -struct Geometry { static constexpr StageEnum Enum = StageEnum::Geometry; static const char* Name; }; -struct Control { static constexpr StageEnum Enum = StageEnum::Control; static const char* Name; }; -struct Evaluation { static constexpr StageEnum Enum = StageEnum::Evaluation; static const char* Name; }; -} +struct Null { + static constexpr StageEnum Enum = StageEnum::Null; + static const char* Name; +}; +struct Vertex { + static constexpr StageEnum Enum = StageEnum::Vertex; + static const char* Name; +}; +struct Fragment { + static constexpr StageEnum Enum = StageEnum::Fragment; + static const char* Name; +}; +struct Geometry { + static constexpr StageEnum Enum = StageEnum::Geometry; + static const char* Name; +}; +struct Control { + static constexpr StageEnum Enum = StageEnum::Control; + static const char* Name; +}; +struct Evaluation { + static constexpr StageEnum Enum = StageEnum::Evaluation; + static const char* Name; +}; +} // namespace PipelineStage #ifdef __APPLE__ using StageBinaryData = std::shared_ptr; -static inline StageBinaryData MakeStageBinaryData(size_t sz) -{ - return StageBinaryData(new uint8_t[sz], std::default_delete{}); +static inline StageBinaryData MakeStageBinaryData(size_t sz) { + return StageBinaryData(new uint8_t[sz], std::default_delete{}); } #else using StageBinaryData = std::shared_ptr; -static inline StageBinaryData MakeStageBinaryData(size_t sz) -{ - return StageBinaryData(new uint8_t[sz]); -} +static inline StageBinaryData MakeStageBinaryData(size_t sz) { return StageBinaryData(new uint8_t[sz]); } #endif -template +template std::pair CompileShader(std::string_view text); -} +} // namespace hecl diff --git a/hecl/include/hecl/Console.hpp b/hecl/include/hecl/Console.hpp index 8ee0b0109..8458afbf1 100644 --- a/hecl/include/hecl/Console.hpp +++ b/hecl/include/hecl/Console.hpp @@ -7,108 +7,89 @@ #include "boo/IWindow.hpp" #include "logvisor/logvisor.hpp" -namespace hecl -{ +namespace hecl { class CVarManager; class CVar; -struct SConsoleCommand -{ - enum class ECommandFlags - { - Normal = 0, - Cheat = (1 << 0), - Developer = (1 << 1) - }; - std::string m_displayName; - std::string m_helpString; - std::string m_usage; - std::function&)> m_func; - ECommandFlags m_flags; +struct SConsoleCommand { + enum class ECommandFlags { Normal = 0, Cheat = (1 << 0), Developer = (1 << 1) }; + std::string m_displayName; + std::string m_helpString; + std::string m_usage; + std::function&)> m_func; + ECommandFlags m_flags; }; ENABLE_BITWISE_ENUM(SConsoleCommand::ECommandFlags) -class Console -{ - friend class LogVisorAdapter; - struct LogVisorAdapter : logvisor::ILogger - { - Console* m_con; - LogVisorAdapter(Console* con) - : m_con(con) {} +class Console { + friend class LogVisorAdapter; + struct LogVisorAdapter : logvisor::ILogger { + Console* m_con; + LogVisorAdapter(Console* con) : m_con(con) {} - ~LogVisorAdapter() {} - void report(const char* modName, logvisor::Level severity, - const char* format, va_list ap); - void report(const char* modName, logvisor::Level severity, - const wchar_t* format, va_list ap); - void reportSource(const char* modName, logvisor::Level severity, - const char* file, unsigned linenum, - const char* format, va_list ap); - void reportSource(const char* modName, logvisor::Level severity, - const char* file, unsigned linenum, - const wchar_t* format, va_list ap); - }; + ~LogVisorAdapter() {} + void report(const char* modName, logvisor::Level severity, const char* format, va_list ap); + void report(const char* modName, logvisor::Level severity, const wchar_t* format, va_list ap); + void reportSource(const char* modName, logvisor::Level severity, const char* file, unsigned linenum, + const char* format, va_list ap); + void reportSource(const char* modName, logvisor::Level severity, const char* file, unsigned linenum, + const wchar_t* format, va_list ap); + }; public: - static Console* m_instance; - enum class Level - { - Info, /**< Non-error informative message */ - Warning, /**< Non-error warning message */ - Error, /**< Recoverable error message */ - Fatal /**< Non-recoverable error message (Kept for compatibility with logvisor) */ - }; + static Console* m_instance; + enum class Level { + Info, /**< Non-error informative message */ + Warning, /**< Non-error warning message */ + Error, /**< Recoverable error message */ + Fatal /**< Non-recoverable error message (Kept for compatibility with logvisor) */ + }; - enum State - { - Closed, - Closing, - Opened, - Opening - }; + enum State { Closed, Closing, Opened, Opening }; private: - CVarManager* m_cvarMgr; - std::unordered_map m_commands; - std::vector> m_log; - int m_logOffset; - std::string m_commandString; - std::vector m_commandHistory; - int m_cursorPosition = -1; - int m_currentCommand = -1; - size_t m_maxLines = 0; - bool m_overwrite : 1; - bool m_cursorAtEnd : 1; - State m_state = State::Closed; - CVar* m_conSpeed; - CVar* m_conHeight; - float m_cachedConSpeed; - float m_cachedConHeight; - bool m_showCursor = true; - float m_cursorTime = 0.f; + CVarManager* m_cvarMgr; + std::unordered_map m_commands; + std::vector> m_log; + int m_logOffset; + std::string m_commandString; + std::vector m_commandHistory; + int m_cursorPosition = -1; + int m_currentCommand = -1; + size_t m_maxLines = 0; + bool m_overwrite : 1; + bool m_cursorAtEnd : 1; + State m_state = State::Closed; + CVar* m_conSpeed; + CVar* m_conHeight; + float m_cachedConSpeed; + float m_cachedConHeight; + bool m_showCursor = true; + float m_cursorTime = 0.f; + public: - Console(CVarManager*); - void registerCommand(std::string_view name, std::string_view helpText, std::string_view usage, const std::function&)>&& func, SConsoleCommand::ECommandFlags cmdFlags = SConsoleCommand::ECommandFlags::Normal); - void unregisterCommand(std::string_view name); + Console(CVarManager*); + void registerCommand(std::string_view name, std::string_view helpText, std::string_view usage, + const std::function&)>&& func, + SConsoleCommand::ECommandFlags cmdFlags = SConsoleCommand::ECommandFlags::Normal); + void unregisterCommand(std::string_view name); - void executeString(const std::string& strToExec); + void executeString(const std::string& strToExec); - void help(Console* con, const std::vector& args); - void listCommands(Console* con, const std::vector& args); - bool commandExists(std::string_view cmd); + void help(Console* con, const std::vector& args); + void listCommands(Console* con, const std::vector& args); + bool commandExists(std::string_view cmd); - void report(Level level, const char *fmt, va_list list); - void report(Level level, const char* fmt, ...); + void report(Level level, const char* fmt, va_list list); + void report(Level level, const char* fmt, ...); - void proc(); - void draw(boo::IGraphicsCommandQueue* gfxQ); - void handleCharCode(unsigned long chr, boo::EModifierKey mod, bool repeat); - void handleSpecialKeyDown(boo::ESpecialKey sp, boo::EModifierKey mod, bool repeat); - void handleSpecialKeyUp(boo::ESpecialKey sp, boo::EModifierKey mod); - void dumpLog(); - static Console* instance(); - static void RegisterLogger(Console* con); - bool isOpen() { return m_state == State::Opened; } + void proc(); + void draw(boo::IGraphicsCommandQueue* gfxQ); + void handleCharCode(unsigned long chr, boo::EModifierKey mod, bool repeat); + void handleSpecialKeyDown(boo::ESpecialKey sp, boo::EModifierKey mod, bool repeat); + void handleSpecialKeyUp(boo::ESpecialKey sp, boo::EModifierKey mod); + void dumpLog(); + static Console* instance(); + static void RegisterLogger(Console* con); + bool isOpen() { return m_state == State::Opened; } }; -} - +} // namespace hecl diff --git a/hecl/include/hecl/Database.hpp b/hecl/include/hecl/Database.hpp index 7b6f448c7..d0822b1fb 100644 --- a/hecl/include/hecl/Database.hpp +++ b/hecl/include/hecl/Database.hpp @@ -21,12 +21,10 @@ #define RUNTIME_ORIGINAL_IDS 0 -namespace hecl -{ +namespace hecl { class ClientProcess; -namespace Database -{ +namespace Database { class Project; extern logvisor::Module LogModule; @@ -34,27 +32,23 @@ extern logvisor::Module LogModule; /** * @brief Nodegraph class for gathering dependency-resolved objects for packaging */ -class PackageDepsgraph -{ +class PackageDepsgraph { public: - struct Node - { - enum class Type - { - Data, - Group - } type; - ProjectPath path; - ProjectPath cookedPath; - class ObjectBase* projectObj; - Node* sub; - Node* next; - }; + struct Node { + enum class Type { Data, Group } type; + ProjectPath path; + ProjectPath cookedPath; + class ObjectBase* projectObj; + Node* sub; + Node* next; + }; + private: - friend class Project; - std::vector m_nodes; + friend class Project; + std::vector m_nodes; + public: - const Node* getRootNode() const {return &m_nodes[0];} + const Node* getRootNode() const { return &m_nodes[0]; } }; /** @@ -63,78 +57,88 @@ public: * The DataSpec class manages interfaces for unpackaging, cooking, and packaging * of data for interacting with a specific system/game-engine. */ -class IDataSpec -{ - const DataSpecEntry* m_specEntry; +class IDataSpec { + const DataSpecEntry* m_specEntry; + public: - IDataSpec(const DataSpecEntry* specEntry) : m_specEntry(specEntry) {} - virtual ~IDataSpec() {} - using FCookProgress = std::function; + IDataSpec(const DataSpecEntry* specEntry) : m_specEntry(specEntry) {} + virtual ~IDataSpec() {} + using FCookProgress = std::function; - /** - * @brief Extract Pass Info - * - * An extract pass iterates through a source package or image and - * reverses the cooking process by emitting editable resources - */ - struct ExtractPassInfo - { - SystemString srcpath; - std::vector extractArgs; - bool force; - }; + /** + * @brief Extract Pass Info + * + * An extract pass iterates through a source package or image and + * reverses the cooking process by emitting editable resources + */ + struct ExtractPassInfo { + SystemString srcpath; + std::vector extractArgs; + bool force; + }; - /** - * @brief Extract Report Representation - * - * Constructed by canExtract() to advise the user of the content about - * to be extracted - */ - struct ExtractReport - { - SystemString name; - SystemString desc; - std::vector childOpts; - }; + /** + * @brief Extract Report Representation + * + * Constructed by canExtract() to advise the user of the content about + * to be extracted + */ + struct ExtractReport { + SystemString name; + SystemString desc; + std::vector childOpts; + }; - virtual void setThreadProject() {} + virtual void setThreadProject() {} - virtual bool canExtract(const ExtractPassInfo& info, std::vector& reps) - {(void)info;(void)reps;LogModule.report(logvisor::Error, "not implemented");return false;} - virtual void doExtract(const ExtractPassInfo& info, const MultiProgressPrinter& progress) - {(void)info;(void)progress;} + virtual bool canExtract(const ExtractPassInfo& info, std::vector& reps) { + (void)info; + (void)reps; + LogModule.report(logvisor::Error, "not implemented"); + return false; + } + virtual void doExtract(const ExtractPassInfo& info, const MultiProgressPrinter& progress) { + (void)info; + (void)progress; + } - virtual bool canCook(const ProjectPath& path, blender::Token& btok, int cookPass = -1) - {(void)path;LogModule.report(logvisor::Error, "not implemented");(void)cookPass;return false;} - virtual const DataSpecEntry* overrideDataSpec(const ProjectPath& path, - const Database::DataSpecEntry* oldEntry, - blender::Token& btok) const - {(void)path;return oldEntry;} - virtual void doCook(const ProjectPath& path, const ProjectPath& cookedPath, - bool fast, blender::Token& btok, FCookProgress progress) - {(void)path;(void)cookedPath;(void)fast;(void)progress;} + virtual bool canCook(const ProjectPath& path, blender::Token& btok, int cookPass = -1) { + (void)path; + LogModule.report(logvisor::Error, "not implemented"); + (void)cookPass; + return false; + } + virtual const DataSpecEntry* overrideDataSpec(const ProjectPath& path, const Database::DataSpecEntry* oldEntry, + blender::Token& btok) const { + (void)path; + return oldEntry; + } + virtual void doCook(const ProjectPath& path, const ProjectPath& cookedPath, bool fast, blender::Token& btok, + FCookProgress progress) { + (void)path; + (void)cookedPath; + (void)fast; + (void)progress; + } - virtual bool canPackage(const ProjectPath& path) - {(void)path;return false;} - virtual void doPackage(const ProjectPath& path, const Database::DataSpecEntry* entry, - bool fast, blender::Token& btok, const MultiProgressPrinter& progress, - ClientProcess* cp=nullptr) - {(void)path;} + virtual bool canPackage(const ProjectPath& path) { + (void)path; + return false; + } + virtual void doPackage(const ProjectPath& path, const Database::DataSpecEntry* entry, bool fast, blender::Token& btok, + const MultiProgressPrinter& progress, ClientProcess* cp = nullptr) { + (void)path; + } - virtual void interruptCook() {} + virtual void interruptCook() {} - const DataSpecEntry* getDataSpecEntry() const {return m_specEntry;} + const DataSpecEntry* getDataSpecEntry() const { return m_specEntry; } }; /** * @brief Pre-emptive indication of what the constructed DataSpec is used for */ -enum class DataSpecTool -{ - Extract, - Cook, - Package -}; +enum class DataSpecTool { Extract, Cook, Package }; extern std::vector DATA_SPEC_REGISTRY; @@ -143,18 +147,16 @@ extern std::vector DATA_SPEC_REGISTRY; * * Auto-registers with data spec registry */ -struct DataSpecEntry -{ - SystemStringView m_name; - SystemStringView m_desc; - SystemStringView m_pakExt; - int m_numCookPasses; - std::function(Project&, DataSpecTool)> m_factory; +struct DataSpecEntry { + SystemStringView m_name; + SystemStringView m_desc; + SystemStringView m_pakExt; + int m_numCookPasses; + std::function(Project&, DataSpecTool)> m_factory; - DataSpecEntry(SystemStringView name, SystemStringView desc, SystemStringView pakExt, int numCookPasses, - std::function(Project& project, DataSpecTool)>&& factory) - : m_name(name), m_desc(desc), m_pakExt(pakExt), m_numCookPasses(numCookPasses), - m_factory(std::move(factory)) {} + DataSpecEntry(SystemStringView name, SystemStringView desc, SystemStringView pakExt, int numCookPasses, + std::function(Project& project, DataSpecTool)>&& factory) + : m_name(name), m_desc(desc), m_pakExt(pakExt), m_numCookPasses(numCookPasses), m_factory(std::move(factory)) {} }; /** @@ -166,79 +168,74 @@ struct DataSpecEntry * * DO NOT CONSTRUCT THIS OR SUBCLASSES DIRECTLY!! */ -class ObjectBase -{ - friend class Project; - SystemString m_path; +class ObjectBase { + friend class Project; + SystemString m_path; + protected: + /** + * @brief Byte-order of target system + */ + enum class DataEndianness { + None, + Big, /**< Big-endian (PowerPC) */ + Little /**< Little-endian (Intel) */ + }; - /** - * @brief Byte-order of target system - */ - enum class DataEndianness - { - None, - Big, /**< Big-endian (PowerPC) */ - Little /**< Little-endian (Intel) */ - }; + /** + * @brief Data-formats of target system + */ + enum class DataPlatform { + None, + Generic, /**< Scanline textures and 3-way shader bundle (GLSL, HLSL, SPIR-V) */ + Revolution, /**< Tiled textures and GX register buffers */ + Cafe /**< Swizzled textures and R700 shader objects */ + }; - /** - * @brief Data-formats of target system - */ - enum class DataPlatform - { - None, - Generic, /**< Scanline textures and 3-way shader bundle (GLSL, HLSL, SPIR-V) */ - Revolution, /**< Tiled textures and GX register buffers */ - Cafe /**< Swizzled textures and R700 shader objects */ - }; + typedef std::function FDataAppender; - typedef std::function FDataAppender; + /** + * @brief Optional private method implemented by subclasses to cook objects + * @param dataAppender subclass calls this function zero or more times to provide cooked-data linearly + * @param endianness byte-order to target + * @param platform data-formats to target + * @return true if cook succeeded + * + * This method is called during IProject::cookPath(). + * Part of the cooking process may include embedding database-refs to dependencies. + * This method should store the 64-bit value provided by IDataObject::id() when doing this. + */ + virtual bool cookObject(FDataAppender dataAppender, DataEndianness endianness, DataPlatform platform) { + (void)dataAppender; + (void)endianness; + (void)platform; + return true; + } - /** - * @brief Optional private method implemented by subclasses to cook objects - * @param dataAppender subclass calls this function zero or more times to provide cooked-data linearly - * @param endianness byte-order to target - * @param platform data-formats to target - * @return true if cook succeeded - * - * This method is called during IProject::cookPath(). - * Part of the cooking process may include embedding database-refs to dependencies. - * This method should store the 64-bit value provided by IDataObject::id() when doing this. - */ - virtual bool cookObject(FDataAppender dataAppender, - DataEndianness endianness, DataPlatform platform) - {(void)dataAppender;(void)endianness;(void)platform;return true;} + typedef std::function FDepAdder; - typedef std::function FDepAdder; + /** + * @brief Optional private method implemented by CProjectObject subclasses to resolve dependencies + * @param depAdder subclass calls this function zero or more times to register each dependency + * + * This method is called during IProject::packagePath(). + * Dependencies registered via this method will eventually have this method called on themselves + * as well. This is a non-recursive operation, no need for subclasses to implement recursion-control. + */ + virtual void gatherDeps(FDepAdder depAdder) { (void)depAdder; } - /** - * @brief Optional private method implemented by CProjectObject subclasses to resolve dependencies - * @param depAdder subclass calls this function zero or more times to register each dependency - * - * This method is called during IProject::packagePath(). - * Dependencies registered via this method will eventually have this method called on themselves - * as well. This is a non-recursive operation, no need for subclasses to implement recursion-control. - */ - virtual void gatherDeps(FDepAdder depAdder) - {(void)depAdder;} - - /** - * @brief Get a packagable FourCC representation of the object's type - * @return FourCC of the type - */ - virtual FourCC getType() const - {return FourCC("NULL");} + /** + * @brief Get a packagable FourCC representation of the object's type + * @return FourCC of the type + */ + virtual FourCC getType() const { return FourCC("NULL"); } public: - ObjectBase(SystemStringView path) - : m_path(path) {} - - SystemStringView getPath() const {return m_path;} + ObjectBase(SystemStringView path) : m_path(path) {} + SystemStringView getPath() const { return m_path; } }; - /** * @brief Main project interface * @@ -246,237 +243,226 @@ public: * resources in their ideal editor-formats. This interface exposes all * primary operations to perform on a given project. */ -class Project -{ +class Project { public: - struct ProjectDataSpec - { - const DataSpecEntry& spec; - ProjectPath cookedPath; - bool active; - }; + struct ProjectDataSpec { + const DataSpecEntry& spec; + ProjectPath cookedPath; + bool active; + }; + private: - ProjectRootPath m_rootPath; - ProjectPath m_workRoot; - ProjectPath m_dotPath; - ProjectPath m_cookedRoot; - std::vector m_compiledSpecs; - std::unordered_map m_bridgePathCache; - std::vector> m_cookSpecs; - std::unique_ptr m_lastPackageSpec; - bool m_valid = false; + ProjectRootPath m_rootPath; + ProjectPath m_workRoot; + ProjectPath m_dotPath; + ProjectPath m_cookedRoot; + std::vector m_compiledSpecs; + std::unordered_map m_bridgePathCache; + std::vector> m_cookSpecs; + std::unique_ptr m_lastPackageSpec; + bool m_valid = false; + public: - Project(const ProjectRootPath& rootPath); - operator bool() const {return m_valid;} + Project(const ProjectRootPath& rootPath); + operator bool() const { return m_valid; } - /** - * @brief Configuration file handle - * - * Holds a path to a line-delimited textual configuration file; - * opening a locked handle for read/write transactions - */ - class ConfigFile - { - SystemString m_filepath; - std::vector m_lines; - FILE* m_lockedFile = NULL; - public: - ConfigFile(const Project& project, SystemStringView name, - SystemStringView subdir=_SYS_STR("/.hecl/")); - std::vector& lockAndRead(); - void addLine(std::string_view line); - void removeLine(std::string_view refLine); - bool checkForLine(std::string_view refLine); - void unlockAndDiscard(); - bool unlockAndCommit(); - }; - ConfigFile m_specs; - ConfigFile m_paths; - ConfigFile m_groups; + /** + * @brief Configuration file handle + * + * Holds a path to a line-delimited textual configuration file; + * opening a locked handle for read/write transactions + */ + class ConfigFile { + SystemString m_filepath; + std::vector m_lines; + FILE* m_lockedFile = NULL; - /** - * @brief A rough description of how 'expensive' a given cook operation is - * - * This is used to provide pretty colors during the cook operation - */ - enum class Cost - { - None, - Light, - Medium, - Heavy - }; + public: + ConfigFile(const Project& project, SystemStringView name, SystemStringView subdir = _SYS_STR("/.hecl/")); + std::vector& lockAndRead(); + void addLine(std::string_view line); + void removeLine(std::string_view refLine); + bool checkForLine(std::string_view refLine); + void unlockAndDiscard(); + bool unlockAndCommit(); + }; + ConfigFile m_specs; + ConfigFile m_paths; + ConfigFile m_groups; - /** - * @brief Get the path of the project's root-directory - * @return project root path - * - * Self explanatory - */ - const ProjectRootPath& getProjectRootPath() const {return m_rootPath;} + /** + * @brief A rough description of how 'expensive' a given cook operation is + * + * This is used to provide pretty colors during the cook operation + */ + enum class Cost { None, Light, Medium, Heavy }; - /** - * @brief Get the path of project's working directory - * @return project working path - */ - const ProjectPath& getProjectWorkingPath() const {return m_workRoot;} + /** + * @brief Get the path of the project's root-directory + * @return project root path + * + * Self explanatory + */ + const ProjectRootPath& getProjectRootPath() const { return m_rootPath; } - /** - * @brief Get the path of project's cooked directory for a specific DataSpec - * @param DataSpec to retrieve path for - * @return project cooked path - * - * The cooked path matches the directory layout of the working directory - */ - const ProjectPath& getProjectCookedPath(const DataSpecEntry& spec) const; + /** + * @brief Get the path of project's working directory + * @return project working path + */ + const ProjectPath& getProjectWorkingPath() const { return m_workRoot; } - /** - * @brief Add given file(s) to the database - * @param path file or pattern within project - * @return true on success - * - * This method blocks while object hashing takes place - */ - bool addPaths(const std::vector& paths); + /** + * @brief Get the path of project's cooked directory for a specific DataSpec + * @param DataSpec to retrieve path for + * @return project cooked path + * + * The cooked path matches the directory layout of the working directory + */ + const ProjectPath& getProjectCookedPath(const DataSpecEntry& spec) const; - /** - * @brief Remove a given file or file-pattern from the database - * @param paths file(s) or pattern(s) within project - * @param recursive traverse into matched subdirectories - * @return true on success - * - * This method will not delete actual working files from the project - * directory. It will delete associated cooked objects though. - */ - bool removePaths(const std::vector& paths, bool recursive=false); + /** + * @brief Add given file(s) to the database + * @param path file or pattern within project + * @return true on success + * + * This method blocks while object hashing takes place + */ + bool addPaths(const std::vector& paths); - /** - * @brief Register a working sub-directory as a Dependency Group - * @param path directory to register as Dependency Group - * @return true on success - * - * Dependency Groups are used at runtime to stage burst load-transactions. - * They may only be added to directories and will automatically claim - * subdirectories as well. - * - * Cooked objects in dependency groups will be packaged contiguously - * and automatically duplicated if shared with other dependency groups. - * This contiguous storage makes for optimal loading from slow block-devices - * like optical drives. - */ - bool addGroup(const ProjectPath& path); + /** + * @brief Remove a given file or file-pattern from the database + * @param paths file(s) or pattern(s) within project + * @param recursive traverse into matched subdirectories + * @return true on success + * + * This method will not delete actual working files from the project + * directory. It will delete associated cooked objects though. + */ + bool removePaths(const std::vector& paths, bool recursive = false); - /** - * @brief Unregister a working sub-directory as a dependency group - * @param path directory to unregister as Dependency Group - * @return true on success - */ - bool removeGroup(const ProjectPath& path); + /** + * @brief Register a working sub-directory as a Dependency Group + * @param path directory to register as Dependency Group + * @return true on success + * + * Dependency Groups are used at runtime to stage burst load-transactions. + * They may only be added to directories and will automatically claim + * subdirectories as well. + * + * Cooked objects in dependency groups will be packaged contiguously + * and automatically duplicated if shared with other dependency groups. + * This contiguous storage makes for optimal loading from slow block-devices + * like optical drives. + */ + bool addGroup(const ProjectPath& path); - /** - * @brief Re-reads the data store holding user's spec preferences - * - * Call periodically in a long-term use of the hecl::Database::Project class. - * Install filesystem event-hooks if possible. - */ - void rescanDataSpecs(); + /** + * @brief Unregister a working sub-directory as a dependency group + * @param path directory to unregister as Dependency Group + * @return true on success + */ + bool removeGroup(const ProjectPath& path); - /** - * @brief Return map populated with dataspecs targetable by this project interface - * @return Platform map with name-string keys and enable-status values - */ - const std::vector& getDataSpecs() const {return m_compiledSpecs;} + /** + * @brief Re-reads the data store holding user's spec preferences + * + * Call periodically in a long-term use of the hecl::Database::Project class. + * Install filesystem event-hooks if possible. + */ + void rescanDataSpecs(); - /** - * @brief Enable persistent user preference for particular spec string(s) - * @param specs String(s) representing unique spec(s) from getDataSpecs - * @return true on success - */ - bool enableDataSpecs(const std::vector& specs); + /** + * @brief Return map populated with dataspecs targetable by this project interface + * @return Platform map with name-string keys and enable-status values + */ + const std::vector& getDataSpecs() const { return m_compiledSpecs; } - /** - * @brief Disable persistent user preference for particular spec string(s) - * @param specs String(s) representing unique spec(s) from getDataSpecs - * @return true on success - */ - bool disableDataSpecs(const std::vector& specs); + /** + * @brief Enable persistent user preference for particular spec string(s) + * @param specs String(s) representing unique spec(s) from getDataSpecs + * @return true on success + */ + bool enableDataSpecs(const std::vector& specs); - /** - * @brief Begin cook process for specified directory - * @param path directory of intermediates to cook - * @param feedbackCb a callback to run reporting cook-progress - * @param recursive traverse subdirectories to cook as well - * @param fast enables faster (draft) extraction for supported data types - * @param spec if non-null, cook using a manually-selected dataspec - * @param cp if non-null, cook asynchronously via the ClientProcess - * @param cookPass cookPath() should be called the number of times - * prescribed in DataSpecEntry at the root-most invocation. - * This value conveys the pass index through the call tree. - * Negative values mean "cook always". - * @return true on success - * - * Object cooking is generally an expensive process for large projects. - * This method blocks execution during the procedure, with periodic - * feedback delivered via feedbackCb. - */ - bool cookPath(const ProjectPath& path, const MultiProgressPrinter& feedbackCb, - bool recursive=false, bool force=false, bool fast=false, - const DataSpecEntry* spec=nullptr, ClientProcess* cp=nullptr, - int cookPass = -1); + /** + * @brief Disable persistent user preference for particular spec string(s) + * @param specs String(s) representing unique spec(s) from getDataSpecs + * @return true on success + */ + bool disableDataSpecs(const std::vector& specs); - /** - * @brief Begin package process for specified !world.blend or directory - * @param path Path to !world.blend or directory - * @param feedbackCb a callback to run reporting cook-progress - * @param fast enables faster (draft) extraction for supported data types - * @param spec if non-null, cook using a manually-selected dataspec - * @param cp if non-null, cook asynchronously via the ClientProcess - */ - bool packagePath(const ProjectPath& path, const MultiProgressPrinter& feedbackCb, - bool fast=false, const DataSpecEntry* spec=nullptr, - ClientProcess* cp=nullptr); + /** + * @brief Begin cook process for specified directory + * @param path directory of intermediates to cook + * @param feedbackCb a callback to run reporting cook-progress + * @param recursive traverse subdirectories to cook as well + * @param fast enables faster (draft) extraction for supported data types + * @param spec if non-null, cook using a manually-selected dataspec + * @param cp if non-null, cook asynchronously via the ClientProcess + * @param cookPass cookPath() should be called the number of times + * prescribed in DataSpecEntry at the root-most invocation. + * This value conveys the pass index through the call tree. + * Negative values mean "cook always". + * @return true on success + * + * Object cooking is generally an expensive process for large projects. + * This method blocks execution during the procedure, with periodic + * feedback delivered via feedbackCb. + */ + bool cookPath(const ProjectPath& path, const MultiProgressPrinter& feedbackCb, bool recursive = false, + bool force = false, bool fast = false, const DataSpecEntry* spec = nullptr, ClientProcess* cp = nullptr, + int cookPass = -1); - /** - * @brief Interrupts a cook in progress (call from SIGINT handler) - * - * Database corruption is bad! HECL spreads its data objects through - * the filesystem; this ensures that open objects are cleanly - * finalized or discarded before stopping. - * - * Note that this method returns immediately; the resumed cookPath() - * call will return as quickly as possible. - */ - void interruptCook(); + /** + * @brief Begin package process for specified !world.blend or directory + * @param path Path to !world.blend or directory + * @param feedbackCb a callback to run reporting cook-progress + * @param fast enables faster (draft) extraction for supported data types + * @param spec if non-null, cook using a manually-selected dataspec + * @param cp if non-null, cook asynchronously via the ClientProcess + */ + bool packagePath(const ProjectPath& path, const MultiProgressPrinter& feedbackCb, bool fast = false, + const DataSpecEntry* spec = nullptr, ClientProcess* cp = nullptr); - /** - * @brief Delete cooked objects for directory - * @param path directory of intermediates to clean - * @param recursive traverse subdirectories to clean as well - * @return true on success - * - * Developers understand how useful 'clean' is. While ideally not required, - * it's useful for verifying that a rebuild from ground-up is doable. - */ - bool cleanPath(const ProjectPath& path, bool recursive=false); + /** + * @brief Interrupts a cook in progress (call from SIGINT handler) + * + * Database corruption is bad! HECL spreads its data objects through + * the filesystem; this ensures that open objects are cleanly + * finalized or discarded before stopping. + * + * Note that this method returns immediately; the resumed cookPath() + * call will return as quickly as possible. + */ + void interruptCook(); - /** - * @brief Constructs a full depsgraph of the project-subpath provided - * @param path Subpath of project to root depsgraph at - * @return Populated depsgraph ready to traverse - */ - PackageDepsgraph buildPackageDepsgraph(const ProjectPath& path); + /** + * @brief Delete cooked objects for directory + * @param path directory of intermediates to clean + * @param recursive traverse subdirectories to clean as well + * @return true on success + * + * Developers understand how useful 'clean' is. While ideally not required, + * it's useful for verifying that a rebuild from ground-up is doable. + */ + bool cleanPath(const ProjectPath& path, bool recursive = false); - /** Add ProjectPath to bridge cache */ - void addBridgePathToCache(uint64_t id, const ProjectPath& path); + /** + * @brief Constructs a full depsgraph of the project-subpath provided + * @param path Subpath of project to root depsgraph at + * @return Populated depsgraph ready to traverse + */ + PackageDepsgraph buildPackageDepsgraph(const ProjectPath& path); - /** Clear all ProjectPaths in bridge cache */ - void clearBridgePathCache(); + /** Add ProjectPath to bridge cache */ + void addBridgePathToCache(uint64_t id, const ProjectPath& path); - /** Lookup ProjectPath from bridge cache */ - const ProjectPath* lookupBridgePath(uint64_t id) const; + /** Clear all ProjectPaths in bridge cache */ + void clearBridgePathCache(); + /** Lookup ProjectPath from bridge cache */ + const ProjectPath* lookupBridgePath(uint64_t id) const; }; -} -} - +} // namespace Database +} // namespace hecl diff --git a/hecl/include/hecl/FourCC.hpp b/hecl/include/hecl/FourCC.hpp index c0147027f..9d5c3f91f 100644 --- a/hecl/include/hecl/FourCC.hpp +++ b/hecl/include/hecl/FourCC.hpp @@ -5,8 +5,7 @@ #include #include "athena/DNA.hpp" -namespace hecl -{ +namespace hecl { /** * @brief FourCC representation used within HECL's database @@ -15,73 +14,73 @@ namespace hecl * while fitting comfortably in a 32-bit word. HECL uses a four-char array * to remain endian-independent. */ -class FourCC -{ +class FourCC { protected: - union - { - char fcc[4]; - uint32_t num; - }; + union { + char fcc[4]; + uint32_t num; + }; + public: - FourCC() /* Sentinel FourCC */ - : num(0) {} - FourCC(const FourCC& other) - {num = other.num;} - FourCC(const char* name) - : num(*(uint32_t*)name) {} - FourCC(uint32_t n) - : num(n) {} - bool operator==(const FourCC& other) const {return num == other.num;} - bool operator!=(const FourCC& other) const {return num != other.num;} - bool operator==(const char* other) const {return num == *(uint32_t*)other;} - bool operator!=(const char* other) const {return num != *(uint32_t*)other;} - bool operator==(int32_t other) const { return num == other;} - bool operator!=(int32_t other) const { return num != other;} - 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);} - uint32_t toUint32() const {return num;} - operator uint32_t() const {return num;} - const char* getChars() const {return fcc;} - char* getChars() {return fcc;} + FourCC() /* Sentinel FourCC */ + : num(0) {} + FourCC(const FourCC& other) { num = other.num; } + FourCC(const char* name) : num(*(uint32_t*)name) {} + FourCC(uint32_t n) : num(n) {} + bool operator==(const FourCC& other) const { return num == other.num; } + bool operator!=(const FourCC& other) const { return num != other.num; } + bool operator==(const char* other) const { return num == *(uint32_t*)other; } + bool operator!=(const char* other) const { return num != *(uint32_t*)other; } + bool operator==(int32_t other) const { return num == other; } + bool operator!=(int32_t other) const { return num != other; } + 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); } + uint32_t toUint32() const { return num; } + operator uint32_t() const { return num; } + const char* getChars() const { return fcc; } + char* getChars() { return fcc; } }; #define FOURCC(chars) FourCC(SBIG(chars)) using BigDNA = athena::io::DNA; /** FourCC with DNA read/write */ -class DNAFourCC final : public BigDNA, public FourCC -{ +class DNAFourCC final : public BigDNA, public FourCC { public: - DNAFourCC() : FourCC() {} - DNAFourCC(const FourCC& other) - : FourCC() {num = other.toUint32();} - DNAFourCC(const char* name) - : FourCC(name) {} - DNAFourCC(uint32_t n) - : FourCC(n) {} - AT_DECL_EXPLICIT_DNA_YAML + DNAFourCC() : FourCC() {} + DNAFourCC(const FourCC& other) : FourCC() { num = other.toUint32(); } + DNAFourCC(const char* name) : FourCC(name) {} + DNAFourCC(uint32_t n) : FourCC(n) {} + AT_DECL_EXPLICIT_DNA_YAML }; -template <> inline void DNAFourCC::Enumerate(typename Read::StreamT& r) -{ r.readUBytesToBuf(fcc, 4); } -template <> inline void DNAFourCC::Enumerate(typename Write::StreamT& w) -{ w.writeUBytes((atUint8*)fcc, 4); } -template <> inline void DNAFourCC::Enumerate(typename ReadYaml::StreamT& r) -{ std::string rs = r.readString(nullptr); strncpy(fcc, rs.c_str(), 4); } -template <> inline void DNAFourCC::Enumerate(typename WriteYaml::StreamT& w) -{ w.writeString(nullptr, std::string(fcc, 4)); } -template <> inline void DNAFourCC::Enumerate(typename BinarySize::StreamT& s) -{ s += 4; } - +template <> +inline void DNAFourCC::Enumerate(typename Read::StreamT& r) { + r.readUBytesToBuf(fcc, 4); +} +template <> +inline void DNAFourCC::Enumerate(typename Write::StreamT& w) { + w.writeUBytes((atUint8*)fcc, 4); +} +template <> +inline void DNAFourCC::Enumerate(typename ReadYaml::StreamT& r) { + std::string rs = r.readString(nullptr); + strncpy(fcc, rs.c_str(), 4); +} +template <> +inline void DNAFourCC::Enumerate(typename WriteYaml::StreamT& w) { + w.writeString(nullptr, std::string(fcc, 4)); +} +template <> +inline void DNAFourCC::Enumerate(typename BinarySize::StreamT& s) { + s += 4; } -namespace std -{ -template <> struct hash -{ - size_t operator()(const hecl::FourCC& val) const noexcept - {return val.toUint32();} -}; -} +} // namespace hecl +namespace std { +template <> +struct hash { + size_t operator()(const hecl::FourCC& val) const noexcept { return val.toUint32(); } +}; +} // namespace std diff --git a/hecl/include/hecl/Frontend.hpp b/hecl/include/hecl/Frontend.hpp index 0748281be..ff2a4e785 100644 --- a/hecl/include/hecl/Frontend.hpp +++ b/hecl/include/hecl/Frontend.hpp @@ -8,372 +8,341 @@ #include #include -namespace hecl::Frontend -{ +namespace hecl::Frontend { using namespace std::literals; -struct SourceLocation -{ - int line = -1; - int col = -1; - SourceLocation() = default; - SourceLocation(int l, int c) : line(l), col(c) {} +struct SourceLocation { + int line = -1; + int col = -1; + SourceLocation() = default; + SourceLocation(int l, int c) : line(l), col(c) {} }; -class Diagnostics -{ - std::string m_name; - std::string m_source; - std::string m_backend = "Backend"; - std::string sourceDiagString(const SourceLocation& l, bool ansi=false) const; -public: - void reset(std::string_view name, std::string_view source) {m_name = name; m_source = source;} - void reset(std::string_view name) {m_name = name; m_source.clear();} - void setBackend(std::string_view backend) {m_backend = backend;} - void reportScannerErr(const SourceLocation& l, const char* format, ...); - void reportParserErr(const SourceLocation& l, const char* format, ...); - void reportBackendErr(const SourceLocation& l, const char* format, ...); - - std::string_view getName() const {return m_name;} - std::string_view getSource() const {return m_source;} -}; - -struct Token -{ - enum class Kind - { - None, - Eof, - Lf, - Plus, - Minus, - Times, - Div, - Lpar, - Rpar, - Comma, - Period, - Ident, - Number - }; - - static std::string_view KindToStr(Kind k) - { - switch (k) - { - case Kind::None: - default: - return "none"sv; - case Kind::Eof: return "eof"sv; - case Kind::Lf: return "lf"sv; - case Kind::Plus: return "+"sv; - case Kind::Minus: return "-"sv; - case Kind::Times: return "*"sv; - case Kind::Div: return "/"sv; - case Kind::Lpar: return "("sv; - case Kind::Rpar: return ")"sv; - case Kind::Comma: return ","sv; - case Kind::Period: return "."sv; - case Kind::Ident: return "ident"sv; - case Kind::Number: return "number"sv; - } - } - - Kind kind = Kind::None; - std::string str; - SourceLocation loc; - - Token() = default; - Token(Kind kind, const SourceLocation& loc) - : kind(kind), loc(loc) {} - Token(Kind kind, std::string&& str, const SourceLocation& loc) - : kind(kind), str(std::move(str)), loc(loc) {} - - std::string toString() const - { - if (str.empty()) - return hecl::Format("%d:%d: %s", loc.line, loc.col, KindToStr(kind).data()); - else - return hecl::Format("%d:%d: %s (%s)", loc.line, loc.col, KindToStr(kind).data(), str.c_str()); - } -}; - -class Scanner -{ - friend class Parser; - static constexpr char LF = '\n'; - static constexpr char COMMENT = '#'; - - Diagnostics& m_diag; - std::string_view m_source; - std::string_view::const_iterator m_sourceIt; - char ch; - SourceLocation loc; - int lfcol; - - std::string lastLine; - std::string currentLine; - - Token::Kind CharToTokenKind(char ch) - { - switch (ch) - { - case '(': return Token::Kind::Lpar; - case ')': return Token::Kind::Rpar; - case ',': return Token::Kind::Comma; - case '.': return Token::Kind::Period; - case '+': return Token::Kind::Plus; - case '-': return Token::Kind::Minus; - case '*': return Token::Kind::Times; - case '/': return Token::Kind::Div; - default: return Token::Kind::None; - } - } - - template - void error(const SourceLocation& loc, const char* s, Args&&... args) - { - m_diag.reportScannerErr(loc, s, args...); - } - - static bool isDigit(char c) - { - return c >= '0' && c <= '9'; - } - - static bool isStartIdent(char c) - { - return (c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z') || - (c == '_'); - } - - static bool isMidIdent(char c) - { - return (c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z') || - (c == '_') || isDigit(c); - } - - int _read(); - bool read(); - - static char chr(char c) { return (c < 32) ? '.' : c; } +class Diagnostics { + std::string m_name; + std::string m_source; + std::string m_backend = "Backend"; + std::string sourceDiagString(const SourceLocation& l, bool ansi = false) const; public: - Scanner(Diagnostics& diag) : m_diag(diag) {} + void reset(std::string_view name, std::string_view source) { + m_name = name; + m_source = source; + } + void reset(std::string_view name) { + m_name = name; + m_source.clear(); + } + void setBackend(std::string_view backend) { m_backend = backend; } + void reportScannerErr(const SourceLocation& l, const char* format, ...); + void reportParserErr(const SourceLocation& l, const char* format, ...); + void reportBackendErr(const SourceLocation& l, const char* format, ...); - void reset(std::string_view in) - { - m_source = in; - m_sourceIt = in.cbegin(); - ch = 0; - loc.line = 1; - loc.col = 0; - lfcol = 0; - lastLine = std::string(); - currentLine = std::string(); - read(); - } - - Token next(); + std::string_view getName() const { return m_name; } + std::string_view getSource() const { return m_source; } }; -struct IRNode -{ - friend struct IR; +struct Token { + enum class Kind { None, Eof, Lf, Plus, Minus, Times, Div, Lpar, Rpar, Comma, Period, Ident, Number }; - enum class Op - { - Add, Sub, Mul, Div - }; - enum class Kind - { - None, Call, Imm, Binop, Swizzle - }; - Kind kind = Kind::None; - std::string str; - float val; - Op op; - std::unique_ptr left; - std::unique_ptr right; - std::list children; - SourceLocation loc; - - static std::string_view OpToStr(Op op) - { - switch (op) - { - case Op::Add: return "+"sv; - case Op::Sub: return "-"sv; - case Op::Mul: return "*"sv; - case Op::Div: return "/"sv; - default: return ""sv; - } + static std::string_view KindToStr(Kind k) { + switch (k) { + case Kind::None: + default: + return "none"sv; + case Kind::Eof: + return "eof"sv; + case Kind::Lf: + return "lf"sv; + case Kind::Plus: + return "+"sv; + case Kind::Minus: + return "-"sv; + case Kind::Times: + return "*"sv; + case Kind::Div: + return "/"sv; + case Kind::Lpar: + return "("sv; + case Kind::Rpar: + return ")"sv; + case Kind::Comma: + return ","sv; + case Kind::Period: + return "."sv; + case Kind::Ident: + return "ident"sv; + case Kind::Number: + return "number"sv; } + } - static std::string_view KindToStr(Kind k) - { - switch (k) - { - case Kind::None: - default: - return "none"sv; - case Kind::Call: return "call"sv; - case Kind::Imm: return "imm"sv; - case Kind::Binop: return "binop"sv; - case Kind::Swizzle: return "swizzle"sv; - } + Kind kind = Kind::None; + std::string str; + SourceLocation loc; + + Token() = default; + Token(Kind kind, const SourceLocation& loc) : kind(kind), loc(loc) {} + Token(Kind kind, std::string&& str, const SourceLocation& loc) : kind(kind), str(std::move(str)), loc(loc) {} + + std::string toString() const { + if (str.empty()) + return hecl::Format("%d:%d: %s", loc.line, loc.col, KindToStr(kind).data()); + else + return hecl::Format("%d:%d: %s (%s)", loc.line, loc.col, KindToStr(kind).data(), str.c_str()); + } +}; + +class Scanner { + friend class Parser; + static constexpr char LF = '\n'; + static constexpr char COMMENT = '#'; + + Diagnostics& m_diag; + std::string_view m_source; + std::string_view::const_iterator m_sourceIt; + char ch; + SourceLocation loc; + int lfcol; + + std::string lastLine; + std::string currentLine; + + Token::Kind CharToTokenKind(char ch) { + switch (ch) { + case '(': + return Token::Kind::Lpar; + case ')': + return Token::Kind::Rpar; + case ',': + return Token::Kind::Comma; + case '.': + return Token::Kind::Period; + case '+': + return Token::Kind::Plus; + case '-': + return Token::Kind::Minus; + case '*': + return Token::Kind::Times; + case '/': + return Token::Kind::Div; + default: + return Token::Kind::None; } + } - IRNode() = default; - IRNode(Kind kind, std::string&& str, const SourceLocation& loc) - : kind(kind), str(std::move(str)), loc(loc) {} - IRNode(Kind kind, float val, const SourceLocation& loc) - : kind(kind), val(val), loc(loc) {} - IRNode(Kind kind, std::string&& str, std::list&& children, const SourceLocation& loc) - : kind(kind), str(std::move(str)), children(std::move(children)), loc(loc) {} - IRNode(Op op, IRNode&& left, IRNode&& right, const SourceLocation& loc) - : kind(Kind::Binop), op(op), left(new IRNode(std::move(left))), right(new IRNode(std::move(right))), loc(loc) {} - IRNode(Kind kind, std::string&& str, IRNode&& node, const SourceLocation& loc) - : kind(kind), str(std::move(str)), left(new IRNode(std::move(node))), loc(loc) {} + template + void error(const SourceLocation& loc, const char* s, Args&&... args) { + m_diag.reportScannerErr(loc, s, args...); + } - std::string toString(bool stripUVAnims = false) const { return fmt(0, stripUVAnims); } + static bool isDigit(char c) { return c >= '0' && c <= '9'; } + + static bool isStartIdent(char c) { return (c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z') || (c == '_'); } + + static bool isMidIdent(char c) { + return (c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z') || (c == '_') || isDigit(c); + } + + int _read(); + bool read(); + + static char chr(char c) { return (c < 32) ? '.' : c; } + +public: + Scanner(Diagnostics& diag) : m_diag(diag) {} + + void reset(std::string_view in) { + m_source = in; + m_sourceIt = in.cbegin(); + ch = 0; + loc.line = 1; + loc.col = 0; + lfcol = 0; + lastLine = std::string(); + currentLine = std::string(); + read(); + } + + Token next(); +}; + +struct IRNode { + friend struct IR; + + enum class Op { Add, Sub, Mul, Div }; + enum class Kind { None, Call, Imm, Binop, Swizzle }; + Kind kind = Kind::None; + std::string str; + float val; + Op op; + std::unique_ptr left; + std::unique_ptr right; + std::list children; + SourceLocation loc; + + static std::string_view OpToStr(Op op) { + switch (op) { + case Op::Add: + return "+"sv; + case Op::Sub: + return "-"sv; + case Op::Mul: + return "*"sv; + case Op::Div: + return "/"sv; + default: + return ""sv; + } + } + + static std::string_view KindToStr(Kind k) { + switch (k) { + case Kind::None: + default: + return "none"sv; + case Kind::Call: + return "call"sv; + case Kind::Imm: + return "imm"sv; + case Kind::Binop: + return "binop"sv; + case Kind::Swizzle: + return "swizzle"sv; + } + } + + IRNode() = default; + IRNode(Kind kind, std::string&& str, const SourceLocation& loc) : kind(kind), str(std::move(str)), loc(loc) {} + IRNode(Kind kind, float val, const SourceLocation& loc) : kind(kind), val(val), loc(loc) {} + IRNode(Kind kind, std::string&& str, std::list&& children, const SourceLocation& loc) + : kind(kind), str(std::move(str)), children(std::move(children)), loc(loc) {} + IRNode(Op op, IRNode&& left, IRNode&& right, const SourceLocation& loc) + : kind(Kind::Binop), op(op), left(new IRNode(std::move(left))), right(new IRNode(std::move(right))), loc(loc) {} + IRNode(Kind kind, std::string&& str, IRNode&& node, const SourceLocation& loc) + : kind(kind), str(std::move(str)), left(new IRNode(std::move(node))), loc(loc) {} + + std::string toString(bool stripUVAnims = false) const { return fmt(0, stripUVAnims); } private: - static std::string rep(int n, std::string_view s); - std::string fmt(int level, bool stripUVAnims) const; - std::string describe() const; + static std::string rep(int n, std::string_view s); + std::string fmt(int level, bool stripUVAnims) const; + std::string describe() const; }; -class Parser -{ - Scanner m_scanner; +class Parser { + Scanner m_scanner; - Token t; - Token la; - Token::Kind sym; + Token t; + Token la; + Token::Kind sym; - void scan() - { - t = la; - la = m_scanner.next(); - sym = la.kind; - } + void scan() { + t = la; + la = m_scanner.next(); + sym = la.kind; + } - template - void error(const char* s, Args&&... args) - { - m_scanner.m_diag.reportParserErr(la.loc, s, args...); - } + template + void error(const char* s, Args&&... args) { + m_scanner.m_diag.reportParserErr(la.loc, s, args...); + } - void check(Token::Kind expected); - IRNode call(); - static bool imm(const IRNode& a, const IRNode& b); - IRNode expr(); - IRNode sum(); - IRNode factor(); - IRNode value(); + void check(Token::Kind expected); + IRNode call(); + static bool imm(const IRNode& a, const IRNode& b); + IRNode expr(); + IRNode sum(); + IRNode factor(); + IRNode value(); public: - Parser(Diagnostics& diag) - : m_scanner(diag) {} + Parser(Diagnostics& diag) : m_scanner(diag) {} - void reset(std::string_view in) { la = Token(); m_scanner.reset(in); } - std::list parse(); + void reset(std::string_view in) { + la = Token(); + m_scanner.reset(in); + } + std::list parse(); }; using BigDNA = athena::io::DNA; -struct IR : BigDNA -{ +struct IR : BigDNA { + AT_DECL_EXPLICIT_DNA + + enum OpType : uint8_t { + None, /**< NOP */ + Call, /**< Deferred function insertion for HECL backend using specified I/O regs */ + LoadImm, /**< Load a constant (numeric literal) into register */ + Arithmetic, /**< Perform binary arithmetic between registers */ + Swizzle /**< Vector insertion/extraction/swizzling operation */ + }; + + using RegID = atUint16; + + struct Instruction : BigDNA { AT_DECL_EXPLICIT_DNA - enum OpType : uint8_t - { - None, /**< NOP */ - Call, /**< Deferred function insertion for HECL backend using specified I/O regs */ - LoadImm, /**< Load a constant (numeric literal) into register */ - Arithmetic, /**< Perform binary arithmetic between registers */ - Swizzle /**< Vector insertion/extraction/swizzling operation */ - }; + OpType m_op = OpType::None; + RegID m_target = RegID(-1); + SourceLocation m_loc; - using RegID = atUint16; + struct Call : BigDNA { + AT_DECL_DNA + String<-1> m_name; + Value m_argInstCount; + Vector m_argInstIdxs; + } m_call; - struct Instruction : BigDNA - { - AT_DECL_EXPLICIT_DNA + struct LoadImm : BigDNA { + AT_DECL_DNA + Value m_immVec = {}; + } m_loadImm; - OpType m_op = OpType::None; - RegID m_target = RegID(-1); - SourceLocation m_loc; + enum ArithmeticOpType : uint8_t { None, Add, Subtract, Multiply, Divide }; - struct Call : BigDNA - { - AT_DECL_DNA - String<-1> m_name; - Value m_argInstCount; - Vector m_argInstIdxs; - } m_call; + struct Arithmetic : BigDNA { + AT_DECL_DNA + Value m_op = ArithmeticOpType::None; + Value m_instIdxs[2]; + } m_arithmetic; - struct LoadImm : BigDNA - { - AT_DECL_DNA - Value m_immVec = {}; - } m_loadImm; + struct Swizzle : BigDNA { + AT_DECL_DNA + Value m_idxs[4] = {-1, -1, -1, -1}; + Value m_instIdx; + } m_swizzle; - enum ArithmeticOpType : uint8_t - { - None, - Add, - Subtract, - Multiply, - Divide - }; + Instruction(OpType type, RegID target, const SourceLocation& loc) : m_op(type), m_target(target), m_loc(loc) {} + int getChildCount() const; + const IR::Instruction& getChildInst(const IR& ir, size_t idx) const; + const atVec4f& getImmVec() const; - struct Arithmetic : BigDNA - { - AT_DECL_DNA - Value m_op = ArithmeticOpType::None; - Value m_instIdxs[2]; - } m_arithmetic; + Instruction(athena::io::IStreamReader& reader) { read(reader); } + }; - struct Swizzle : BigDNA - { - AT_DECL_DNA - Value m_idxs[4] = {-1, -1, -1, -1}; - Value m_instIdx; - } m_swizzle; + atUint64 m_hash = 0; + atUint16 m_regCount = 0; + std::vector m_instructions; - Instruction(OpType type, RegID target, const SourceLocation& loc) - : m_op(type), m_target(target), m_loc(loc) {} - int getChildCount() const; - const IR::Instruction& getChildInst(const IR& ir, size_t idx) const; - const atVec4f& getImmVec() const; + boo::BlendFactor m_blendSrc = boo::BlendFactor::One; + boo::BlendFactor m_blendDst = boo::BlendFactor::Zero; + bool m_doAlpha = false; - Instruction(athena::io::IStreamReader& reader) {read(reader);} - }; - - atUint64 m_hash = 0; - atUint16 m_regCount = 0; - std::vector m_instructions; - - boo::BlendFactor m_blendSrc = boo::BlendFactor::One; - boo::BlendFactor m_blendDst = boo::BlendFactor::Zero; - bool m_doAlpha = false; - - static atInt8 swizzleCompIdx(char aChar); - int addInstruction(const IRNode& n, IR::RegID target); + static atInt8 swizzleCompIdx(char aChar); + int addInstruction(const IRNode& n, IR::RegID target); }; -class Frontend -{ - Diagnostics m_diag; - Parser m_parser; +class Frontend { + Diagnostics m_diag; + Parser m_parser; + public: - IR compileSource(std::string_view source, std::string_view diagName); - Diagnostics& getDiagnostics() { return m_diag; } - Frontend() : m_parser(m_diag) {} + IR compileSource(std::string_view source, std::string_view diagName); + Diagnostics& getDiagnostics() { return m_diag; } + Frontend() : m_parser(m_diag) {} }; -} - +} // namespace hecl::Frontend diff --git a/hecl/include/hecl/HMDLMeta.hpp b/hecl/include/hecl/HMDLMeta.hpp index 14c509de7..d82ff12db 100644 --- a/hecl/include/hecl/HMDLMeta.hpp +++ b/hecl/include/hecl/HMDLMeta.hpp @@ -3,30 +3,26 @@ #include "hecl/hecl.hpp" #include "athena/DNA.hpp" -namespace hecl -{ +namespace hecl { -enum class HMDLTopology : atUint32 -{ - Triangles, - TriStrips, +enum class HMDLTopology : atUint32 { + Triangles, + TriStrips, }; #define HECL_HMDL_META_SZ 32 -struct HMDLMeta : athena::io::DNA -{ - AT_DECL_DNA - Value magic = 'TACO'; - Value topology; - Value vertStride; - Value vertCount; - Value indexCount; - Value colorCount; - Value uvCount; - Value weightCount; - Value bankCount; +struct HMDLMeta : athena::io::DNA { + AT_DECL_DNA + Value magic = 'TACO'; + Value topology; + Value vertStride; + Value vertCount; + Value indexCount; + Value colorCount; + Value uvCount; + Value weightCount; + Value bankCount; }; -} - +} // namespace hecl diff --git a/hecl/include/hecl/MathExtras.hpp b/hecl/include/hecl/MathExtras.hpp index fb15e54a2..14192a7cb 100644 --- a/hecl/include/hecl/MathExtras.hpp +++ b/hecl/include/hecl/MathExtras.hpp @@ -17,20 +17,18 @@ /// \brief Extend the default __GNUC_PREREQ even if glibc's features.h isn't /// available. #ifndef LLVM_GNUC_PREREQ -# if defined(__GNUC__) && defined(__GNUC_MINOR__) && defined(__GNUC_PATCHLEVEL__) -# define LLVM_GNUC_PREREQ(maj, min, patch) \ - ((__GNUC__ << 20) + (__GNUC_MINOR__ << 10) + __GNUC_PATCHLEVEL__ >= \ - ((maj) << 20) + ((min) << 10) + (patch)) -# elif defined(__GNUC__) && defined(__GNUC_MINOR__) -# define LLVM_GNUC_PREREQ(maj, min, patch) \ - ((__GNUC__ << 20) + (__GNUC_MINOR__ << 10) >= ((maj) << 20) + ((min) << 10)) -# else -# define LLVM_GNUC_PREREQ(maj, min, patch) 0 -# endif +#if defined(__GNUC__) && defined(__GNUC_MINOR__) && defined(__GNUC_PATCHLEVEL__) +#define LLVM_GNUC_PREREQ(maj, min, patch) \ + ((__GNUC__ << 20) + (__GNUC_MINOR__ << 10) + __GNUC_PATCHLEVEL__ >= ((maj) << 20) + ((min) << 10) + (patch)) +#elif defined(__GNUC__) && defined(__GNUC_MINOR__) +#define LLVM_GNUC_PREREQ(maj, min, patch) ((__GNUC__ << 20) + (__GNUC_MINOR__ << 10) >= ((maj) << 20) + ((min) << 10)) +#else +#define LLVM_GNUC_PREREQ(maj, min, patch) 0 +#endif #endif #ifndef __has_builtin -# define __has_builtin(x) 0 +#define __has_builtin(x) 0 #endif #include "hecl.hpp" @@ -61,7 +59,8 @@ enum ZeroBehavior { }; namespace detail { -template struct TrailingZerosCounter { +template +struct TrailingZerosCounter { static std::size_t count(T Val, ZeroBehavior) { if (!Val) return std::numeric_limits::digits; @@ -85,7 +84,8 @@ template struct TrailingZerosCounter { }; #if __GNUC__ >= 4 || defined(_MSC_VER) -template struct TrailingZerosCounter { +template +struct TrailingZerosCounter { static std::size_t count(T Val, ZeroBehavior ZB) { if (ZB != ZB_Undefined && Val == 0) return 32; @@ -101,7 +101,8 @@ template struct TrailingZerosCounter { }; #if !defined(_MSC_VER) || defined(_M_X64) -template struct TrailingZerosCounter { +template +struct TrailingZerosCounter { static std::size_t count(T Val, ZeroBehavior ZB) { if (ZB != ZB_Undefined && Val == 0) return 64; @@ -128,14 +129,14 @@ template struct TrailingZerosCounter { /// valid arguments. template std::size_t countTrailingZeros(T Val, ZeroBehavior ZB = ZB_Width) { - static_assert(std::numeric_limits::is_integer && - !std::numeric_limits::is_signed, + static_assert(std::numeric_limits::is_integer && !std::numeric_limits::is_signed, "Only unsigned integral types are allowed."); return detail::TrailingZerosCounter::count(Val, ZB); } namespace detail { -template struct LeadingZerosCounter { +template +struct LeadingZerosCounter { static std::size_t count(T Val, ZeroBehavior) { if (!Val) return std::numeric_limits::digits; @@ -154,7 +155,8 @@ template struct LeadingZerosCounter { }; #if __GNUC__ >= 4 || defined(_MSC_VER) -template struct LeadingZerosCounter { +template +struct LeadingZerosCounter { static std::size_t count(T Val, ZeroBehavior ZB) { if (ZB != ZB_Undefined && Val == 0) return 32; @@ -170,7 +172,8 @@ template struct LeadingZerosCounter { }; #if !defined(_MSC_VER) || defined(_M_X64) -template struct LeadingZerosCounter { +template +struct LeadingZerosCounter { static std::size_t count(T Val, ZeroBehavior ZB) { if (ZB != ZB_Undefined && Val == 0) return 64; @@ -197,8 +200,7 @@ template struct LeadingZerosCounter { /// valid arguments. template std::size_t countLeadingZeros(T Val, ZeroBehavior ZB = ZB_Width) { - static_assert(std::numeric_limits::is_integer && - !std::numeric_limits::is_signed, + static_assert(std::numeric_limits::is_integer && !std::numeric_limits::is_signed, "Only unsigned integral types are allowed."); return detail::LeadingZerosCounter::count(Val, ZB); } @@ -210,7 +212,8 @@ std::size_t countLeadingZeros(T Val, ZeroBehavior ZB = ZB_Width) { /// /// \param ZB the behavior on an input of 0. Only ZB_Max and ZB_Undefined are /// valid arguments. -template T findFirstSet(T Val, ZeroBehavior ZB = ZB_Max) { +template +T findFirstSet(T Val, ZeroBehavior ZB = ZB_Max) { if (ZB == ZB_Max && Val == 0) return std::numeric_limits::max(); @@ -224,14 +227,14 @@ template T findFirstSet(T Val, ZeroBehavior ZB = ZB_Max) { /// /// \param ZB the behavior on an input of 0. Only ZB_Max and ZB_Undefined are /// valid arguments. -template T findLastSet(T Val, ZeroBehavior ZB = ZB_Max) { +template +T findLastSet(T Val, ZeroBehavior ZB = ZB_Max) { if (ZB == ZB_Max && Val == 0) return std::numeric_limits::max(); // Use ^ instead of - because both gcc and llvm can remove the associated ^ // in the __builtin_clz intrinsic on x86. - return countLeadingZeros(Val, ZB_Undefined) ^ - (std::numeric_limits::digits - 1); + return countLeadingZeros(Val, ZB_Undefined) ^ (std::numeric_limits::digits - 1); } /// \brief Macro compressed bit reversal table for 256 bits. @@ -241,7 +244,7 @@ static const unsigned char BitReverseTable256[256] = { #define R2(n) n, n + 2 * 64, n + 1 * 64, n + 3 * 64 #define R4(n) R2(n), R2(n + 2 * 16), R2(n + 1 * 16), R2(n + 3 * 16) #define R6(n) R4(n), R4(n + 2 * 4), R4(n + 1 * 4), R4(n + 3 * 4) - R6(0), R6(2), R6(1), R6(3) + R6(0), R6(2), R6(1), R6(3) #undef R2 #undef R4 #undef R6 @@ -264,33 +267,31 @@ T reverseBits(T Val) { // ambiguity. /// Hi_32 - This function returns the high 32 bits of a 64 bit value. -constexpr inline uint32_t Hi_32(uint64_t Value) { - return static_cast(Value >> 32); -} +constexpr inline uint32_t Hi_32(uint64_t Value) { return static_cast(Value >> 32); } /// Lo_32 - This function returns the low 32 bits of a 64 bit value. -constexpr inline uint32_t Lo_32(uint64_t Value) { - return static_cast(Value); -} +constexpr inline uint32_t Lo_32(uint64_t Value) { return static_cast(Value); } /// Make_64 - This functions makes a 64-bit integer from a high / low pair of /// 32-bit integers. -constexpr inline uint64_t Make_64(uint32_t High, uint32_t Low) { - return ((uint64_t)High << 32) | (uint64_t)Low; -} +constexpr inline uint64_t Make_64(uint32_t High, uint32_t Low) { return ((uint64_t)High << 32) | (uint64_t)Low; } /// isInt - Checks if an integer fits into the given bit width. -template constexpr inline bool isInt(int64_t x) { - return N >= 64 || (-(INT64_C(1)<<(N-1)) <= x && x < (INT64_C(1)<<(N-1))); +template +constexpr inline bool isInt(int64_t x) { + return N >= 64 || (-(INT64_C(1) << (N - 1)) <= x && x < (INT64_C(1) << (N - 1))); } // Template specializations to get better code for common cases. -template <> constexpr inline bool isInt<8>(int64_t x) { +template <> +constexpr inline bool isInt<8>(int64_t x) { return static_cast(x) == x; } -template <> constexpr inline bool isInt<16>(int64_t x) { +template <> +constexpr inline bool isInt<16>(int64_t x) { return static_cast(x) == x; } -template <> constexpr inline bool isInt<32>(int64_t x) { +template <> +constexpr inline bool isInt<32>(int64_t x) { return static_cast(x) == x; } @@ -298,8 +299,7 @@ template <> constexpr inline bool isInt<32>(int64_t x) { /// left by S. template constexpr inline bool isShiftedInt(int64_t x) { - static_assert( - N > 0, "isShiftedInt<0> doesn't make sense (refers to a 0-bit number."); + static_assert(N > 0, "isShiftedInt<0> doesn't make sense (refers to a 0-bit number."); static_assert(N + S <= 64, "isShiftedInt with N + S > 64 is too wide."); return isInt(x) && (x % (UINT64_C(1) << S) == 0); } @@ -313,35 +313,34 @@ constexpr inline bool isShiftedInt(int64_t x) { /// to keep MSVC from (incorrectly) warning on isUInt<64> that we're shifting /// left too many places. template -constexpr inline typename std::enable_if<(N < 64), bool>::type -isUInt(uint64_t X) { +constexpr inline typename std::enable_if<(N < 64), bool>::type isUInt(uint64_t X) { static_assert(N > 0, "isUInt<0> doesn't make sense"); return X < (UINT64_C(1) << (N)); } template -constexpr inline typename std::enable_if= 64, bool>::type -isUInt(uint64_t X) { +constexpr inline typename std::enable_if= 64, bool>::type isUInt(uint64_t X) { return true; } // Template specializations to get better code for common cases. -template <> constexpr inline bool isUInt<8>(uint64_t x) { +template <> +constexpr inline bool isUInt<8>(uint64_t x) { return static_cast(x) == x; } -template <> constexpr inline bool isUInt<16>(uint64_t x) { +template <> +constexpr inline bool isUInt<16>(uint64_t x) { return static_cast(x) == x; } -template <> constexpr inline bool isUInt<32>(uint64_t x) { +template <> +constexpr inline bool isUInt<32>(uint64_t x) { return static_cast(x) == x; } /// Checks if a unsigned integer is an N bit number shifted left by S. template constexpr inline bool isShiftedUInt(uint64_t x) { - static_assert( - N > 0, "isShiftedUInt<0> doesn't make sense (refers to a 0-bit number)"); - static_assert(N + S <= 64, - "isShiftedUInt with N + S > 64 is too wide."); + static_assert(N > 0, "isShiftedUInt<0> doesn't make sense (refers to a 0-bit number)"); + static_assert(N + S <= 64, "isShiftedUInt with N + S > 64 is too wide."); // Per the two static_asserts above, S must be strictly less than 64. So // 1 << S is not undefined behavior. return isUInt(x) && (x % (UINT64_C(1) << S) == 0); @@ -362,7 +361,7 @@ inline uint64_t maxUIntN(uint64_t N) { inline int64_t minIntN(int64_t N) { assert(N > 0 && N <= 64 && "integer width out of range"); - return -(UINT64_C(1)<<(N-1)); + return -(UINT64_C(1) << (N - 1)); } /// Gets the maximum value for a N-bit signed integer. @@ -376,72 +375,50 @@ inline int64_t maxIntN(int64_t N) { /// isUIntN - Checks if an unsigned integer fits into the given (dynamic) /// bit width. -inline bool isUIntN(unsigned N, uint64_t x) { - return N >= 64 || x <= maxUIntN(N); -} +inline bool isUIntN(unsigned N, uint64_t x) { return N >= 64 || x <= maxUIntN(N); } /// isIntN - Checks if an signed integer fits into the given (dynamic) /// bit width. -inline bool isIntN(unsigned N, int64_t x) { - return N >= 64 || (minIntN(N) <= x && x <= maxIntN(N)); -} +inline bool isIntN(unsigned N, int64_t x) { return N >= 64 || (minIntN(N) <= x && x <= maxIntN(N)); } /// isMask_32 - This function returns true if the argument is a non-empty /// sequence of ones starting at the least significant bit with the remainder /// zero (32 bit version). Ex. isMask_32(0x0000FFFFU) == true. -constexpr inline bool isMask_32(uint32_t Value) { - return Value && ((Value + 1) & Value) == 0; -} +constexpr inline bool isMask_32(uint32_t Value) { return Value && ((Value + 1) & Value) == 0; } /// isMask_64 - This function returns true if the argument is a non-empty /// sequence of ones starting at the least significant bit with the remainder /// zero (64 bit version). -constexpr inline bool isMask_64(uint64_t Value) { - return Value && ((Value + 1) & Value) == 0; -} +constexpr inline bool isMask_64(uint64_t Value) { return Value && ((Value + 1) & Value) == 0; } /// isShiftedMask_32 - This function returns true if the argument contains a /// non-empty sequence of ones with the remainder zero (32 bit version.) /// Ex. isShiftedMask_32(0x0000FF00U) == true. -constexpr inline bool isShiftedMask_32(uint32_t Value) { - return Value && isMask_32((Value - 1) | Value); -} +constexpr inline bool isShiftedMask_32(uint32_t Value) { return Value && isMask_32((Value - 1) | Value); } /// isShiftedMask_64 - This function returns true if the argument contains a /// non-empty sequence of ones with the remainder zero (64 bit version.) -constexpr inline bool isShiftedMask_64(uint64_t Value) { - return Value && isMask_64((Value - 1) | Value); -} +constexpr inline bool isShiftedMask_64(uint64_t Value) { return Value && isMask_64((Value - 1) | Value); } /// isPowerOf2_32 - This function returns true if the argument is a power of /// two > 0. Ex. isPowerOf2_32(0x00100000U) == true (32 bit edition.) -constexpr inline bool isPowerOf2_32(uint32_t Value) { - return Value && !(Value & (Value - 1)); -} +constexpr inline bool isPowerOf2_32(uint32_t Value) { return Value && !(Value & (Value - 1)); } /// isPowerOf2_64 - This function returns true if the argument is a power of two /// > 0 (64 bit edition.) -constexpr inline bool isPowerOf2_64(uint64_t Value) { - return Value && !(Value & (Value - int64_t(1L))); -} +constexpr inline bool isPowerOf2_64(uint64_t Value) { return Value && !(Value & (Value - int64_t(1L))); } /// ByteSwap_16 - This function returns a byte-swapped representation of the /// 16-bit argument, Value. -inline uint16_t ByteSwap_16(uint16_t Value) { - return hecl::bswap16(Value); -} +inline uint16_t ByteSwap_16(uint16_t Value) { return hecl::bswap16(Value); } /// ByteSwap_32 - This function returns a byte-swapped representation of the /// 32-bit argument, Value. -inline uint32_t ByteSwap_32(uint32_t Value) { - return hecl::bswap32(Value); -} +inline uint32_t ByteSwap_32(uint32_t Value) { return hecl::bswap32(Value); } /// ByteSwap_64 - This function returns a byte-swapped representation of the /// 64-bit argument, Value. -inline uint64_t ByteSwap_64(uint64_t Value) { - return hecl::bswap64(Value); -} +inline uint64_t ByteSwap_64(uint64_t Value) { return hecl::bswap64(Value); } /// \brief Count the number of ones from the most significant bit to the first /// zero bit. @@ -453,8 +430,7 @@ inline uint64_t ByteSwap_64(uint64_t Value) { /// ZB_Undefined are valid arguments. template std::size_t countLeadingOnes(T Value, ZeroBehavior ZB = ZB_Width) { - static_assert(std::numeric_limits::is_integer && - !std::numeric_limits::is_signed, + static_assert(std::numeric_limits::is_integer && !std::numeric_limits::is_signed, "Only unsigned integral types are allowed."); return countLeadingZeros(~Value, ZB); } @@ -469,14 +445,14 @@ std::size_t countLeadingOnes(T Value, ZeroBehavior ZB = ZB_Width) { /// ZB_Undefined are valid arguments. template std::size_t countTrailingOnes(T Value, ZeroBehavior ZB = ZB_Width) { - static_assert(std::numeric_limits::is_integer && - !std::numeric_limits::is_signed, + static_assert(std::numeric_limits::is_integer && !std::numeric_limits::is_signed, "Only unsigned integral types are allowed."); return countTrailingZeros(~Value, ZB); } namespace detail { -template struct PopulationCounter { +template +struct PopulationCounter { static unsigned count(T Value) { // Generic version, forward to 32 bits. static_assert(SizeOfT <= 4, "Not implemented!"); @@ -491,7 +467,8 @@ template struct PopulationCounter { } }; -template struct PopulationCounter { +template +struct PopulationCounter { static unsigned count(T Value) { #if __GNUC__ >= 4 return __builtin_popcountll(Value); @@ -511,8 +488,7 @@ template struct PopulationCounter { /// Returns 0 if the word is zero. template inline unsigned countPopulation(T Value) { - static_assert(std::numeric_limits::is_integer && - !std::numeric_limits::is_signed, + static_assert(std::numeric_limits::is_integer && !std::numeric_limits::is_signed, "Only unsigned integral types are allowed."); return detail::PopulationCounter::count(Value); } @@ -529,28 +505,20 @@ inline double Log2(double Value) { /// Log2_32 - This function returns the floor log base 2 of the specified value, /// -1 if the value is zero. (32 bit edition.) /// Ex. Log2_32(32) == 5, Log2_32(1) == 0, Log2_32(0) == -1, Log2_32(6) == 2 -inline unsigned Log2_32(uint32_t Value) { - return 31 - countLeadingZeros(Value); -} +inline unsigned Log2_32(uint32_t Value) { return 31 - countLeadingZeros(Value); } /// Log2_64 - This function returns the floor log base 2 of the specified value, /// -1 if the value is zero. (64 bit edition.) -inline unsigned Log2_64(uint64_t Value) { - return 63 - countLeadingZeros(Value); -} +inline unsigned Log2_64(uint64_t Value) { return 63 - countLeadingZeros(Value); } /// Log2_32_Ceil - This function returns the ceil log base 2 of the specified /// value, 32 if the value is zero. (32 bit edition). /// Ex. Log2_32_Ceil(32) == 5, Log2_32_Ceil(1) == 0, Log2_32_Ceil(6) == 3 -inline unsigned Log2_32_Ceil(uint32_t Value) { - return 32 - countLeadingZeros(Value - 1); -} +inline unsigned Log2_32_Ceil(uint32_t Value) { return 32 - countLeadingZeros(Value - 1); } /// Log2_64_Ceil - This function returns the ceil log base 2 of the specified /// value, 64 if the value is zero. (64 bit edition.) -inline unsigned Log2_64_Ceil(uint64_t Value) { - return 64 - countLeadingZeros(Value - 1); -} +inline unsigned Log2_64_Ceil(uint64_t Value) { return 64 - countLeadingZeros(Value - 1); } /// GreatestCommonDivisor64 - Return the greatest common divisor of the two /// values using Euclid's algorithm. @@ -626,9 +594,8 @@ constexpr inline uint64_t MinAlign(uint64_t A, uint64_t B) { /// /// Alignment should be a power of two. This method rounds up, so /// alignAddr(7, 4) == 8 and alignAddr(8, 4) == 8. -inline uintptr_t alignAddr(const void *Addr, size_t Alignment) { - assert(Alignment && isPowerOf2_64((uint64_t)Alignment) && - "Alignment is not a power of two!"); +inline uintptr_t alignAddr(const void* Addr, size_t Alignment) { + assert(Alignment && isPowerOf2_64((uint64_t)Alignment) && "Alignment is not a power of two!"); assert((uintptr_t)Addr + Alignment - 1 >= (uintptr_t)Addr); @@ -637,7 +604,7 @@ inline uintptr_t alignAddr(const void *Addr, size_t Alignment) { /// \brief Returns the necessary adjustment for aligning \c Ptr to \c Alignment /// bytes, rounding up. -inline size_t alignmentAdjustment(const void *Ptr, size_t Alignment) { +inline size_t alignmentAdjustment(const void* Ptr, size_t Alignment) { return alignAddr(Ptr, Alignment) - (uintptr_t)Ptr; } @@ -656,7 +623,8 @@ inline uint64_t NextPowerOf2(uint64_t A) { /// Returns the power of two which is less than or equal to the given value. /// Essentially, it is a floor operation across the domain of powers of two. inline uint64_t PowerOf2Floor(uint64_t A) { - if (!A) return 0; + if (!A) + return 0; return 1ull << (63 - countLeadingZeros(A, ZB_Undefined)); } @@ -696,7 +664,8 @@ inline uint64_t alignTo(uint64_t Value, uint64_t Align, uint64_t Skew = 0) { /// Returns the next integer (mod 2**64) that is greater than or equal to /// \p Value and is a multiple of \c Align. \c Align must be non-zero. -template constexpr inline uint64_t alignTo(uint64_t Value) { +template +constexpr inline uint64_t alignTo(uint64_t Value) { static_assert(Align != 0u, "Align must be non-zero"); return (Value + Align - 1) / Align * Align; } @@ -725,13 +694,12 @@ inline uint64_t alignDown(uint64_t Value, uint64_t Align, uint64_t Skew = 0) { /// Returns the offset to the next integer (mod 2**64) that is greater than /// or equal to \p Value and is a multiple of \p Align. \p Align must be /// non-zero. -inline uint64_t OffsetToAlignment(uint64_t Value, uint64_t Align) { - return alignTo(Value, Align) - Value; -} +inline uint64_t OffsetToAlignment(uint64_t Value, uint64_t Align) { return alignTo(Value, Align) - Value; } /// Sign-extend the number in the bottom B bits of X to a 32-bit integer. /// Requires 0 < B <= 32. -template constexpr inline int32_t SignExtend32(uint32_t X) { +template +constexpr inline int32_t SignExtend32(uint32_t X) { static_assert(B > 0, "Bit width can't be 0."); static_assert(B <= 32, "Bit width out of range."); return int32_t(X << (32 - B)) >> (32 - B); @@ -747,7 +715,8 @@ inline int32_t SignExtend32(uint32_t X, unsigned B) { /// Sign-extend the number in the bottom B bits of X to a 64-bit integer. /// Requires 0 < B < 64. -template constexpr inline int64_t SignExtend64(uint64_t x) { +template +constexpr inline int64_t SignExtend64(uint64_t x) { static_assert(B > 0, "Bit width can't be 0."); static_assert(B <= 64, "Bit width out of range."); return int64_t(x << (64 - B)) >> (64 - B); @@ -764,8 +733,7 @@ inline int64_t SignExtend64(uint64_t X, unsigned B) { /// Subtract two unsigned integers, X and Y, of type T and return the absolute /// value of the result. template -typename std::enable_if::value, T>::type -AbsoluteDifference(T X, T Y) { +typename std::enable_if::value, T>::type AbsoluteDifference(T X, T Y) { return std::max(X, Y) - std::min(X, Y); } @@ -773,10 +741,9 @@ AbsoluteDifference(T X, T Y) { /// maximum representable value of T on overflow. ResultOverflowed indicates if /// the result is larger than the maximum representable value of type T. template -typename std::enable_if::value, T>::type -SaturatingAdd(T X, T Y, bool *ResultOverflowed = nullptr) { +typename std::enable_if::value, T>::type SaturatingAdd(T X, T Y, bool* ResultOverflowed = nullptr) { bool Dummy; - bool &Overflowed = ResultOverflowed ? *ResultOverflowed : Dummy; + bool& Overflowed = ResultOverflowed ? *ResultOverflowed : Dummy; // Hacker's Delight, p. 29 T Z = X + Y; Overflowed = (Z < X || Z < Y); @@ -790,10 +757,10 @@ SaturatingAdd(T X, T Y, bool *ResultOverflowed = nullptr) { /// maximum representable value of T on overflow. ResultOverflowed indicates if /// the result is larger than the maximum representable value of type T. template -typename std::enable_if::value, T>::type -SaturatingMultiply(T X, T Y, bool *ResultOverflowed = nullptr) { +typename std::enable_if::value, T>::type SaturatingMultiply(T X, T Y, + bool* ResultOverflowed = nullptr) { bool Dummy; - bool &Overflowed = ResultOverflowed ? *ResultOverflowed : Dummy; + bool& Overflowed = ResultOverflowed ? *ResultOverflowed : Dummy; // Hacker's Delight, p. 30 has a different algorithm, but we don't use that // because it fails for uint16_t (where multiplication can have undefined @@ -836,10 +803,10 @@ SaturatingMultiply(T X, T Y, bool *ResultOverflowed = nullptr) { /// overflow. ResultOverflowed indicates if the result is larger than the /// maximum representable value of type T. template -typename std::enable_if::value, T>::type -SaturatingMultiplyAdd(T X, T Y, T A, bool *ResultOverflowed = nullptr) { +typename std::enable_if::value, T>::type SaturatingMultiplyAdd(T X, T Y, T A, + bool* ResultOverflowed = nullptr) { bool Dummy; - bool &Overflowed = ResultOverflowed ? *ResultOverflowed : Dummy; + bool& Overflowed = ResultOverflowed ? *ResultOverflowed : Dummy; T Product = SaturatingMultiply(X, Y, &Overflowed); if (Overflowed) @@ -850,6 +817,5 @@ SaturatingMultiplyAdd(T X, T Y, T A, bool *ResultOverflowed = nullptr) { /// Use this rather than HUGE_VALF; the latter causes warnings on MSVC. extern const float huge_valf; -} // End llvm namespace -} // End hecl namespace - +} // namespace llvm +} // namespace hecl diff --git a/hecl/include/hecl/MultiProgressPrinter.hpp b/hecl/include/hecl/MultiProgressPrinter.hpp index fbcc645cc..5e5014793 100644 --- a/hecl/include/hecl/MultiProgressPrinter.hpp +++ b/hecl/include/hecl/MultiProgressPrinter.hpp @@ -3,57 +3,53 @@ #include "hecl.hpp" #include -namespace hecl -{ +namespace hecl { -class MultiProgressPrinter -{ - std::thread m_logThread; - mutable std::mutex m_logLock; - bool m_newLineAfter; +class MultiProgressPrinter { + std::thread m_logThread; + mutable std::mutex m_logLock; + bool m_newLineAfter; - struct TermInfo - { + struct TermInfo { #if _WIN32 - HANDLE console; + HANDLE console; #endif - int width; - bool xtermColor = false; - bool truncate = false; - } m_termInfo; + int width; + bool xtermColor = false; + bool truncate = false; + } m_termInfo; - struct ThreadStat - { - hecl::SystemString m_message, m_submessage; - float m_factor = 0.f; - bool m_active = false; - void print(const TermInfo& tinfo) const; - }; - mutable std::vector m_threadStats; + struct ThreadStat { + hecl::SystemString m_message, m_submessage; + float m_factor = 0.f; + bool m_active = false; + void print(const TermInfo& tinfo) const; + }; + mutable std::vector m_threadStats; + + mutable float m_mainFactor = -1.f; + mutable int m_indeterminateCounter = 0; + mutable int m_curThreadLines = 0; + mutable int m_curProgLines = 0; + mutable int m_latestThread = -1; + mutable bool m_running = false; + mutable bool m_dirty = false; + mutable bool m_mainIndeterminate = false; + uint64_t m_lastLogCounter = 0; + void LogProc(); + void DoPrint(); + void DrawIndeterminateBar(); + void MoveCursorUp(int n); - mutable float m_mainFactor = -1.f; - mutable int m_indeterminateCounter = 0; - mutable int m_curThreadLines = 0; - mutable int m_curProgLines = 0; - mutable int m_latestThread = -1; - mutable bool m_running = false; - mutable bool m_dirty = false; - mutable bool m_mainIndeterminate = false; - uint64_t m_lastLogCounter = 0; - void LogProc(); - void DoPrint(); - void DrawIndeterminateBar(); - void MoveCursorUp(int n); public: - MultiProgressPrinter(bool activate = false); - ~MultiProgressPrinter(); - void print(const hecl::SystemChar* message, const hecl::SystemChar* submessage, - float factor = -1.f, int threadIdx = 0) const; - void setMainFactor(float factor) const; - void setMainIndeterminate(bool indeterminate) const; - void startNewLine() const; - void flush() const; + MultiProgressPrinter(bool activate = false); + ~MultiProgressPrinter(); + void print(const hecl::SystemChar* message, const hecl::SystemChar* submessage, float factor = -1.f, + int threadIdx = 0) const; + void setMainFactor(float factor) const; + void setMainIndeterminate(bool indeterminate) const; + void startNewLine() const; + void flush() const; }; -} - +} // namespace hecl diff --git a/hecl/include/hecl/Pipeline.hpp b/hecl/include/hecl/Pipeline.hpp index 19aec165a..f1233ac17 100644 --- a/hecl/include/hecl/Pipeline.hpp +++ b/hecl/include/hecl/Pipeline.hpp @@ -11,241 +11,208 @@ /* CMake-curated rep classes for the application */ #include "ApplicationReps.hpp" -namespace hecl -{ +namespace hecl { #if HECL_RUNTIME -template -class StageRuntimeObject : public StageRep -{ - boo::ObjToken m_stage; +template +class StageRuntimeObject : public StageRep { + boo::ObjToken m_stage; + public: - static constexpr StageTargetType TargetType = StageTargetType::Runtime; - static constexpr PipelineTargetType PipelineTarget = PipelineTargetType::StageRuntimeCollection; - static constexpr bool HasHash = false; - StageRuntimeObject() = default; - StageRuntimeObject(StageConverter& conv, FactoryCtx& ctx, const StageBinary& in) - { - m_stage = static_cast(ctx).newShaderStage(in.data(), in.size(), S::Enum); - } - boo::ObjToken stage() const { return m_stage; } + static constexpr StageTargetType TargetType = StageTargetType::Runtime; + static constexpr PipelineTargetType PipelineTarget = PipelineTargetType::StageRuntimeCollection; + static constexpr bool HasHash = false; + StageRuntimeObject() = default; + StageRuntimeObject(StageConverter& conv, FactoryCtx& ctx, const StageBinary& in) { + m_stage = static_cast(ctx).newShaderStage(in.data(), in.size(), S::Enum); + } + boo::ObjToken stage() const { return m_stage; } }; #endif -class HECLIR : public PipelineRep -{ - const hecl::Backend::IR& m_ir; - const hecl::Backend::ShaderTag& m_tag; - const hecl::Backend::ExtensionSlot& m_extension; - uint64_t m_hash; -public: - HECLIR(const hecl::Backend::IR& ir, const hecl::Backend::ShaderTag& tag, - const hecl::Backend::ExtensionSlot& extension) - : m_ir(ir), m_tag(tag), m_extension(extension) - { - m_hash = tag.val64(); - m_hash ^= extension.hash(); - } - static constexpr bool HasHash = true; - uint64_t Hash() const { return m_hash; } +class HECLIR : public PipelineRep { + const hecl::Backend::IR& m_ir; + const hecl::Backend::ShaderTag& m_tag; + const hecl::Backend::ExtensionSlot& m_extension; + uint64_t m_hash; - const hecl::Backend::IR& ir() const { return m_ir; } - const hecl::Backend::ShaderTag& tag() const { return m_tag; } - const hecl::Backend::ExtensionSlot& extension() const { return m_extension; } +public: + HECLIR(const hecl::Backend::IR& ir, const hecl::Backend::ShaderTag& tag, + const hecl::Backend::ExtensionSlot& extension) + : m_ir(ir), m_tag(tag), m_extension(extension) { + m_hash = tag.val64(); + m_hash ^= extension.hash(); + } + static constexpr bool HasHash = true; + uint64_t Hash() const { return m_hash; } + + const hecl::Backend::IR& ir() const { return m_ir; } + const hecl::Backend::ShaderTag& tag() const { return m_tag; } + const hecl::Backend::ExtensionSlot& extension() const { return m_extension; } }; -template -class HECLBackendImpl : public PipelineRep

-{ - hecl::Backend::ShaderTag m_tag; - BackendTp m_backend; - const hecl::Backend::ExtensionSlot& m_extension; +template +class HECLBackendImpl : public PipelineRep

{ + hecl::Backend::ShaderTag m_tag; + BackendTp m_backend; + const hecl::Backend::ExtensionSlot& m_extension; + public: - static constexpr bool HasHash = false; - HECLBackendImpl(PipelineConverter

& conv, FactoryCtx& ctx, const HECLIR& in) - : m_tag(in.tag()), m_extension(in.extension()) - { - hecl::Backend::Diagnostics diag; - m_backend.reset(in.ir(), diag); - } - std::string makeVert() const - { - return m_backend.makeVert( - m_tag.getColorCount(), m_tag.getUvCount(), m_tag.getWeightCount(), - m_tag.getSkinSlotCount(), m_extension.texCount, - m_extension.texs, m_tag.getReflectionType()); - } - std::string makeFrag() const - { - return m_backend.makeFrag(m_extension.blockCount, m_extension.blockNames, - m_tag.getAlphaTest() || m_extension.forceAlphaTest, m_tag.getReflectionType(), - m_backend.m_blendSrc, m_backend.m_blendDst, - m_extension.lighting, m_extension.post, - m_extension.texCount, m_extension.texs); - } - const hecl::Backend::ShaderTag& getTag() const { return m_tag; } - const hecl::Backend::ExtensionSlot& extension() const { return m_extension; } - std::pair blendFactors() const - { return {m_backend.m_blendSrc, m_backend.m_blendDst}; } + static constexpr bool HasHash = false; + HECLBackendImpl(PipelineConverter

& conv, FactoryCtx& ctx, const HECLIR& in) + : m_tag(in.tag()), m_extension(in.extension()) { + hecl::Backend::Diagnostics diag; + m_backend.reset(in.ir(), diag); + } + std::string makeVert() const { + return m_backend.makeVert(m_tag.getColorCount(), m_tag.getUvCount(), m_tag.getWeightCount(), + m_tag.getSkinSlotCount(), m_extension.texCount, m_extension.texs, + m_tag.getReflectionType()); + } + std::string makeFrag() const { + return m_backend.makeFrag(m_extension.blockCount, m_extension.blockNames, + m_tag.getAlphaTest() || m_extension.forceAlphaTest, m_tag.getReflectionType(), + m_backend.m_blendSrc, m_backend.m_blendDst, m_extension.lighting, m_extension.post, + m_extension.texCount, m_extension.texs); + } + const hecl::Backend::ShaderTag& getTag() const { return m_tag; } + const hecl::Backend::ExtensionSlot& extension() const { return m_extension; } + std::pair blendFactors() const { + return {m_backend.m_blendSrc, m_backend.m_blendDst}; + } }; -template -class HECLBackend : public PipelineRep

-{ +template +class HECLBackend : public PipelineRep

{ public: - static constexpr bool HasHash = false; + static constexpr bool HasHash = false; }; -template<> -class HECLBackend : public HECLBackendImpl -{ +template <> +class HECLBackend : public HECLBackendImpl { public: - using HECLBackendImpl::HECLBackendImpl; + using HECLBackendImpl::HECLBackendImpl; }; -template<> -class HECLBackend : public HECLBackendImpl -{ +template <> +class HECLBackend : public HECLBackendImpl { public: - using HECLBackendImpl::HECLBackendImpl; + using HECLBackendImpl::HECLBackendImpl; }; -template<> -class HECLBackend : public HECLBackendImpl -{ +template <> +class HECLBackend : public HECLBackendImpl { public: - using HECLBackendImpl::HECLBackendImpl; + using HECLBackendImpl::HECLBackendImpl; }; -template<> -class HECLBackend : public HECLBackendImpl -{ +template <> +class HECLBackend : public HECLBackendImpl { public: - using HECLBackendImpl::HECLBackendImpl; + using HECLBackendImpl::HECLBackendImpl; }; -template<> -class HECLBackend : public HECLBackendImpl -{ +template <> +class HECLBackend : public HECLBackendImpl { public: - using HECLBackendImpl::HECLBackendImpl; + using HECLBackendImpl::HECLBackendImpl; }; -template class T, typename P, typename... Rest> -StageCollection>::StageCollection(PipelineConverter

& conv, FactoryCtx& ctx, const HECLBackend

& in) -{ - m_vertex = conv.getVertexConverter().convert(ctx, StageSourceText(in.makeVert())); - m_fragment = conv.getFragmentConverter().convert(ctx, StageSourceText(in.makeFrag())); - m_vtxFmtData = in.getTag().vertexFormat(); - m_vtxFmt = boo::VertexFormatInfo(m_vtxFmtData.size(), m_vtxFmtData.data()); - m_additionalInfo = in.getTag().additionalInfo(in.extension(), in.blendFactors()); - MakeHash(); +template