Merge pull request #639 from MihailRis/add-platform-new-engine-instance

add platform::new_engine_instance
This commit is contained in:
MihailRis 2025-10-04 02:15:12 +03:00 committed by GitHub
commit 3c0ba4a8c4
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 168 additions and 8 deletions

View File

@ -6,6 +6,7 @@
#include <stack>
#include "typedefs.hpp"
#include "util/stringutil.hpp"
#include "util/platform.hpp"
#include <utility>
#include "io/devices/StdfsDevice.hpp"
@ -44,6 +45,7 @@ void EnginePaths::prepare() {
resourcesFolder.string() + " is not a directory"
);
}
logger.info() << "executable path: " << platform::get_executable_path().string();
logger.info() << "resources folder: " << fs::canonical(resourcesFolder).u8string();
logger.info() << "user files folder: " << fs::canonical(userFilesFolder).u8string();
logger.info() << "project folder: " << fs::canonical(projectFolder).u8string();

View File

@ -141,7 +141,7 @@ void SkeletonConfig::update(
build_matrix(rotation, interpolation.getCurrent())
);
} else {
update(0, skeleton, root.get(), rotation);
update(0, skeleton, root.get(), build_matrix(rotation, position));
}
}

View File

@ -10,13 +10,22 @@
#include "stringutil.hpp"
#include "typedefs.hpp"
#include "debug/Logger.hpp"
static debug::Logger logger("platform");
#include "frontend/locale.hpp"
#ifdef _WIN32
#include <Windows.h>
#pragma comment(lib, "winmm.lib")
#else
#include <unistd.h>
#endif
namespace platform::internal {
std::filesystem::path get_executable_path();
}
static debug::Logger logger("platform");
#ifdef _WIN32
void platform::configure_encoding() {
// set utf-8 encoding to console output
SetConsoleOutputCP(CP_UTF8);
@ -83,9 +92,6 @@ bool platform::open_url(const std::string& url) {
#else // _WIN32
#include <unistd.h>
#include "frontend/locale.hpp"
void platform::configure_encoding() {
}
@ -158,3 +164,124 @@ void platform::open_folder(const std::filesystem::path& folder) {
#endif
}
std::filesystem::path platform::get_executable_path() {
#ifdef _WIN32
wchar_t buffer[MAX_PATH];
DWORD result = GetModuleFileNameW(NULL, buffer, MAX_PATH);
if (result == 0) {
DWORD error = GetLastError();
throw std::runtime_error("GetModuleFileName failed with code: " + std::to_string(error));
}
int size = WideCharToMultiByte(
CP_UTF8, 0, buffer, -1, nullptr, 0, nullptr, nullptr
);
if (size == 0) {
throw std::runtime_error("could not get executable path");
}
std::string str(size, 0);
size = WideCharToMultiByte(
CP_UTF8, 0, buffer, -1, str.data(), size, nullptr, nullptr
);
if (size == 0) {
DWORD error = GetLastError();
throw std::runtime_error("WideCharToMultiByte failed with code: " + std::to_string(error));
}
str.resize(size - 1);
return std::filesystem::path(str);
#elif defined(__APPLE__)
auto path = platform::internal::get_executable_path();
if (path.empty()) {
throw std::runtime_error("could not get executable path");
}
return path;
#else
char buffer[1024];
ssize_t count = readlink("/proc/self/exe", buffer, sizeof(buffer));
if (count != -1) {
return std::filesystem::canonical(std::filesystem::path(
std::string(buffer, static_cast<size_t>(count))
));
}
throw std::runtime_error("could not get executable path");
#endif
}
void platform::new_engine_instance(const std::vector<std::string>& args) {
auto executable = get_executable_path();
#ifdef _WIN32
std::stringstream ss;
ss << util::quote(executable.u8string());
for (int i = 0; i < args.size(); i++) {
ss << " " << util::quote(args[i]);
}
auto toWString = [](const std::string& src) -> std::wstring {
if (src.empty())
return L"";
int size = MultiByteToWideChar(CP_UTF8, 0, src.c_str(), -1, nullptr, 0);
if (size == 0) {
throw std::runtime_error(
"MultiByteToWideChar failed with code: " +
std::to_string(GetLastError())
);
}
std::vector<wchar_t> buffer(size + 1);
buffer[size] = 0;
size = MultiByteToWideChar(CP_UTF8, 0, src.c_str(), -1, buffer.data(), size);
if (size == 0) {
throw std::runtime_error(
"MultiByteToWideChar failed with code: " +
std::to_string(GetLastError())
);
}
return std::wstring(buffer.data(), size + 1);
};
auto commandString = toWString(ss.str());
STARTUPINFOW si = { sizeof(si) };
PROCESS_INFORMATION pi = { 0 };
DWORD flags = CREATE_NEW_PROCESS_GROUP | DETACHED_PROCESS;
// | CREATE_NO_WINDOW;
BOOL success = CreateProcessW(
nullptr,
commandString.data(),
nullptr,
nullptr,
FALSE,
flags,
nullptr,
nullptr,
&si,
&pi
);
if (success) {
CloseHandle(pi.hProcess);
CloseHandle(pi.hThread);
} else {
throw std::runtime_error(
"starting an engine instance failed with code: " +
std::to_string(GetLastError())
);
}
#else
std::stringstream ss;
ss << executable;
for (int i = 0; i < args.size(); i++) {
ss << " " << util::quote(args[i]);
}
ss << " >/dev/null &";
auto command = ss.str();
if (int res = system(command.c_str())) {
throw std::runtime_error(
"starting an engine instance failed with code: " +
std::to_string(res)
);
}
#endif
}

View File

@ -1,17 +1,24 @@
#pragma once
#include <string>
#include <vector>
#include <filesystem>
namespace platform {
void configure_encoding();
/// @return environment locale in ISO format ll_CC
/// @brief Get Environment locale in ISO format ll_CC
std::string detect_locale();
/// @brief Open folder using system file manager asynchronously
/// @param folder target folder
void open_folder(const std::filesystem::path& folder);
/// Makes the current thread sleep for the specified amount of milliseconds.
/// @brief Makes the current thread sleep for the specified amount of milliseconds.
void sleep(size_t millis);
/// @brief Get current process id
int get_process_id();
/// @brief Get current process running executable path
std::filesystem::path get_executable_path();
/// @brief Run a separate engine instance with specified arguments
void new_engine_instance(const std::vector<std::string>& args);
/// @brief Open URL in web browser
bool open_url(const std::string& url);
}

View File

@ -0,0 +1,24 @@
#include <filesystem>
#ifndef _WIN32
#include <unistd.h>
#endif
#ifdef __APPLE__
#include <mach-o/dyld.h>
#endif
namespace platform::internal {
std::filesystem::path get_executable_path() {
#ifdef __APPLE__
char buffer[1024];
uint32_t size = sizeof(buffer);
if (_NSGetExecutablePath(buffer, &size) == 0) {
return std::filesystem::canonical(std::filesystem::path(buffer));
} else {
return std::filesystem::path();
}
#endif
return std::filesystem::path();
}
}