diff --git a/hecl/driver/main.cpp b/hecl/driver/main.cpp index 8d03f0450..d3cbbd4de 100644 --- a/hecl/driver/main.cpp +++ b/hecl/driver/main.cpp @@ -151,7 +151,7 @@ int main(int argc, const char** argv) info.cwd += _S('/'); #endif - if (argv[0][0] != _S('/') && argv[0][0] != _S('\\')) + if (hecl::PathRelative(argv[0])) ExeDir = hecl::SystemString(cwdbuf) + _S('/'); hecl::SystemString Argv0(argv[0]); hecl::SystemString::size_type lastIdx = Argv0.find_last_of(_S("/\\")); diff --git a/hecl/extern/boo b/hecl/extern/boo index 0cc794f49..8bcac27c1 160000 --- a/hecl/extern/boo +++ b/hecl/extern/boo @@ -1 +1 @@ -Subproject commit 0cc794f49d8884c30ba43b195aecdfed14062a53 +Subproject commit 8bcac27c10064e36be2b351f9f764412fceaa1ff diff --git a/hecl/include/hecl/Blender/BlenderConnection.hpp b/hecl/include/hecl/Blender/BlenderConnection.hpp index b6300e203..5dfa43a50 100644 --- a/hecl/include/hecl/Blender/BlenderConnection.hpp +++ b/hecl/include/hecl/Blender/BlenderConnection.hpp @@ -383,9 +383,9 @@ public: if (strcmp(readBuf, "OK")) BlenderLog.report(logvisor::Fatal, "unable get AABB: %s", readBuf); - Vector3f min(*m_parent); - Vector3f max(*m_parent); - return std::make_pair(min.val, max.val); + Vector3f minPt(*m_parent); + Vector3f maxPt(*m_parent); + return std::make_pair(minPt.val, maxPt.val); } /* Vector types with integrated stream reading constructor */ diff --git a/hecl/include/hecl/hecl.hpp b/hecl/include/hecl/hecl.hpp index a99ad4058..3bc675042 100644 --- a/hecl/include/hecl/hecl.hpp +++ b/hecl/include/hecl/hecl.hpp @@ -19,6 +19,7 @@ #endif #include #include +#include #include "winsupport.hpp" #endif @@ -457,6 +458,17 @@ static inline bool CheckFreeSpace(const SystemChar* path, size_t reqSz) #endif } +static inline bool PathRelative(const SystemChar* path) +{ + if (!path || !path[0]) + return false; +#if _WIN32 + return PathIsRelative(path); +#else + return path[0] != '/'; +#endif +} + static inline int ConsoleWidth() { int retval = 80; diff --git a/hecl/lib/Blender/BlenderConnection.cpp b/hecl/lib/Blender/BlenderConnection.cpp index 01d97ebe0..e2e93238e 100644 --- a/hecl/lib/Blender/BlenderConnection.cpp +++ b/hecl/lib/Blender/BlenderConnection.cpp @@ -19,7 +19,6 @@ #if _WIN32 #include #include -#include #endif namespace std @@ -1378,17 +1377,6 @@ std::vector BlenderConnection::DataStream: return ret; } -static bool PathRelative(const SystemString& path) -{ - if (path.empty()) - return false; -#if _WIN32 - return PathIsRelative(path.c_str()); -#else - return path[0] != '/'; -#endif -} - void BlenderConnection::DataStream::compileGuiFrame(const std::string& pathOut, int version) { if (m_parent->m_loadedType != BlendType::Frame) @@ -1414,7 +1402,7 @@ void BlenderConnection::DataStream::compileGuiFrame(const std::string& pathOut, SystemStringView absolute(readStr); auto& proj = m_parent->m_loadedBlend.getProject(); SystemString relative; - if (PathRelative(absolute.sys_str())) + if (PathRelative(absolute.c_str())) relative = absolute.sys_str(); else relative = proj.getProjectRootPath().getProjectRelativeFromAbsolute(absolute); diff --git a/hecl/lib/ClientProcess.cpp b/hecl/lib/ClientProcess.cpp index 19015afc8..c6c26ee87 100644 --- a/hecl/lib/ClientProcess.cpp +++ b/hecl/lib/ClientProcess.cpp @@ -43,6 +43,13 @@ void ClientProcess::BufferTransaction::run(BlenderToken& btok) void ClientProcess::CookTransaction::run(BlenderToken& btok) { m_dataSpec->setThreadProject(); + if (m_path.getAuxInfo().empty()) + LogModule.report(logvisor::Info, _S("Cooking %s"), + m_path.getRelativePath().c_str()); + else + LogModule.report(logvisor::Info, _S("Cooking %s|%s"), + m_path.getRelativePath().c_str(), + m_path.getAuxInfo().c_str()); m_returnResult = m_parent.syncCook(m_path, m_dataSpec, btok); m_complete = true; } diff --git a/hecl/lib/hecl.cpp b/hecl/lib/hecl.cpp index 234097f81..eaaf073ef 100644 --- a/hecl/lib/hecl.cpp +++ b/hecl/lib/hecl.cpp @@ -761,6 +761,117 @@ const SystemChar* GetTmpDir() int RunProcess(const SystemChar* path, const SystemChar* const args[]) { #ifdef _WIN32 + SECURITY_ATTRIBUTES sattrs = {sizeof(SECURITY_ATTRIBUTES), NULL, TRUE}; + HANDLE consoleOutReadTmp, consoleOutWrite, consoleErrWrite, consoleOutRead; + if (!CreatePipe(&consoleOutReadTmp, &consoleOutWrite, &sattrs, 0)) + { + LogModule.report(logvisor::Fatal, "Error with CreatePipe"); + return -1; + } + + if (!DuplicateHandle(GetCurrentProcess(), consoleOutWrite, + GetCurrentProcess(), &consoleErrWrite, 0, + TRUE,DUPLICATE_SAME_ACCESS)) + { + LogModule.report(logvisor::Fatal, "Error with DuplicateHandle"); + CloseHandle(consoleOutReadTmp); + CloseHandle(consoleOutWrite); + return -1; + } + + if (!DuplicateHandle(GetCurrentProcess(), consoleOutReadTmp, + GetCurrentProcess(), + &consoleOutRead, // Address of new handle. + 0, FALSE, // Make it uninheritable. + DUPLICATE_SAME_ACCESS)) + { + LogModule.report(logvisor::Fatal, "Error with DupliateHandle"); + CloseHandle(consoleOutReadTmp); + CloseHandle(consoleOutWrite); + CloseHandle(consoleErrWrite); + return -1; + } + + CloseHandle(consoleOutReadTmp); + + hecl::SystemString cmdLine; + const SystemChar* const* arg = &args[1]; + while (*arg) + { + cmdLine += _S(" \""); + cmdLine += *arg++; + cmdLine += _S('"'); + } + + STARTUPINFO sinfo = {sizeof(STARTUPINFO)}; + HANDLE nulHandle = CreateFileW(L"nul", GENERIC_WRITE, FILE_SHARE_READ|FILE_SHARE_WRITE, + &sattrs, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); + sinfo.dwFlags = STARTF_USESTDHANDLES; + sinfo.hStdInput = nulHandle; + sinfo.hStdError = consoleErrWrite; + sinfo.hStdOutput = consoleOutWrite; + + PROCESS_INFORMATION pinfo = {}; + if (!CreateProcessW(path, (LPWSTR)cmdLine.c_str(), NULL, NULL, TRUE, NORMAL_PRIORITY_CLASS, NULL, NULL, &sinfo, &pinfo)) + { + LPWSTR messageBuffer = nullptr; + FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, + NULL, GetLastError(), MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPWSTR)&messageBuffer, 0, NULL); + LogModule.report(logvisor::Error, L"unable to launch process from %s: %s", path, messageBuffer); + LocalFree(messageBuffer); + + CloseHandle(nulHandle); + CloseHandle(consoleErrWrite); + CloseHandle(consoleOutWrite); + CloseHandle(consoleOutRead); + return -1; + } + + CloseHandle(nulHandle); + CloseHandle(consoleErrWrite); + CloseHandle(consoleOutWrite); + + bool consoleThreadRunning = true; + auto consoleThread = std::thread([=, &consoleThreadRunning]() + { + CHAR lpBuffer[256]; + DWORD nBytesRead; + DWORD nCharsWritten; + + while (consoleThreadRunning) + { + if (!ReadFile(consoleOutRead, lpBuffer, sizeof(lpBuffer), + &nBytesRead, NULL) || !nBytesRead) + { + DWORD err = GetLastError(); + if (err == ERROR_BROKEN_PIPE) + break; // pipe done - normal exit path. + else + LogModule.report(logvisor::Error, "Error with ReadFile: %08X", err); // Something bad happened. + } + + // Display the character read on the screen. + auto lk = logvisor::LockLog(); + if (!WriteConsoleA(GetStdHandle(STD_OUTPUT_HANDLE), lpBuffer, + nBytesRead, &nCharsWritten, NULL)) + LogModule.report(logvisor::Error, "Error with WriteConsole: %08X", GetLastError()); + } + + CloseHandle(consoleOutRead); + }); + + WaitForSingleObject(pinfo.hProcess, INFINITE); + DWORD ret; + if (!GetExitCodeProcess(pinfo.hProcess, &ret)) + ret = -1; + consoleThreadRunning = false; + if (consoleThread.joinable()) + consoleThread.join(); + + CloseHandle(pinfo.hProcess); + CloseHandle(pinfo.hThread); + + return ret; #else pid_t pid = fork(); if (!pid)