Вы не можете выбрать более 25 тем Темы должны начинаться с буквы или цифры, могут содержать дефисы(-) и должны содержать не более 35 символов.
 
 
 
 
 
 

164 строки
4.5 KiB

  1. //
  2. // Lol Engine
  3. //
  4. // Copyright © 2010–2024 Sam Hocevar <sam@hocevar.net>
  5. //
  6. // Lol Engine is free software. It comes without any warranty, to
  7. // the extent permitted by applicable law. You can redistribute it
  8. // and/or modify it under the terms of the Do What the Fuck You Want
  9. // to Public License, Version 2, as published by the WTFPL Task Force.
  10. // See http://www.wtfpl.net/ for more details.
  11. //
  12. #include <lol/engine/sys>
  13. #include <lol/msg>
  14. #include <vector> // std::vector
  15. #include <string> // std::string
  16. #include <cctype>
  17. #if !__ANDROID__ && !__EMSCRIPTEN__ && !__NX__
  18. # include <filesystem> // std::filesystem::exists
  19. #endif
  20. namespace lol::sys
  21. {
  22. #if _WIN32
  23. # define SEPARATOR '\\'
  24. #else
  25. # define SEPARATOR '/'
  26. #endif
  27. static std::vector<std::string> data_dir;
  28. void init(int argc, char *argv[],
  29. std::string const &projectdir,
  30. std::string const &solutiondir,
  31. std::string const &sourcesubdir)
  32. {
  33. using namespace std;
  34. msg::debug("project dir: “%s”\n", projectdir.c_str());
  35. msg::debug("solution dir: “%s”\n", solutiondir.c_str());
  36. msg::debug("source subdir: “%s”\n", sourcesubdir.c_str());
  37. //
  38. // Retrieve binary directory, defaulting to no directory on Android
  39. // and emscripten, and the current directory on other platforms.
  40. //
  41. #if __ANDROID__ || __EMSCRIPTEN__ || __NX__
  42. std::string binarydir = "";
  43. #else
  44. std::string binarydir = std::filesystem::current_path().string() + SEPARATOR;
  45. if (argc > 0)
  46. {
  47. char const *last_sep = strrchr(argv[0], SEPARATOR);
  48. if (last_sep)
  49. binarydir = std::string(argv[0], last_sep - argv[0] + 1);
  50. }
  51. #endif
  52. bool got_rootdir = false;
  53. //
  54. // If project dir and solution dir are set, add them to data; also
  55. // add current directory in case we were launched from another place.
  56. //
  57. if (!got_rootdir && projectdir.length() && solutiondir.length())
  58. {
  59. // This data dir is for standalone executables
  60. std::string rootdir = binarydir;
  61. #if !__NX__
  62. if (rootdir.length() && rootdir.back() != SEPARATOR)
  63. rootdir += SEPARATOR;
  64. add_data_dir(rootdir);
  65. #endif
  66. // This data dir is for engine stuff
  67. rootdir = solutiondir;
  68. if (rootdir.length() && rootdir.back() != SEPARATOR)
  69. rootdir += SEPARATOR;
  70. rootdir += "../src/"; // FIXME: use SEPARATOR?
  71. add_data_dir(rootdir);
  72. // This data dir is for submodule support stuff
  73. rootdir = solutiondir;
  74. if (rootdir.length() && rootdir.back() != SEPARATOR)
  75. rootdir += SEPARATOR;
  76. rootdir += "./lol/src/"; // FIXME: use SEPARATOR?
  77. add_data_dir(rootdir);
  78. // This data dir is for project-specific stuff
  79. rootdir = projectdir;
  80. if (rootdir.length() && rootdir.back() != SEPARATOR)
  81. rootdir += SEPARATOR;
  82. add_data_dir(rootdir);
  83. got_rootdir = true;
  84. }
  85. //
  86. // If no project dir, use the executable location as the starting point
  87. // to guess the data dir.
  88. //
  89. if (!got_rootdir)
  90. {
  91. // First climb back the hierarchy to get to the engine root and
  92. // add a data dir for engine stuff.
  93. std::string rootdir = binarydir;
  94. if (rootdir.length() && rootdir.back() != SEPARATOR)
  95. rootdir += SEPARATOR;
  96. for (int i = 1; i < (int)sourcesubdir.length(); ++i)
  97. {
  98. if ((sourcesubdir[i] == SEPARATOR
  99. && sourcesubdir[i - 1] != SEPARATOR)
  100. || i == (int)sourcesubdir.length() - 1)
  101. rootdir += "../";
  102. }
  103. rootdir += "src/";
  104. add_data_dir(rootdir);
  105. // This data dir is for project-specific stuff
  106. rootdir = binarydir;
  107. add_data_dir(rootdir);
  108. got_rootdir = true;
  109. }
  110. msg::debug("binary dir: “%s”\n", binarydir.c_str());
  111. for (int i = 0; i < int(data_dir.size()); ++i)
  112. msg::debug("data dir %d/%d: “%s”\n", i + 1, int(data_dir.size()),
  113. data_dir[i].c_str());
  114. }
  115. //
  116. // Data directory handling
  117. //
  118. void add_data_dir(std::string const &dir)
  119. {
  120. data_dir.push_back(dir);
  121. }
  122. std::string get_data_path(std::string const &file)
  123. {
  124. // If not an absolute path, look through known data directories
  125. if (file[0] != '/')
  126. for (auto const &dir : data_dir)
  127. {
  128. auto path = dir + file;
  129. #if !__ANDROID__ && !__EMSCRIPTEN__ && !__NX__
  130. std::error_code ec;
  131. if (std::filesystem::exists(path, ec))
  132. return path;
  133. #endif
  134. }
  135. return file;
  136. }
  137. } // namespace lol::sys