2015-07-22 19:14:50 +00:00
|
|
|
#if _WIN32
|
2015-10-12 04:38:49 +00:00
|
|
|
#ifndef NOMINMAX
|
|
|
|
#define NOMINMAX
|
|
|
|
#endif
|
2017-11-06 06:56:17 +00:00
|
|
|
#define WIN_PAUSE 0
|
2015-08-31 03:36:24 +00:00
|
|
|
#include <objbase.h>
|
2015-07-22 19:14:50 +00:00
|
|
|
#endif
|
|
|
|
|
2015-08-31 03:36:24 +00:00
|
|
|
#include <clocale>
|
2017-12-29 07:56:31 +00:00
|
|
|
#include <cstdio>
|
|
|
|
#include <cstring>
|
|
|
|
#include <cstdlib>
|
|
|
|
#include <cstdarg>
|
2015-08-16 23:01:35 +00:00
|
|
|
#include <signal.h>
|
2015-05-20 05:22:32 +00:00
|
|
|
#include <regex>
|
2015-05-26 04:42:20 +00:00
|
|
|
#include <list>
|
2016-03-04 23:02:44 +00:00
|
|
|
#include "hecl/Database.hpp"
|
2017-12-29 07:56:31 +00:00
|
|
|
#include "hecl/Blender/Connection.hpp"
|
2016-03-04 23:02:44 +00:00
|
|
|
#include "logvisor/logvisor.hpp"
|
2015-07-05 06:27:24 +00:00
|
|
|
|
2016-09-25 01:57:43 +00:00
|
|
|
logvisor::Module LogModule("hecl::Driver");
|
2015-05-17 04:55:29 +00:00
|
|
|
|
2015-06-10 02:40:03 +00:00
|
|
|
#include "ToolBase.hpp"
|
|
|
|
#include "ToolInit.hpp"
|
|
|
|
#include "ToolSpec.hpp"
|
2015-06-12 09:08:49 +00:00
|
|
|
#include "ToolExtract.hpp"
|
2015-06-10 02:40:03 +00:00
|
|
|
#include "ToolCook.hpp"
|
|
|
|
#include "ToolPackage.hpp"
|
2018-04-15 06:04:08 +00:00
|
|
|
#include "ToolImage.hpp"
|
2015-06-10 02:40:03 +00:00
|
|
|
#include "ToolHelp.hpp"
|
2015-05-15 22:39:43 +00:00
|
|
|
|
2015-07-25 23:01:02 +00:00
|
|
|
/* Static reference to dataspec additions
|
|
|
|
* (used by MSVC to definitively link DataSpecs) */
|
2015-07-22 19:14:50 +00:00
|
|
|
#include "../DataSpecRegistry.hpp"
|
|
|
|
|
2015-05-26 04:42:20 +00:00
|
|
|
bool XTERM_COLOR = false;
|
|
|
|
|
2015-07-05 06:27:24 +00:00
|
|
|
|
2015-06-11 09:41:10 +00:00
|
|
|
/*
|
2015-06-10 02:40:03 +00:00
|
|
|
#define HECL_GIT 1234567
|
|
|
|
#define HECL_GIT_S "1234567"
|
|
|
|
#define HECL_BRANCH master
|
|
|
|
#define HECL_BRANCH_S "master"
|
2015-06-11 09:41:10 +00:00
|
|
|
*/
|
2015-06-10 02:40:03 +00:00
|
|
|
|
2015-05-20 05:22:32 +00:00
|
|
|
/* Main usage message */
|
2016-03-04 23:02:44 +00:00
|
|
|
static void printHelp(const hecl::SystemChar* pname)
|
2015-05-15 22:39:43 +00:00
|
|
|
{
|
2015-05-26 04:42:20 +00:00
|
|
|
if (XTERM_COLOR)
|
2016-03-04 23:02:44 +00:00
|
|
|
hecl::Printf(_S("" BOLD "HECL" NORMAL ""));
|
2015-05-26 04:42:20 +00:00
|
|
|
else
|
2016-03-04 23:02:44 +00:00
|
|
|
hecl::Printf(_S("HECL"));
|
2018-04-15 06:04:08 +00:00
|
|
|
#if HECL_HAS_NOD
|
|
|
|
# define TOOL_LIST "extract|init|cook|package|image|help"
|
|
|
|
#else
|
|
|
|
# define TOOL_LIST "extract|init|cook|package|help"
|
|
|
|
#endif
|
2015-05-20 05:22:32 +00:00
|
|
|
#if HECL_GIT
|
2018-04-15 06:04:08 +00:00
|
|
|
hecl::Printf(_S(" Commit " HECL_GIT_S " " HECL_BRANCH_S "\nUsage: %s " TOOL_LIST "\n"), pname);
|
2015-05-20 05:22:32 +00:00
|
|
|
#elif HECL_VER
|
2018-04-15 06:04:08 +00:00
|
|
|
hecl::Printf(_S(" Version " HECL_VER_S "\nUsage: %s " TOOL_LIST "\n"), pname);
|
2015-05-20 05:22:32 +00:00
|
|
|
#else
|
2018-04-15 06:04:08 +00:00
|
|
|
hecl::Printf(_S("\nUsage: %s " TOOL_LIST "\n"), pname);
|
2015-05-20 05:22:32 +00:00
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Regex patterns */
|
2016-03-04 23:02:44 +00:00
|
|
|
static const hecl::SystemRegex regOPEN(_S("-o([^\"]*|\\S*)"), std::regex::ECMAScript|std::regex::optimize);
|
2015-05-19 07:01:18 +00:00
|
|
|
|
2015-08-16 23:01:35 +00:00
|
|
|
/* SIGINT will gracefully close blender connections and delete blends in progress */
|
|
|
|
static void SIGINTHandler(int sig)
|
|
|
|
{
|
2017-12-29 07:56:31 +00:00
|
|
|
hecl::blender::Connection::Shutdown();
|
2018-01-10 06:16:18 +00:00
|
|
|
logvisor::KillProcessTree();
|
2015-08-16 23:01:35 +00:00
|
|
|
exit(1);
|
|
|
|
}
|
|
|
|
|
2015-09-02 22:00:05 +00:00
|
|
|
/* SIGWINCH should do nothing */
|
|
|
|
static void SIGWINCHHandler(int sig) {}
|
|
|
|
|
2016-03-04 23:02:44 +00:00
|
|
|
static logvisor::Module AthenaLog("Athena");
|
|
|
|
static void AthenaExc(athena::error::Level level, const char* file,
|
2015-07-26 02:52:02 +00:00
|
|
|
const char*, int line, const char* fmt, ...)
|
|
|
|
{
|
|
|
|
va_list ap;
|
|
|
|
va_start(ap, fmt);
|
2016-09-11 21:16:16 +00:00
|
|
|
AthenaLog.report(logvisor::Level(level), fmt, ap);
|
2015-07-26 02:52:02 +00:00
|
|
|
va_end(ap);
|
|
|
|
}
|
|
|
|
|
2017-02-24 08:27:07 +00:00
|
|
|
static hecl::SystemChar cwdbuf[1024];
|
|
|
|
hecl::SystemString ExeDir;
|
|
|
|
|
2016-06-17 20:44:49 +00:00
|
|
|
#if _WIN32
|
2015-06-10 02:40:03 +00:00
|
|
|
int wmain(int argc, const wchar_t** argv)
|
|
|
|
#else
|
2015-05-19 07:01:18 +00:00
|
|
|
int main(int argc, const char** argv)
|
2015-06-10 02:40:03 +00:00
|
|
|
#endif
|
2015-05-19 07:01:18 +00:00
|
|
|
{
|
2018-01-02 00:58:13 +00:00
|
|
|
if (argc > 1 && !hecl::StrCmp(argv[1], _S("--dlpackage")))
|
|
|
|
{
|
|
|
|
printf("%s\n", HECL_DLPACKAGE);
|
|
|
|
return 100;
|
|
|
|
}
|
|
|
|
|
2015-08-31 03:36:24 +00:00
|
|
|
#if _WIN32
|
2016-06-17 20:44:49 +00:00
|
|
|
CoInitializeEx(nullptr, COINIT_MULTITHREADED | COINIT_DISABLE_OLE1DDE);
|
2015-08-31 03:36:24 +00:00
|
|
|
#else
|
|
|
|
std::setlocale(LC_ALL, "en-US.UTF-8");
|
|
|
|
#endif
|
2016-03-24 02:51:57 +00:00
|
|
|
|
2015-05-26 04:42:20 +00:00
|
|
|
/* Xterm check */
|
2015-09-02 22:00:05 +00:00
|
|
|
#if _WIN32
|
|
|
|
const char* conemuANSI = getenv("ConEmuANSI");
|
|
|
|
if (conemuANSI && !strcmp(conemuANSI, "ON"))
|
|
|
|
XTERM_COLOR = true;
|
|
|
|
#else
|
2015-05-26 04:42:20 +00:00
|
|
|
const char* term = getenv("TERM");
|
2015-07-07 04:45:29 +00:00
|
|
|
if (term && !strncmp(term, "xterm", 5))
|
2015-05-26 04:42:20 +00:00
|
|
|
XTERM_COLOR = true;
|
2015-09-02 22:12:48 +00:00
|
|
|
signal(SIGWINCH, SIGWINCHHandler);
|
2015-09-02 22:00:05 +00:00
|
|
|
#endif
|
2015-08-16 23:01:35 +00:00
|
|
|
signal(SIGINT, SIGINTHandler);
|
|
|
|
|
2016-09-08 06:15:39 +00:00
|
|
|
logvisor::RegisterStandardExceptions();
|
2016-03-04 23:02:44 +00:00
|
|
|
logvisor::RegisterConsoleLogger();
|
2015-07-26 02:52:02 +00:00
|
|
|
atSetExceptionHandler(AthenaExc);
|
2015-07-06 01:35:08 +00:00
|
|
|
|
2015-05-20 05:22:32 +00:00
|
|
|
/* Basic usage check */
|
2015-05-19 07:01:18 +00:00
|
|
|
if (argc == 1)
|
|
|
|
{
|
|
|
|
printHelp(argv[0]);
|
2015-07-22 19:14:50 +00:00
|
|
|
#if WIN_PAUSE
|
|
|
|
system("PAUSE");
|
|
|
|
#endif
|
2015-05-19 07:01:18 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
else if (argc == 0)
|
|
|
|
{
|
2015-06-10 02:40:03 +00:00
|
|
|
printHelp(_S("hecl"));
|
2015-07-22 19:14:50 +00:00
|
|
|
#if WIN_PAUSE
|
|
|
|
system("PAUSE");
|
|
|
|
#endif
|
2015-05-19 07:01:18 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2015-08-08 23:33:55 +00:00
|
|
|
/* Prepare DataSpecs */
|
|
|
|
HECLRegisterDataSpecs();
|
|
|
|
|
2015-05-20 05:22:32 +00:00
|
|
|
/* Assemble common tool pass info */
|
2015-06-10 02:40:03 +00:00
|
|
|
ToolPassInfo info;
|
2015-05-20 05:22:32 +00:00
|
|
|
info.pname = argv[0];
|
2016-03-04 23:02:44 +00:00
|
|
|
if (hecl::Getcwd(cwdbuf, 1024))
|
2015-09-10 20:44:25 +00:00
|
|
|
{
|
2015-05-27 09:09:05 +00:00
|
|
|
info.cwd = cwdbuf;
|
2015-09-10 20:44:25 +00:00
|
|
|
if (info.cwd.size() && info.cwd.back() != _S('/') && info.cwd.back() != _S('\\'))
|
|
|
|
#if _WIN32
|
|
|
|
info.cwd += _S('\\');
|
|
|
|
#else
|
|
|
|
info.cwd += _S('/');
|
|
|
|
#endif
|
2017-02-24 08:27:07 +00:00
|
|
|
|
2017-02-25 07:58:36 +00:00
|
|
|
if (hecl::PathRelative(argv[0]))
|
2017-02-24 08:27:07 +00:00
|
|
|
ExeDir = hecl::SystemString(cwdbuf) + _S('/');
|
|
|
|
hecl::SystemString Argv0(argv[0]);
|
|
|
|
hecl::SystemString::size_type lastIdx = Argv0.find_last_of(_S("/\\"));
|
|
|
|
if (lastIdx != hecl::SystemString::npos)
|
|
|
|
ExeDir.insert(ExeDir.end(), Argv0.begin(), Argv0.begin() + lastIdx);
|
2015-09-10 20:44:25 +00:00
|
|
|
}
|
2015-05-19 07:01:18 +00:00
|
|
|
|
2015-05-20 05:22:32 +00:00
|
|
|
/* Concatenate args */
|
2016-03-04 23:02:44 +00:00
|
|
|
std::vector<hecl::SystemString> args;
|
2015-10-04 04:35:18 +00:00
|
|
|
args.reserve(argc-2);
|
2015-05-20 05:22:32 +00:00
|
|
|
for (int i=2 ; i<argc ; ++i)
|
2016-03-04 23:02:44 +00:00
|
|
|
args.push_back(hecl::SystemString(argv[i]));
|
2015-05-20 05:22:32 +00:00
|
|
|
|
|
|
|
if (!args.empty())
|
|
|
|
{
|
|
|
|
/* Extract output argument */
|
2015-10-04 04:35:18 +00:00
|
|
|
for (auto it = args.cbegin() ; it != args.cend() ;)
|
2015-05-20 05:22:32 +00:00
|
|
|
{
|
2016-03-04 23:02:44 +00:00
|
|
|
const hecl::SystemString& arg = *it;
|
|
|
|
hecl::SystemRegexMatch oMatch;
|
2015-05-26 04:42:20 +00:00
|
|
|
if (std::regex_search(arg, oMatch, regOPEN))
|
|
|
|
{
|
2016-03-04 23:02:44 +00:00
|
|
|
const hecl::SystemString& token = oMatch[1].str();
|
2015-05-26 04:42:20 +00:00
|
|
|
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;
|
2015-05-20 05:22:32 +00:00
|
|
|
}
|
|
|
|
|
2015-10-16 00:34:47 +00:00
|
|
|
/* Iterate flags */
|
2015-10-04 04:35:18 +00:00
|
|
|
for (auto it = args.cbegin() ; it != args.cend() ;)
|
2015-05-20 05:22:32 +00:00
|
|
|
{
|
2016-03-04 23:02:44 +00:00
|
|
|
const hecl::SystemString& arg = *it;
|
2015-10-22 02:01:08 +00:00
|
|
|
if (arg.size() < 2 || arg[0] != _S('-') || arg[1] == _S('-'))
|
2015-05-26 04:42:20 +00:00
|
|
|
{
|
2015-10-16 00:34:47 +00:00
|
|
|
++it;
|
2015-05-26 04:42:20 +00:00
|
|
|
continue;
|
|
|
|
}
|
2015-05-20 05:22:32 +00:00
|
|
|
|
2015-10-16 00:34:47 +00:00
|
|
|
for (auto chit = arg.cbegin() + 1 ; chit != arg.cend() ; ++chit)
|
2015-05-26 04:42:20 +00:00
|
|
|
{
|
2015-10-16 00:34:47 +00:00
|
|
|
if (*chit == _S('v'))
|
|
|
|
++info.verbosityLevel;
|
|
|
|
else if (*chit == _S('f'))
|
|
|
|
info.force = true;
|
2016-03-24 02:51:57 +00:00
|
|
|
else if (*chit == _S('y'))
|
|
|
|
info.yes = true;
|
2017-12-16 02:13:20 +00:00
|
|
|
else if (*chit == _S('g'))
|
|
|
|
info.gui = true;
|
2015-10-16 00:34:47 +00:00
|
|
|
else
|
|
|
|
info.flags.push_back(*chit);
|
2015-05-26 04:42:20 +00:00
|
|
|
}
|
2015-10-16 00:34:47 +00:00
|
|
|
|
|
|
|
it = args.erase(it);
|
2015-05-20 05:22:32 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Gather remaining args */
|
2015-10-04 04:35:18 +00:00
|
|
|
info.args.reserve(args.size());
|
2016-03-04 23:02:44 +00:00
|
|
|
for (const hecl::SystemString& arg : args)
|
2015-05-26 04:42:20 +00:00
|
|
|
info.args.push_back(arg);
|
2015-05-20 05:22:32 +00:00
|
|
|
}
|
|
|
|
|
2015-06-11 04:55:06 +00:00
|
|
|
/* Attempt to find hecl project */
|
2016-03-04 23:02:44 +00:00
|
|
|
hecl::ProjectRootPath rootPath = hecl::SearchForProject(info.cwd);
|
|
|
|
std::unique_ptr<hecl::Database::Project> project;
|
2015-09-30 06:23:07 +00:00
|
|
|
if (rootPath)
|
2015-06-11 04:55:06 +00:00
|
|
|
{
|
2016-03-04 23:02:44 +00:00
|
|
|
size_t ErrorRef = logvisor::ErrorCount;
|
|
|
|
hecl::Database::Project* newProj = new hecl::Database::Project(rootPath);
|
|
|
|
if (logvisor::ErrorCount > ErrorRef)
|
2015-06-11 04:55:06 +00:00
|
|
|
{
|
2015-07-22 19:14:50 +00:00
|
|
|
#if WIN_PAUSE
|
|
|
|
system("PAUSE");
|
|
|
|
#endif
|
2015-07-26 02:52:02 +00:00
|
|
|
delete newProj;
|
2015-06-11 04:55:06 +00:00
|
|
|
return -1;
|
|
|
|
}
|
2015-07-26 02:52:02 +00:00
|
|
|
project.reset(newProj);
|
|
|
|
info.project = newProj;
|
2015-06-11 04:55:06 +00:00
|
|
|
}
|
|
|
|
|
2015-05-20 05:22:32 +00:00
|
|
|
/* Construct selected tool */
|
2016-03-04 23:02:44 +00:00
|
|
|
hecl::SystemString toolName(argv[1]);
|
|
|
|
hecl::ToLower(toolName);
|
2015-06-11 04:55:06 +00:00
|
|
|
std::unique_ptr<ToolBase> tool;
|
2015-07-26 02:52:02 +00:00
|
|
|
|
2016-03-04 23:02:44 +00:00
|
|
|
size_t ErrorRef = logvisor::ErrorCount;
|
2015-07-26 02:52:02 +00:00
|
|
|
if (toolName == _S("init"))
|
|
|
|
tool.reset(new ToolInit(info));
|
|
|
|
else if (toolName == _S("spec"))
|
|
|
|
tool.reset(new ToolSpec(info));
|
|
|
|
else if (toolName == _S("extract"))
|
|
|
|
tool.reset(new ToolExtract(info));
|
|
|
|
else if (toolName == _S("cook"))
|
|
|
|
tool.reset(new ToolCook(info));
|
|
|
|
else if (toolName == _S("package") || toolName == _S("pack"))
|
|
|
|
tool.reset(new ToolPackage(info));
|
2018-04-15 06:04:08 +00:00
|
|
|
#if HECL_HAS_NOD
|
|
|
|
else if (toolName == _S("image"))
|
|
|
|
tool.reset(new ToolImage(info));
|
|
|
|
#endif
|
2015-07-26 02:52:02 +00:00
|
|
|
else if (toolName == _S("help"))
|
|
|
|
tool.reset(new ToolHelp(info));
|
|
|
|
else
|
2015-09-10 20:44:25 +00:00
|
|
|
{
|
2016-03-04 23:02:44 +00:00
|
|
|
FILE* fp = hecl::Fopen(argv[1], _S("rb"));
|
2015-09-10 20:44:25 +00:00
|
|
|
if (!fp)
|
2016-03-04 23:02:44 +00:00
|
|
|
LogModule.report(logvisor::Error, _S("unrecognized tool '%s'"), toolName.c_str());
|
2015-09-10 20:44:25 +00:00
|
|
|
else
|
|
|
|
{
|
|
|
|
/* Shortcut-case: implicit extract */
|
|
|
|
fclose(fp);
|
2015-10-04 04:35:18 +00:00
|
|
|
info.args.insert(info.args.begin(), argv[1]);
|
2015-09-10 20:44:25 +00:00
|
|
|
tool.reset(new ToolExtract(info));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-03-04 23:02:44 +00:00
|
|
|
if (logvisor::ErrorCount > ErrorRef)
|
2015-05-20 05:22:32 +00:00
|
|
|
{
|
2015-07-22 19:14:50 +00:00
|
|
|
#if WIN_PAUSE
|
|
|
|
system("PAUSE");
|
2015-07-16 02:03:38 +00:00
|
|
|
#endif
|
2015-05-20 05:22:32 +00:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (info.verbosityLevel)
|
2016-03-04 23:02:44 +00:00
|
|
|
LogModule.report(logvisor::Info, _S("Constructed tool '%s' %d\n"),
|
2015-07-05 06:27:24 +00:00
|
|
|
tool->toolName().c_str(), info.verbosityLevel);
|
2015-05-20 05:22:32 +00:00
|
|
|
|
|
|
|
/* Run tool */
|
2016-03-04 23:02:44 +00:00
|
|
|
ErrorRef = logvisor::ErrorCount;
|
2015-07-26 02:52:02 +00:00
|
|
|
int retval = tool->run();
|
2016-03-04 23:02:44 +00:00
|
|
|
if (logvisor::ErrorCount > ErrorRef)
|
2015-05-20 05:22:32 +00:00
|
|
|
{
|
2017-12-29 07:56:31 +00:00
|
|
|
hecl::blender::Connection::Shutdown();
|
2015-07-22 19:14:50 +00:00
|
|
|
#if WIN_PAUSE
|
|
|
|
system("PAUSE");
|
2015-07-16 02:03:38 +00:00
|
|
|
#endif
|
2015-05-20 05:22:32 +00:00
|
|
|
return -1;
|
|
|
|
}
|
2015-05-19 07:01:18 +00:00
|
|
|
|
2017-12-29 07:56:31 +00:00
|
|
|
hecl::blender::Connection::Shutdown();
|
2015-07-22 19:14:50 +00:00
|
|
|
#if WIN_PAUSE
|
|
|
|
system("PAUSE");
|
|
|
|
#endif
|
2015-05-20 05:22:32 +00:00
|
|
|
return retval;
|
2015-05-15 22:39:43 +00:00
|
|
|
}
|
2015-07-07 04:45:29 +00:00
|
|
|
|
|
|
|
|