Files
SpineParticlesWeb/DateToSpine/src/editor/SpineEditorLocator.cpp
T
2026-09-07 21:29:15 +08:00

80 lines
2.4 KiB
C++

#include "editor/SpineEditorLocator.hpp"
#include <algorithm>
#include <cstdlib>
#include <system_error>
namespace dts {
namespace fs = std::filesystem;
namespace {
void addUnique(std::vector<fs::path>& paths, const fs::path& candidate) {
std::error_code error;
if (!fs::is_regular_file(candidate, error)) {
return;
}
const auto canonical = fs::weakly_canonical(candidate, error);
const auto value = error ? candidate.lexically_normal() : canonical;
if (std::find(paths.begin(), paths.end(), value) == paths.end()) {
paths.push_back(value);
}
}
} // namespace
std::vector<fs::path> SpineEditorLocator::discover() const {
std::vector<fs::path> results;
#if defined(__APPLE__)
addUnique(results, "/Applications/Spine.app/Contents/MacOS/Spine");
if (const char* userHome = std::getenv("HOME")) {
addUnique(results, fs::path(userHome) / "Applications/Spine.app/Contents/MacOS/Spine");
}
#elif defined(_WIN32)
const auto addFromRoot = [&results](const char* variable) {
if (const char* root = std::getenv(variable)) {
addUnique(results, fs::path(root) / "Spine/Spine.com");
}
};
addFromRoot("ProgramFiles");
addFromRoot("ProgramFiles(x86)");
#endif
return results;
}
std::optional<fs::path> SpineEditorLocator::normalize(const fs::path& userPath) const {
std::error_code error;
auto candidate = userPath;
#if defined(__APPLE__)
if (candidate.extension() == ".app") {
candidate /= "Contents/MacOS/Spine";
} else if (fs::is_directory(candidate, error)) {
const auto appCandidate = candidate / "Spine.app/Contents/MacOS/Spine";
if (fs::is_regular_file(appCandidate, error)) {
candidate = appCandidate;
}
}
#elif defined(_WIN32)
if (fs::is_directory(candidate, error)) {
candidate /= "Spine.com";
} else if (candidate.extension() == ".exe") {
auto commandCandidate = candidate;
commandCandidate.replace_extension(".com");
if (fs::is_regular_file(commandCandidate, error)) {
candidate = commandCandidate;
}
}
#endif
if (!fs::is_regular_file(candidate, error)) {
return std::nullopt;
}
const auto canonical = fs::weakly_canonical(candidate, error);
return error ? std::optional(candidate.lexically_normal()) : std::optional(canonical);
}
} // namespace dts