Files
QuaternionEngine/src/core/assets/locator.cpp

126 lines
3.6 KiB
C++

#include "locator.h"
#include <cstdlib>
using std::filesystem::path;
static path get_env_path(const char *name)
{
const char *v = std::getenv(name);
if (!v || !*v) return {};
path p = v;
if (std::filesystem::exists(p)) return std::filesystem::canonical(p);
return {};
}
static path find_upwards_containing(path start, const std::string &subdir, int maxDepth = 6)
{
path cur = std::filesystem::weakly_canonical(start);
for (int i = 0; i <= maxDepth; i++)
{
path candidate = cur / subdir;
if (std::filesystem::exists(candidate)) return cur;
if (!cur.has_parent_path()) break;
cur = cur.parent_path();
}
return {};
}
AssetPaths AssetPaths::detect(const path &startDir)
{
AssetPaths out{};
if (auto root = get_env_path("VKG_ASSET_ROOT"); !root.empty())
{
out.root = root;
if (std::filesystem::exists(root / "assets")) out.assets = root / "assets";
if (std::filesystem::exists(root / "shaders")) out.shaders = root / "shaders";
return out;
}
if (auto aroot = find_upwards_containing(startDir, "assets"); !aroot.empty())
{
out.assets = aroot / "assets";
out.root = aroot;
}
if (auto sroot = find_upwards_containing(startDir, "shaders"); !sroot.empty())
{
out.shaders = sroot / "shaders";
if (out.root.empty()) out.root = sroot;
}
if (out.assets.empty())
{
path p1 = startDir / "assets";
path p2 = startDir / ".." / "assets";
if (std::filesystem::exists(p1)) out.assets = p1;
else if (std::filesystem::exists(p2)) out.assets = std::filesystem::weakly_canonical(p2);
}
if (out.shaders.empty())
{
path p1 = startDir / "shaders";
path p2 = startDir / ".." / "shaders";
if (std::filesystem::exists(p1)) out.shaders = p1;
else if (std::filesystem::exists(p2)) out.shaders = std::filesystem::weakly_canonical(p2);
}
return out;
}
void AssetLocator::init()
{
_paths = AssetPaths::detect();
}
bool AssetLocator::file_exists(const path &p)
{
std::error_code ec;
return !p.empty() && std::filesystem::exists(p, ec) && std::filesystem::is_regular_file(p, ec);
}
std::string AssetLocator::resolve_in(const path &base, std::string_view name)
{
if (name.empty()) return {};
path in = base / std::string(name);
if (file_exists(in)) return in.string();
return {};
}
std::string AssetLocator::shaderPath(std::string_view name) const
{
if (name.empty()) return {};
path np = std::string(name);
if (np.is_absolute() && file_exists(np)) return np.string();
if (file_exists(np)) return np.string();
if (!_paths.shaders.empty())
{
if (auto r = resolve_in(_paths.shaders, name); !r.empty()) return r;
}
if (auto r = resolve_in(std::filesystem::current_path() / "shaders", name); !r.empty()) return r;
if (auto r = resolve_in(std::filesystem::current_path() / ".." / "shaders", name); !r.empty()) return r;
return np.string();
}
std::string AssetLocator::assetPath(std::string_view name) const
{
if (name.empty()) return {};
path np = std::string(name);
if (np.is_absolute() && file_exists(np)) return np.string();
if (file_exists(np)) return np.string();
if (!_paths.assets.empty())
{
if (auto r = resolve_in(_paths.assets, name); !r.empty()) return r;
}
if (auto r = resolve_in(std::filesystem::current_path() / "assets", name); !r.empty()) return r;
if (auto r = resolve_in(std::filesystem::current_path() / ".." / "assets", name); !r.empty()) return r;
return np.string();
}