28 const char* userprofile = std::getenv(
"USERPROFILE");
29 if (userprofile && *userprofile) {
30 return std::filesystem::path(userprofile);
34 const char* homedrive = std::getenv(
"HOMEDRIVE");
35 const char* homepath = std::getenv(
"HOMEPATH");
36 if (homedrive && homepath) {
37 return std::filesystem::path(std::string(homedrive) +
38 std::string(homepath));
43 auto temp = std::filesystem::temp_directory_path(ec);
47 return std::filesystem::path(
".");
48#elif defined(__EMSCRIPTEN__)
50 return std::filesystem::path(
"/home/web_user");
53 const char* home = std::getenv(
"HOME");
55 return std::filesystem::path(home);
59 struct passwd* pw = getpwuid(getuid());
60 if (pw && pw->pw_dir) {
61 return std::filesystem::path(pw->pw_dir);
66 auto cwd = std::filesystem::current_path(ec);
70 return std::filesystem::path(
".");
74 return std::filesystem::path(
".");
80 wchar_t path[MAX_PATH];
81 if (SUCCEEDED(SHGetFolderPathW(NULL, CSIDL_APPDATA, NULL, 0, path))) {
82 std::filesystem::path app_data = std::filesystem::path(path) /
"yaze";
91 std::filesystem::path app_data = home /
"yaze_data";
97#elif defined(__EMSCRIPTEN__)
107 std::filesystem::path app_data(
"/config");
114 std::filesystem::path app_data = home /
".yaze";
131 wchar_t path[MAX_PATH];
132 if (SUCCEEDED(SHGetFolderPathW(NULL, CSIDL_PERSONAL, NULL, 0, path))) {
133 std::filesystem::path docs_dir = std::filesystem::path(path) /
"Yaze";
142 std::filesystem::path docs_dir = home /
"Documents" /
"Yaze";
148#elif defined(__EMSCRIPTEN__)
150 std::filesystem::path docs_dir(
"/projects");
155 std::filesystem::path docs_dir = home /
"Documents" /
"Yaze";
159 docs_dir = home /
"Yaze";
263 const std::string& relative_path) {
264 std::vector<std::filesystem::path> search_paths;
268#ifdef YAZE_ASSETS_PATH
270 search_paths.push_back(std::filesystem::path(YAZE_ASSETS_PATH) /
278 static std::filesystem::path cached_cwd;
279 static bool cwd_cached =
false;
283 cached_cwd = std::filesystem::current_path(ec);
287 if (!cached_cwd.empty()) {
289 search_paths.push_back(cached_cwd /
"assets" / relative_path);
296 static std::filesystem::path cached_exe_dir;
297 static bool exe_dir_cached =
false;
299 if (!exe_dir_cached) {
302 char exe_path[PATH_MAX];
303 uint32_t size =
sizeof(exe_path);
304 if (_NSGetExecutablePath(exe_path, &size) == 0) {
305 cached_exe_dir = std::filesystem::path(exe_path).parent_path();
307#elif defined(__linux__)
308 char exe_path[PATH_MAX];
310 readlink(
"/proc/self/exe", exe_path,
sizeof(exe_path) - 1);
312 exe_path[len] =
'\0';
313 cached_exe_dir = std::filesystem::path(exe_path).parent_path();
316 wchar_t exe_path[MAX_PATH];
317 if (GetModuleFileNameW(NULL, exe_path, MAX_PATH) != 0) {
318 cached_exe_dir = std::filesystem::path(exe_path).parent_path();
324 exe_dir_cached =
true;
327 if (!cached_exe_dir.empty()) {
329 search_paths.push_back(cached_exe_dir /
"assets" / relative_path);
331 search_paths.push_back(cached_exe_dir.parent_path() /
"assets" /
337 auto contents_dir = cached_exe_dir.parent_path();
338 auto bundle_dir = contents_dir.parent_path();
339 auto bundle_parent = bundle_dir.parent_path();
340 search_paths.push_back(contents_dir /
"Resources" /
"assets" /
342 search_paths.push_back(bundle_parent /
"assets" / relative_path);
350 if (!cached_cwd.empty()) {
352 auto parent = cached_cwd.parent_path();
353 if (!parent.empty() && parent != cached_cwd) {
354 search_paths.push_back(parent /
"assets" / relative_path);
355 auto grandparent = parent.parent_path();
356 if (!grandparent.empty() && grandparent != parent) {
357 search_paths.push_back(grandparent /
"assets" / relative_path);
366 static std::filesystem::path cached_home;
367 static bool home_cached =
false;
378 if (!cached_home.empty() && cached_home !=
".") {
380 search_paths.push_back(cached_home /
".yaze" /
"assets" /
390 search_paths.push_back(
391 std::filesystem::path(
"/usr/local/share/yaze/assets") /
393 search_paths.push_back(std::filesystem::path(
"/usr/share/yaze/assets") /
402 const size_t max_paths_to_check = 20;
405 for (
const auto& candidate : search_paths) {
406 if (++checked > max_paths_to_check) {
412 std::error_code exists_ec;
413 if (std::filesystem::exists(candidate, exists_ec) && !exists_ec) {
415 auto status = std::filesystem::status(candidate, exists_ec);
417 status.type() != std::filesystem::file_type::not_found) {
428 return absl::NotFoundError(
429 absl::StrCat(
"Asset not found: ", relative_path));
431 }
catch (
const std::exception& e) {
432 return absl::InternalError(
433 absl::StrCat(
"Exception while searching for asset: ", e.what()));
435 return absl::InternalError(
"Unknown exception while searching for asset");