resource_loader.cpp 42 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327
  1. /**************************************************************************/
  2. /* resource_loader.cpp */
  3. /**************************************************************************/
  4. /* This file is part of: */
  5. /* GODOT ENGINE */
  6. /* https://godotengine.org */
  7. /**************************************************************************/
  8. /* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
  9. /* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
  10. /* */
  11. /* Permission is hereby granted, free of charge, to any person obtaining */
  12. /* a copy of this software and associated documentation files (the */
  13. /* "Software"), to deal in the Software without restriction, including */
  14. /* without limitation the rights to use, copy, modify, merge, publish, */
  15. /* distribute, sublicense, and/or sell copies of the Software, and to */
  16. /* permit persons to whom the Software is furnished to do so, subject to */
  17. /* the following conditions: */
  18. /* */
  19. /* The above copyright notice and this permission notice shall be */
  20. /* included in all copies or substantial portions of the Software. */
  21. /* */
  22. /* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
  23. /* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
  24. /* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
  25. /* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
  26. /* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
  27. /* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
  28. /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
  29. /**************************************************************************/
  30. #include "resource_loader.h"
  31. #include "core/config/project_settings.h"
  32. #include "core/io/file_access.h"
  33. #include "core/io/resource_importer.h"
  34. #include "core/object/script_language.h"
  35. #include "core/os/condition_variable.h"
  36. #include "core/os/os.h"
  37. #include "core/os/safe_binary_mutex.h"
  38. #include "core/string/print_string.h"
  39. #include "core/string/translation.h"
  40. #include "core/variant/variant_parser.h"
  41. #include "servers/rendering_server.h"
  42. #ifdef DEBUG_LOAD_THREADED
  43. #define print_lt(m_text) print_line(m_text)
  44. #else
  45. #define print_lt(m_text)
  46. #endif
  47. Ref<ResourceFormatLoader> ResourceLoader::loader[ResourceLoader::MAX_LOADERS];
  48. int ResourceLoader::loader_count = 0;
  49. bool ResourceFormatLoader::recognize_path(const String &p_path, const String &p_for_type) const {
  50. bool ret = false;
  51. if (GDVIRTUAL_CALL(_recognize_path, p_path, p_for_type, ret)) {
  52. return ret;
  53. }
  54. String extension = p_path.get_extension();
  55. List<String> extensions;
  56. if (p_for_type.is_empty()) {
  57. get_recognized_extensions(&extensions);
  58. } else {
  59. get_recognized_extensions_for_type(p_for_type, &extensions);
  60. }
  61. for (const String &E : extensions) {
  62. if (E.nocasecmp_to(extension) == 0) {
  63. return true;
  64. }
  65. }
  66. return false;
  67. }
  68. bool ResourceFormatLoader::handles_type(const String &p_type) const {
  69. bool success = false;
  70. GDVIRTUAL_CALL(_handles_type, p_type, success);
  71. return success;
  72. }
  73. void ResourceFormatLoader::get_classes_used(const String &p_path, HashSet<StringName> *r_classes) {
  74. Vector<String> ret;
  75. if (GDVIRTUAL_CALL(_get_classes_used, p_path, ret)) {
  76. for (int i = 0; i < ret.size(); i++) {
  77. r_classes->insert(ret[i]);
  78. }
  79. return;
  80. }
  81. String res = get_resource_type(p_path);
  82. if (!res.is_empty()) {
  83. r_classes->insert(res);
  84. }
  85. }
  86. String ResourceFormatLoader::get_resource_type(const String &p_path) const {
  87. String ret;
  88. GDVIRTUAL_CALL(_get_resource_type, p_path, ret);
  89. return ret;
  90. }
  91. String ResourceFormatLoader::get_resource_script_class(const String &p_path) const {
  92. String ret;
  93. GDVIRTUAL_CALL(_get_resource_script_class, p_path, ret);
  94. return ret;
  95. }
  96. ResourceUID::ID ResourceFormatLoader::get_resource_uid(const String &p_path) const {
  97. int64_t uid = ResourceUID::INVALID_ID;
  98. GDVIRTUAL_CALL(_get_resource_uid, p_path, uid);
  99. return uid;
  100. }
  101. void ResourceFormatLoader::get_recognized_extensions_for_type(const String &p_type, List<String> *p_extensions) const {
  102. if (p_type.is_empty() || handles_type(p_type)) {
  103. get_recognized_extensions(p_extensions);
  104. }
  105. }
  106. void ResourceLoader::get_recognized_extensions_for_type(const String &p_type, List<String> *p_extensions) {
  107. for (int i = 0; i < loader_count; i++) {
  108. loader[i]->get_recognized_extensions_for_type(p_type, p_extensions);
  109. }
  110. }
  111. bool ResourceFormatLoader::exists(const String &p_path) const {
  112. bool success = false;
  113. if (GDVIRTUAL_CALL(_exists, p_path, success)) {
  114. return success;
  115. }
  116. return FileAccess::exists(p_path); // By default just check file.
  117. }
  118. void ResourceFormatLoader::get_recognized_extensions(List<String> *p_extensions) const {
  119. PackedStringArray exts;
  120. if (GDVIRTUAL_CALL(_get_recognized_extensions, exts)) {
  121. const String *r = exts.ptr();
  122. for (int i = 0; i < exts.size(); ++i) {
  123. p_extensions->push_back(r[i]);
  124. }
  125. }
  126. }
  127. Ref<Resource> ResourceFormatLoader::load(const String &p_path, const String &p_original_path, Error *r_error, bool p_use_sub_threads, float *r_progress, CacheMode p_cache_mode) {
  128. Variant res;
  129. if (GDVIRTUAL_CALL(_load, p_path, p_original_path, p_use_sub_threads, p_cache_mode, res)) {
  130. if (res.get_type() == Variant::INT) { // Error code, abort.
  131. if (r_error) {
  132. *r_error = (Error)res.operator int64_t();
  133. }
  134. return Ref<Resource>();
  135. } else { // Success, pass on result.
  136. if (r_error) {
  137. *r_error = OK;
  138. }
  139. return res;
  140. }
  141. }
  142. ERR_FAIL_V_MSG(Ref<Resource>(), "Failed to load resource '" + p_path + "'. ResourceFormatLoader::load was not implemented for this resource type.");
  143. }
  144. void ResourceFormatLoader::get_dependencies(const String &p_path, List<String> *p_dependencies, bool p_add_types) {
  145. PackedStringArray deps;
  146. if (GDVIRTUAL_CALL(_get_dependencies, p_path, p_add_types, deps)) {
  147. const String *r = deps.ptr();
  148. for (int i = 0; i < deps.size(); ++i) {
  149. p_dependencies->push_back(r[i]);
  150. }
  151. }
  152. }
  153. Error ResourceFormatLoader::rename_dependencies(const String &p_path, const HashMap<String, String> &p_map) {
  154. Dictionary deps_dict;
  155. for (KeyValue<String, String> E : p_map) {
  156. deps_dict[E.key] = E.value;
  157. }
  158. Error err = OK;
  159. GDVIRTUAL_CALL(_rename_dependencies, p_path, deps_dict, err);
  160. return err;
  161. }
  162. void ResourceFormatLoader::_bind_methods() {
  163. BIND_ENUM_CONSTANT(CACHE_MODE_IGNORE);
  164. BIND_ENUM_CONSTANT(CACHE_MODE_REUSE);
  165. BIND_ENUM_CONSTANT(CACHE_MODE_REPLACE);
  166. BIND_ENUM_CONSTANT(CACHE_MODE_IGNORE_DEEP);
  167. BIND_ENUM_CONSTANT(CACHE_MODE_REPLACE_DEEP);
  168. GDVIRTUAL_BIND(_get_recognized_extensions);
  169. GDVIRTUAL_BIND(_recognize_path, "path", "type");
  170. GDVIRTUAL_BIND(_handles_type, "type");
  171. GDVIRTUAL_BIND(_get_resource_type, "path");
  172. GDVIRTUAL_BIND(_get_resource_script_class, "path");
  173. GDVIRTUAL_BIND(_get_resource_uid, "path");
  174. GDVIRTUAL_BIND(_get_dependencies, "path", "add_types");
  175. GDVIRTUAL_BIND(_rename_dependencies, "path", "renames");
  176. GDVIRTUAL_BIND(_exists, "path");
  177. GDVIRTUAL_BIND(_get_classes_used, "path");
  178. GDVIRTUAL_BIND(_load, "path", "original_path", "use_sub_threads", "cache_mode");
  179. }
  180. ///////////////////////////////////
  181. // This should be robust enough to be called redundantly without issues.
  182. void ResourceLoader::LoadToken::clear() {
  183. thread_load_mutex.lock();
  184. WorkerThreadPool::TaskID task_to_await = 0;
  185. if (!local_path.is_empty()) { // Empty is used for the special case where the load task is not registered.
  186. DEV_ASSERT(thread_load_tasks.has(local_path));
  187. ThreadLoadTask &load_task = thread_load_tasks[local_path];
  188. if (!load_task.awaited) {
  189. task_to_await = load_task.task_id;
  190. load_task.awaited = true;
  191. }
  192. thread_load_tasks.erase(local_path);
  193. local_path.clear();
  194. }
  195. if (!user_path.is_empty()) {
  196. DEV_ASSERT(user_load_tokens.has(user_path));
  197. user_load_tokens.erase(user_path);
  198. user_path.clear();
  199. }
  200. thread_load_mutex.unlock();
  201. // If task is unused, await it here, locally, now the token data is consistent.
  202. if (task_to_await) {
  203. WorkerThreadPool::get_singleton()->wait_for_task_completion(task_to_await);
  204. }
  205. }
  206. ResourceLoader::LoadToken::~LoadToken() {
  207. clear();
  208. }
  209. Ref<Resource> ResourceLoader::_load(const String &p_path, const String &p_original_path, const String &p_type_hint, ResourceFormatLoader::CacheMode p_cache_mode, Error *r_error, bool p_use_sub_threads, float *r_progress) {
  210. const String &original_path = p_original_path.is_empty() ? p_path : p_original_path;
  211. load_nesting++;
  212. if (load_paths_stack->size()) {
  213. thread_load_mutex.lock();
  214. const String &parent_task_path = load_paths_stack->get(load_paths_stack->size() - 1);
  215. HashMap<String, ThreadLoadTask>::Iterator E = thread_load_tasks.find(parent_task_path);
  216. // Avoid double-tracking, for progress reporting, resources that boil down to a remapped path containing the real payload (e.g., imported resources).
  217. bool is_remapped_load = original_path == parent_task_path;
  218. if (E && !is_remapped_load) {
  219. E->value.sub_tasks.insert(p_original_path);
  220. }
  221. thread_load_mutex.unlock();
  222. }
  223. load_paths_stack->push_back(original_path);
  224. // Try all loaders and pick the first match for the type hint
  225. bool found = false;
  226. Ref<Resource> res;
  227. for (int i = 0; i < loader_count; i++) {
  228. if (!loader[i]->recognize_path(p_path, p_type_hint)) {
  229. continue;
  230. }
  231. found = true;
  232. res = loader[i]->load(p_path, original_path, r_error, p_use_sub_threads, r_progress, p_cache_mode);
  233. if (!res.is_null()) {
  234. break;
  235. }
  236. }
  237. load_paths_stack->resize(load_paths_stack->size() - 1);
  238. res_ref_overrides.erase(load_nesting);
  239. load_nesting--;
  240. if (!res.is_null()) {
  241. return res;
  242. }
  243. ERR_FAIL_COND_V_MSG(found, Ref<Resource>(),
  244. vformat("Failed loading resource: %s. Make sure resources have been imported by opening the project in the editor at least once.", p_path));
  245. #ifdef TOOLS_ENABLED
  246. Ref<FileAccess> file_check = FileAccess::create(FileAccess::ACCESS_RESOURCES);
  247. ERR_FAIL_COND_V_MSG(!file_check->file_exists(p_path), Ref<Resource>(), vformat("Resource file not found: %s (expected type: %s)", p_path, p_type_hint));
  248. #endif
  249. ERR_FAIL_V_MSG(Ref<Resource>(), vformat("No loader found for resource: %s (expected type: %s)", p_path, p_type_hint));
  250. }
  251. void ResourceLoader::_thread_load_function(void *p_userdata) {
  252. ThreadLoadTask &load_task = *(ThreadLoadTask *)p_userdata;
  253. thread_load_mutex.lock();
  254. caller_task_id = load_task.task_id;
  255. if (cleaning_tasks) {
  256. load_task.status = THREAD_LOAD_FAILED;
  257. thread_load_mutex.unlock();
  258. return;
  259. }
  260. thread_load_mutex.unlock();
  261. // Thread-safe either if it's the current thread or a brand new one.
  262. CallQueue *own_mq_override = nullptr;
  263. if (load_nesting == 0) {
  264. load_paths_stack = memnew(Vector<String>);
  265. if (!Thread::is_main_thread()) {
  266. // Let the caller thread use its own, for added flexibility. Provide one otherwise.
  267. if (MessageQueue::get_singleton() == MessageQueue::get_main_singleton()) {
  268. own_mq_override = memnew(CallQueue);
  269. MessageQueue::set_thread_singleton_override(own_mq_override);
  270. }
  271. set_current_thread_safe_for_nodes(true);
  272. }
  273. }
  274. // --
  275. Error load_err = OK;
  276. Ref<Resource> res = _load(load_task.remapped_path, load_task.remapped_path != load_task.local_path ? load_task.local_path : String(), load_task.type_hint, load_task.cache_mode, &load_err, load_task.use_sub_threads, &load_task.progress);
  277. if (MessageQueue::get_singleton() != MessageQueue::get_main_singleton()) {
  278. MessageQueue::get_singleton()->flush();
  279. }
  280. thread_load_mutex.lock();
  281. load_task.resource = res;
  282. load_task.progress = 1.0; // It was fully loaded at this point, so force progress to 1.0.
  283. load_task.error = load_err;
  284. if (load_task.error != OK) {
  285. load_task.status = THREAD_LOAD_FAILED;
  286. } else {
  287. load_task.status = THREAD_LOAD_LOADED;
  288. }
  289. if (load_task.cond_var) {
  290. load_task.cond_var->notify_all();
  291. memdelete(load_task.cond_var);
  292. load_task.cond_var = nullptr;
  293. }
  294. bool ignoring = load_task.cache_mode == ResourceFormatLoader::CACHE_MODE_IGNORE || load_task.cache_mode == ResourceFormatLoader::CACHE_MODE_IGNORE_DEEP;
  295. bool replacing = load_task.cache_mode == ResourceFormatLoader::CACHE_MODE_REPLACE || load_task.cache_mode == ResourceFormatLoader::CACHE_MODE_REPLACE_DEEP;
  296. bool unlock_pending = true;
  297. if (load_task.resource.is_valid()) {
  298. // From now on, no critical section needed as no one will write to the task anymore.
  299. // Moreover, the mutex being unlocked is a requirement if some of the calls below
  300. // that set the resource up invoke code that in turn requests resource loading.
  301. thread_load_mutex.unlock();
  302. unlock_pending = false;
  303. if (!ignoring) {
  304. if (replacing) {
  305. Ref<Resource> old_res = ResourceCache::get_ref(load_task.local_path);
  306. if (old_res.is_valid() && old_res != load_task.resource) {
  307. // If resource is already loaded, only replace its data, to avoid existing invalidating instances.
  308. old_res->copy_from(load_task.resource);
  309. load_task.resource = old_res;
  310. }
  311. }
  312. load_task.resource->set_path(load_task.local_path, replacing);
  313. } else {
  314. load_task.resource->set_path_cache(load_task.local_path);
  315. }
  316. if (load_task.xl_remapped) {
  317. load_task.resource->set_as_translation_remapped(true);
  318. }
  319. #ifdef TOOLS_ENABLED
  320. load_task.resource->set_edited(false);
  321. if (timestamp_on_load) {
  322. uint64_t mt = FileAccess::get_modified_time(load_task.remapped_path);
  323. //printf("mt %s: %lli\n",remapped_path.utf8().get_data(),mt);
  324. load_task.resource->set_last_modified_time(mt);
  325. }
  326. #endif
  327. if (_loaded_callback) {
  328. _loaded_callback(load_task.resource, load_task.local_path);
  329. }
  330. } else if (!ignoring) {
  331. Ref<Resource> existing = ResourceCache::get_ref(load_task.local_path);
  332. if (existing.is_valid()) {
  333. load_task.resource = existing;
  334. load_task.status = THREAD_LOAD_LOADED;
  335. load_task.progress = 1.0;
  336. thread_load_mutex.unlock();
  337. unlock_pending = false;
  338. if (_loaded_callback) {
  339. _loaded_callback(load_task.resource, load_task.local_path);
  340. }
  341. }
  342. }
  343. if (unlock_pending) {
  344. thread_load_mutex.unlock();
  345. }
  346. if (load_nesting == 0) {
  347. if (own_mq_override) {
  348. MessageQueue::set_thread_singleton_override(nullptr);
  349. memdelete(own_mq_override);
  350. }
  351. if (load_paths_stack) {
  352. memdelete(load_paths_stack);
  353. load_paths_stack = nullptr;
  354. }
  355. }
  356. }
  357. static String _validate_local_path(const String &p_path) {
  358. ResourceUID::ID uid = ResourceUID::get_singleton()->text_to_id(p_path);
  359. if (uid != ResourceUID::INVALID_ID) {
  360. return ResourceUID::get_singleton()->get_id_path(uid);
  361. } else if (p_path.is_relative_path()) {
  362. return ("res://" + p_path).simplify_path();
  363. } else {
  364. return ProjectSettings::get_singleton()->localize_path(p_path);
  365. }
  366. }
  367. Error ResourceLoader::load_threaded_request(const String &p_path, const String &p_type_hint, bool p_use_sub_threads, ResourceFormatLoader::CacheMode p_cache_mode) {
  368. thread_load_mutex.lock();
  369. if (user_load_tokens.has(p_path)) {
  370. print_verbose("load_threaded_request(): Another threaded load for resource path '" + p_path + "' has been initiated. Not an error.");
  371. user_load_tokens[p_path]->reference(); // Additional request.
  372. thread_load_mutex.unlock();
  373. return OK;
  374. }
  375. user_load_tokens[p_path] = nullptr;
  376. thread_load_mutex.unlock();
  377. Ref<ResourceLoader::LoadToken> token = _load_start(p_path, p_type_hint, p_use_sub_threads ? LOAD_THREAD_DISTRIBUTE : LOAD_THREAD_SPAWN_SINGLE, p_cache_mode);
  378. if (token.is_valid()) {
  379. thread_load_mutex.lock();
  380. token->user_path = p_path;
  381. token->reference(); // First request.
  382. user_load_tokens[p_path] = token.ptr();
  383. print_lt("REQUEST: user load tokens: " + itos(user_load_tokens.size()));
  384. thread_load_mutex.unlock();
  385. return OK;
  386. } else {
  387. return FAILED;
  388. }
  389. }
  390. Ref<Resource> ResourceLoader::load(const String &p_path, const String &p_type_hint, ResourceFormatLoader::CacheMode p_cache_mode, Error *r_error) {
  391. if (r_error) {
  392. *r_error = OK;
  393. }
  394. Ref<LoadToken> load_token = _load_start(p_path, p_type_hint, LOAD_THREAD_FROM_CURRENT, p_cache_mode);
  395. if (!load_token.is_valid()) {
  396. if (r_error) {
  397. *r_error = FAILED;
  398. }
  399. return Ref<Resource>();
  400. }
  401. Ref<Resource> res = _load_complete(*load_token.ptr(), r_error);
  402. return res;
  403. }
  404. Ref<ResourceLoader::LoadToken> ResourceLoader::_load_start(const String &p_path, const String &p_type_hint, LoadThreadMode p_thread_mode, ResourceFormatLoader::CacheMode p_cache_mode) {
  405. String local_path = _validate_local_path(p_path);
  406. bool ignoring_cache = p_cache_mode == ResourceFormatLoader::CACHE_MODE_IGNORE || p_cache_mode == ResourceFormatLoader::CACHE_MODE_IGNORE_DEEP;
  407. Ref<LoadToken> load_token;
  408. bool must_not_register = false;
  409. ThreadLoadTask unregistered_load_task; // Once set, must be valid up to the call to do the load.
  410. ThreadLoadTask *load_task_ptr = nullptr;
  411. bool run_on_current_thread = false;
  412. {
  413. MutexLock thread_load_lock(thread_load_mutex);
  414. if (!ignoring_cache && thread_load_tasks.has(local_path)) {
  415. load_token = Ref<LoadToken>(thread_load_tasks[local_path].load_token);
  416. if (load_token.is_valid()) {
  417. return load_token;
  418. } else {
  419. // The token is dying (reached 0 on another thread).
  420. // Ensure it's killed now so the path can be safely reused right away.
  421. thread_load_tasks[local_path].load_token->clear();
  422. }
  423. }
  424. load_token.instantiate();
  425. load_token->local_path = local_path;
  426. //create load task
  427. {
  428. ThreadLoadTask load_task;
  429. load_task.remapped_path = _path_remap(local_path, &load_task.xl_remapped);
  430. load_task.load_token = load_token.ptr();
  431. load_task.local_path = local_path;
  432. load_task.type_hint = p_type_hint;
  433. load_task.cache_mode = p_cache_mode;
  434. load_task.use_sub_threads = p_thread_mode == LOAD_THREAD_DISTRIBUTE;
  435. if (p_cache_mode == ResourceFormatLoader::CACHE_MODE_REUSE) {
  436. Ref<Resource> existing = ResourceCache::get_ref(local_path);
  437. if (existing.is_valid()) {
  438. //referencing is fine
  439. load_task.resource = existing;
  440. load_task.status = THREAD_LOAD_LOADED;
  441. load_task.progress = 1.0;
  442. thread_load_tasks[local_path] = load_task;
  443. return load_token;
  444. }
  445. }
  446. // If we want to ignore cache, but there's another task loading it, we can't add this one to the map and we also have to finish within scope.
  447. must_not_register = ignoring_cache && thread_load_tasks.has(local_path);
  448. if (must_not_register) {
  449. load_token->local_path.clear();
  450. unregistered_load_task = load_task;
  451. load_task_ptr = &unregistered_load_task;
  452. } else {
  453. DEV_ASSERT(!thread_load_tasks.has(local_path));
  454. HashMap<String, ResourceLoader::ThreadLoadTask>::Iterator E = thread_load_tasks.insert(local_path, load_task);
  455. load_task_ptr = &E->value;
  456. }
  457. }
  458. run_on_current_thread = must_not_register || p_thread_mode == LOAD_THREAD_FROM_CURRENT;
  459. if (run_on_current_thread) {
  460. load_task_ptr->thread_id = Thread::get_caller_id();
  461. } else {
  462. load_task_ptr->task_id = WorkerThreadPool::get_singleton()->add_native_task(&ResourceLoader::_thread_load_function, load_task_ptr);
  463. }
  464. }
  465. if (run_on_current_thread) {
  466. _thread_load_function(load_task_ptr);
  467. if (must_not_register) {
  468. load_token->res_if_unregistered = load_task_ptr->resource;
  469. }
  470. }
  471. return load_token;
  472. }
  473. float ResourceLoader::_dependency_get_progress(const String &p_path) {
  474. if (thread_load_tasks.has(p_path)) {
  475. ThreadLoadTask &load_task = thread_load_tasks[p_path];
  476. float current_progress = 0.0;
  477. int dep_count = load_task.sub_tasks.size();
  478. if (dep_count > 0) {
  479. for (const String &E : load_task.sub_tasks) {
  480. current_progress += _dependency_get_progress(E);
  481. }
  482. current_progress /= float(dep_count);
  483. current_progress *= 0.5;
  484. current_progress += load_task.progress * 0.5;
  485. } else {
  486. current_progress = load_task.progress;
  487. }
  488. load_task.max_reported_progress = MAX(load_task.max_reported_progress, current_progress);
  489. return load_task.max_reported_progress;
  490. } else {
  491. return 1.0; //assume finished loading it so it no longer exists
  492. }
  493. }
  494. ResourceLoader::ThreadLoadStatus ResourceLoader::load_threaded_get_status(const String &p_path, float *r_progress) {
  495. bool ensure_progress = false;
  496. ThreadLoadStatus status = THREAD_LOAD_IN_PROGRESS;
  497. {
  498. MutexLock thread_load_lock(thread_load_mutex);
  499. if (!user_load_tokens.has(p_path)) {
  500. print_verbose("load_threaded_get_status(): No threaded load for resource path '" + p_path + "' has been initiated or its result has already been collected.");
  501. return THREAD_LOAD_INVALID_RESOURCE;
  502. }
  503. String local_path = _validate_local_path(p_path);
  504. if (!thread_load_tasks.has(local_path)) {
  505. #ifdef DEV_ENABLED
  506. CRASH_NOW();
  507. #endif
  508. // On non-dev, be defensive and at least avoid crashing (at this point at least).
  509. return THREAD_LOAD_INVALID_RESOURCE;
  510. }
  511. ThreadLoadTask &load_task = thread_load_tasks[local_path];
  512. status = load_task.status;
  513. if (r_progress) {
  514. *r_progress = _dependency_get_progress(local_path);
  515. }
  516. // Support userland polling in a loop on the main thread.
  517. if (Thread::is_main_thread() && status == THREAD_LOAD_IN_PROGRESS) {
  518. uint64_t frame = Engine::get_singleton()->get_process_frames();
  519. if (frame == load_task.last_progress_check_main_thread_frame) {
  520. ensure_progress = true;
  521. } else {
  522. load_task.last_progress_check_main_thread_frame = frame;
  523. }
  524. }
  525. }
  526. if (ensure_progress) {
  527. _ensure_load_progress();
  528. }
  529. return status;
  530. }
  531. Ref<Resource> ResourceLoader::load_threaded_get(const String &p_path, Error *r_error) {
  532. if (r_error) {
  533. *r_error = OK;
  534. }
  535. Ref<Resource> res;
  536. {
  537. MutexLock thread_load_lock(thread_load_mutex);
  538. if (!user_load_tokens.has(p_path)) {
  539. print_verbose("load_threaded_get(): No threaded load for resource path '" + p_path + "' has been initiated or its result has already been collected.");
  540. if (r_error) {
  541. *r_error = ERR_INVALID_PARAMETER;
  542. }
  543. return Ref<Resource>();
  544. }
  545. LoadToken *load_token = user_load_tokens[p_path];
  546. if (!load_token) {
  547. // This happens if requested from one thread and rapidly querying from another.
  548. if (r_error) {
  549. *r_error = ERR_BUSY;
  550. }
  551. return Ref<Resource>();
  552. }
  553. // Support userland requesting on the main thread before the load is reported to be complete.
  554. if (Thread::is_main_thread() && !load_token->local_path.is_empty()) {
  555. const ThreadLoadTask &load_task = thread_load_tasks[load_token->local_path];
  556. while (load_task.status == THREAD_LOAD_IN_PROGRESS) {
  557. thread_load_lock.~MutexLock();
  558. bool exit = !_ensure_load_progress();
  559. OS::get_singleton()->delay_usec(1000);
  560. new (&thread_load_lock) MutexLock(thread_load_mutex);
  561. if (exit) {
  562. break;
  563. }
  564. }
  565. }
  566. res = _load_complete_inner(*load_token, r_error, thread_load_lock);
  567. if (load_token->unreference()) {
  568. memdelete(load_token);
  569. }
  570. }
  571. print_lt("GET: user load tokens: " + itos(user_load_tokens.size()));
  572. return res;
  573. }
  574. Ref<Resource> ResourceLoader::_load_complete(LoadToken &p_load_token, Error *r_error) {
  575. MutexLock thread_load_lock(thread_load_mutex);
  576. return _load_complete_inner(p_load_token, r_error, thread_load_lock);
  577. }
  578. Ref<Resource> ResourceLoader::_load_complete_inner(LoadToken &p_load_token, Error *r_error, MutexLock<SafeBinaryMutex<BINARY_MUTEX_TAG>> &p_thread_load_lock) {
  579. if (r_error) {
  580. *r_error = OK;
  581. }
  582. if (!p_load_token.local_path.is_empty()) {
  583. if (!thread_load_tasks.has(p_load_token.local_path)) {
  584. #ifdef DEV_ENABLED
  585. CRASH_NOW();
  586. #endif
  587. // On non-dev, be defensive and at least avoid crashing (at this point at least).
  588. if (r_error) {
  589. *r_error = ERR_BUG;
  590. }
  591. return Ref<Resource>();
  592. }
  593. ThreadLoadTask &load_task = thread_load_tasks[p_load_token.local_path];
  594. if (load_task.status == THREAD_LOAD_IN_PROGRESS) {
  595. DEV_ASSERT((load_task.task_id == 0) != (load_task.thread_id == 0));
  596. if ((load_task.task_id != 0 && load_task.task_id == caller_task_id) ||
  597. (load_task.thread_id != 0 && load_task.thread_id == Thread::get_caller_id())) {
  598. // Load is in progress, but it's precisely this thread the one in charge.
  599. // That means this is a cyclic load.
  600. if (r_error) {
  601. *r_error = ERR_BUSY;
  602. }
  603. return Ref<Resource>();
  604. }
  605. bool loader_is_wtp = load_task.task_id != 0;
  606. Error wtp_task_err = FAILED;
  607. if (loader_is_wtp) {
  608. // Loading thread is in the worker pool.
  609. load_task.awaited = true;
  610. thread_load_mutex.unlock();
  611. wtp_task_err = WorkerThreadPool::get_singleton()->wait_for_task_completion(load_task.task_id);
  612. }
  613. if (load_task.status == THREAD_LOAD_IN_PROGRESS) { // If early errored, awaiting would deadlock.
  614. if (loader_is_wtp) {
  615. if (wtp_task_err == ERR_BUSY) {
  616. // The WorkerThreadPool has reported that the current task wants to await on an older one.
  617. // That't not allowed for safety, to avoid deadlocks. Fortunately, though, in the context of
  618. // resource loading that means that the task to wait for can be restarted here to break the
  619. // cycle, with as much recursion into this process as needed.
  620. // When the stack is eventually unrolled, the original load will have been notified to go on.
  621. // CACHE_MODE_IGNORE is needed because, otherwise, the new request would just see there's
  622. // an ongoing load for that resource and wait for it again. This value forces a new load.
  623. Ref<ResourceLoader::LoadToken> token = _load_start(load_task.local_path, load_task.type_hint, LOAD_THREAD_DISTRIBUTE, ResourceFormatLoader::CACHE_MODE_IGNORE);
  624. Ref<Resource> resource = _load_complete(*token.ptr(), &wtp_task_err);
  625. if (r_error) {
  626. *r_error = wtp_task_err;
  627. }
  628. thread_load_mutex.lock();
  629. return resource;
  630. } else {
  631. DEV_ASSERT(wtp_task_err == OK);
  632. thread_load_mutex.lock();
  633. }
  634. } else {
  635. // Loading thread is main or user thread.
  636. if (!load_task.cond_var) {
  637. load_task.cond_var = memnew(ConditionVariable);
  638. }
  639. do {
  640. load_task.cond_var->wait(p_thread_load_lock);
  641. DEV_ASSERT(thread_load_tasks.has(p_load_token.local_path) && p_load_token.get_reference_count());
  642. } while (load_task.cond_var);
  643. }
  644. } else {
  645. if (loader_is_wtp) {
  646. thread_load_mutex.lock();
  647. }
  648. }
  649. }
  650. if (cleaning_tasks) {
  651. load_task.resource = Ref<Resource>();
  652. load_task.error = FAILED;
  653. }
  654. Ref<Resource> resource = load_task.resource;
  655. if (r_error) {
  656. *r_error = load_task.error;
  657. }
  658. return resource;
  659. } else {
  660. // Special case of an unregistered task.
  661. // The resource should have been loaded by now.
  662. Ref<Resource> resource = p_load_token.res_if_unregistered;
  663. if (!resource.is_valid()) {
  664. if (r_error) {
  665. *r_error = FAILED;
  666. }
  667. }
  668. return resource;
  669. }
  670. }
  671. bool ResourceLoader::_ensure_load_progress() {
  672. // Some servers may need a new engine iteration to allow the load to progress.
  673. // Since the only known one is the rendering server (in single thread mode), let's keep it simple and just sync it.
  674. // This may be refactored in the future to support other servers and have less coupling.
  675. if (OS::get_singleton()->get_render_thread_mode() == OS::RENDER_SEPARATE_THREAD) {
  676. return false; // Not needed.
  677. }
  678. RenderingServer::get_singleton()->sync();
  679. return true;
  680. }
  681. Ref<Resource> ResourceLoader::ensure_resource_ref_override_for_outer_load(const String &p_path, const String &p_res_type) {
  682. ERR_FAIL_COND_V(load_nesting == 0, Ref<Resource>()); // It makes no sense to use this from nesting level 0.
  683. const String &local_path = _validate_local_path(p_path);
  684. HashMap<String, Ref<Resource>> &overrides = res_ref_overrides[load_nesting - 1];
  685. HashMap<String, Ref<Resource>>::Iterator E = overrides.find(local_path);
  686. if (E) {
  687. return E->value;
  688. } else {
  689. Object *obj = ClassDB::instantiate(p_res_type);
  690. ERR_FAIL_NULL_V(obj, Ref<Resource>());
  691. Ref<Resource> res(obj);
  692. if (!res.is_valid()) {
  693. memdelete(obj);
  694. ERR_FAIL_V(Ref<Resource>());
  695. }
  696. overrides[local_path] = res;
  697. return res;
  698. }
  699. }
  700. Ref<Resource> ResourceLoader::get_resource_ref_override(const String &p_path) {
  701. DEV_ASSERT(p_path == _validate_local_path(p_path));
  702. HashMap<int, HashMap<String, Ref<Resource>>>::Iterator E = res_ref_overrides.find(load_nesting);
  703. if (!E) {
  704. return nullptr;
  705. }
  706. HashMap<String, Ref<Resource>>::Iterator F = E->value.find(p_path);
  707. if (!F) {
  708. return nullptr;
  709. }
  710. return F->value;
  711. }
  712. bool ResourceLoader::exists(const String &p_path, const String &p_type_hint) {
  713. String local_path = _validate_local_path(p_path);
  714. if (ResourceCache::has(local_path)) {
  715. return true; // If cached, it probably exists
  716. }
  717. bool xl_remapped = false;
  718. String path = _path_remap(local_path, &xl_remapped);
  719. // Try all loaders and pick the first match for the type hint
  720. for (int i = 0; i < loader_count; i++) {
  721. if (!loader[i]->recognize_path(path, p_type_hint)) {
  722. continue;
  723. }
  724. if (loader[i]->exists(path)) {
  725. return true;
  726. }
  727. }
  728. return false;
  729. }
  730. void ResourceLoader::add_resource_format_loader(Ref<ResourceFormatLoader> p_format_loader, bool p_at_front) {
  731. ERR_FAIL_COND(p_format_loader.is_null());
  732. ERR_FAIL_COND(loader_count >= MAX_LOADERS);
  733. if (p_at_front) {
  734. for (int i = loader_count; i > 0; i--) {
  735. loader[i] = loader[i - 1];
  736. }
  737. loader[0] = p_format_loader;
  738. loader_count++;
  739. } else {
  740. loader[loader_count++] = p_format_loader;
  741. }
  742. }
  743. void ResourceLoader::remove_resource_format_loader(Ref<ResourceFormatLoader> p_format_loader) {
  744. ERR_FAIL_COND(p_format_loader.is_null());
  745. // Find loader
  746. int i = 0;
  747. for (; i < loader_count; ++i) {
  748. if (loader[i] == p_format_loader) {
  749. break;
  750. }
  751. }
  752. ERR_FAIL_COND(i >= loader_count); // Not found
  753. // Shift next loaders up
  754. for (; i < loader_count - 1; ++i) {
  755. loader[i] = loader[i + 1];
  756. }
  757. loader[loader_count - 1].unref();
  758. --loader_count;
  759. }
  760. int ResourceLoader::get_import_order(const String &p_path) {
  761. String local_path = _path_remap(_validate_local_path(p_path));
  762. for (int i = 0; i < loader_count; i++) {
  763. if (!loader[i]->recognize_path(local_path)) {
  764. continue;
  765. }
  766. return loader[i]->get_import_order(p_path);
  767. }
  768. return 0;
  769. }
  770. String ResourceLoader::get_import_group_file(const String &p_path) {
  771. String local_path = _path_remap(_validate_local_path(p_path));
  772. for (int i = 0; i < loader_count; i++) {
  773. if (!loader[i]->recognize_path(local_path)) {
  774. continue;
  775. }
  776. return loader[i]->get_import_group_file(p_path);
  777. }
  778. return String(); //not found
  779. }
  780. bool ResourceLoader::is_import_valid(const String &p_path) {
  781. String local_path = _path_remap(_validate_local_path(p_path));
  782. for (int i = 0; i < loader_count; i++) {
  783. if (!loader[i]->recognize_path(local_path)) {
  784. continue;
  785. }
  786. return loader[i]->is_import_valid(p_path);
  787. }
  788. return false; //not found
  789. }
  790. bool ResourceLoader::is_imported(const String &p_path) {
  791. String local_path = _path_remap(_validate_local_path(p_path));
  792. for (int i = 0; i < loader_count; i++) {
  793. if (!loader[i]->recognize_path(local_path)) {
  794. continue;
  795. }
  796. return loader[i]->is_imported(p_path);
  797. }
  798. return false; //not found
  799. }
  800. void ResourceLoader::get_dependencies(const String &p_path, List<String> *p_dependencies, bool p_add_types) {
  801. String local_path = _path_remap(_validate_local_path(p_path));
  802. for (int i = 0; i < loader_count; i++) {
  803. if (!loader[i]->recognize_path(local_path)) {
  804. continue;
  805. }
  806. loader[i]->get_dependencies(local_path, p_dependencies, p_add_types);
  807. }
  808. }
  809. Error ResourceLoader::rename_dependencies(const String &p_path, const HashMap<String, String> &p_map) {
  810. String local_path = _path_remap(_validate_local_path(p_path));
  811. for (int i = 0; i < loader_count; i++) {
  812. if (!loader[i]->recognize_path(local_path)) {
  813. continue;
  814. }
  815. return loader[i]->rename_dependencies(local_path, p_map);
  816. }
  817. return OK; // ??
  818. }
  819. void ResourceLoader::get_classes_used(const String &p_path, HashSet<StringName> *r_classes) {
  820. String local_path = _validate_local_path(p_path);
  821. for (int i = 0; i < loader_count; i++) {
  822. if (!loader[i]->recognize_path(local_path)) {
  823. continue;
  824. }
  825. return loader[i]->get_classes_used(p_path, r_classes);
  826. }
  827. }
  828. String ResourceLoader::get_resource_type(const String &p_path) {
  829. String local_path = _validate_local_path(p_path);
  830. for (int i = 0; i < loader_count; i++) {
  831. String result = loader[i]->get_resource_type(local_path);
  832. if (!result.is_empty()) {
  833. return result;
  834. }
  835. }
  836. return "";
  837. }
  838. String ResourceLoader::get_resource_script_class(const String &p_path) {
  839. String local_path = _validate_local_path(p_path);
  840. for (int i = 0; i < loader_count; i++) {
  841. String result = loader[i]->get_resource_script_class(local_path);
  842. if (!result.is_empty()) {
  843. return result;
  844. }
  845. }
  846. return "";
  847. }
  848. ResourceUID::ID ResourceLoader::get_resource_uid(const String &p_path) {
  849. String local_path = _validate_local_path(p_path);
  850. for (int i = 0; i < loader_count; i++) {
  851. ResourceUID::ID id = loader[i]->get_resource_uid(local_path);
  852. if (id != ResourceUID::INVALID_ID) {
  853. return id;
  854. }
  855. }
  856. return ResourceUID::INVALID_ID;
  857. }
  858. String ResourceLoader::_path_remap(const String &p_path, bool *r_translation_remapped) {
  859. String new_path = p_path;
  860. if (translation_remaps.has(p_path)) {
  861. // translation_remaps has the following format:
  862. // { "res://path.png": PackedStringArray( "res://path-ru.png:ru", "res://path-de.png:de" ) }
  863. // To find the path of the remapped resource, we extract the locale name after
  864. // the last ':' to match the project locale.
  865. // An extra remap may still be necessary afterwards due to the text -> binary converter on export.
  866. String locale = TranslationServer::get_singleton()->get_locale();
  867. ERR_FAIL_COND_V_MSG(locale.length() < 2, p_path, "Could not remap path '" + p_path + "' for translation as configured locale '" + locale + "' is invalid.");
  868. Vector<String> &res_remaps = *translation_remaps.getptr(new_path);
  869. int best_score = 0;
  870. for (int i = 0; i < res_remaps.size(); i++) {
  871. int split = res_remaps[i].rfind(":");
  872. if (split == -1) {
  873. continue;
  874. }
  875. String l = res_remaps[i].substr(split + 1).strip_edges();
  876. int score = TranslationServer::get_singleton()->compare_locales(locale, l);
  877. if (score > 0 && score >= best_score) {
  878. new_path = res_remaps[i].left(split);
  879. best_score = score;
  880. if (score == 10) {
  881. break; // Exact match, skip the rest.
  882. }
  883. }
  884. }
  885. if (r_translation_remapped) {
  886. *r_translation_remapped = true;
  887. }
  888. // Fallback to p_path if new_path does not exist.
  889. if (!FileAccess::exists(new_path + ".import") && !FileAccess::exists(new_path)) {
  890. WARN_PRINT(vformat("Translation remap '%s' does not exist. Falling back to '%s'.", new_path, p_path));
  891. new_path = p_path;
  892. }
  893. }
  894. if (path_remaps.has(new_path)) {
  895. new_path = path_remaps[new_path];
  896. } else {
  897. // Try file remap.
  898. Error err;
  899. Ref<FileAccess> f = FileAccess::open(new_path + ".remap", FileAccess::READ, &err);
  900. if (f.is_valid()) {
  901. VariantParser::StreamFile stream;
  902. stream.f = f;
  903. String assign;
  904. Variant value;
  905. VariantParser::Tag next_tag;
  906. int lines = 0;
  907. String error_text;
  908. while (true) {
  909. assign = Variant();
  910. next_tag.fields.clear();
  911. next_tag.name = String();
  912. err = VariantParser::parse_tag_assign_eof(&stream, lines, error_text, next_tag, assign, value, nullptr, true);
  913. if (err == ERR_FILE_EOF) {
  914. break;
  915. } else if (err != OK) {
  916. ERR_PRINT("Parse error: " + p_path + ".remap:" + itos(lines) + " error: " + error_text + ".");
  917. break;
  918. }
  919. if (assign == "path") {
  920. new_path = value;
  921. break;
  922. } else if (next_tag.name != "remap") {
  923. break;
  924. }
  925. }
  926. }
  927. }
  928. return new_path;
  929. }
  930. String ResourceLoader::import_remap(const String &p_path) {
  931. if (ResourceFormatImporter::get_singleton()->recognize_path(p_path)) {
  932. return ResourceFormatImporter::get_singleton()->get_internal_resource_path(p_path);
  933. }
  934. return p_path;
  935. }
  936. String ResourceLoader::path_remap(const String &p_path) {
  937. return _path_remap(p_path);
  938. }
  939. void ResourceLoader::reload_translation_remaps() {
  940. ResourceCache::lock.lock();
  941. List<Resource *> to_reload;
  942. SelfList<Resource> *E = remapped_list.first();
  943. while (E) {
  944. to_reload.push_back(E->self());
  945. E = E->next();
  946. }
  947. ResourceCache::lock.unlock();
  948. //now just make sure to not delete any of these resources while changing locale..
  949. while (to_reload.front()) {
  950. to_reload.front()->get()->reload_from_file();
  951. to_reload.pop_front();
  952. }
  953. }
  954. void ResourceLoader::load_translation_remaps() {
  955. if (!ProjectSettings::get_singleton()->has_setting("internationalization/locale/translation_remaps")) {
  956. return;
  957. }
  958. Dictionary remaps = GLOBAL_GET("internationalization/locale/translation_remaps");
  959. List<Variant> keys;
  960. remaps.get_key_list(&keys);
  961. for (const Variant &E : keys) {
  962. Array langs = remaps[E];
  963. Vector<String> lang_remaps;
  964. lang_remaps.resize(langs.size());
  965. String *lang_remaps_ptrw = lang_remaps.ptrw();
  966. for (const Variant &lang : langs) {
  967. *lang_remaps_ptrw++ = lang;
  968. }
  969. translation_remaps[String(E)] = lang_remaps;
  970. }
  971. }
  972. void ResourceLoader::clear_translation_remaps() {
  973. translation_remaps.clear();
  974. while (remapped_list.first() != nullptr) {
  975. remapped_list.remove(remapped_list.first());
  976. }
  977. }
  978. void ResourceLoader::clear_thread_load_tasks() {
  979. // Bring the thing down as quickly as possible without causing deadlocks or leaks.
  980. thread_load_mutex.lock();
  981. cleaning_tasks = true;
  982. while (true) {
  983. bool none_running = true;
  984. if (thread_load_tasks.size()) {
  985. for (KeyValue<String, ResourceLoader::ThreadLoadTask> &E : thread_load_tasks) {
  986. if (E.value.status == THREAD_LOAD_IN_PROGRESS) {
  987. if (E.value.cond_var) {
  988. E.value.cond_var->notify_all();
  989. memdelete(E.value.cond_var);
  990. E.value.cond_var = nullptr;
  991. }
  992. none_running = false;
  993. }
  994. }
  995. }
  996. if (none_running) {
  997. break;
  998. }
  999. thread_load_mutex.unlock();
  1000. OS::get_singleton()->delay_usec(1000);
  1001. thread_load_mutex.lock();
  1002. }
  1003. while (user_load_tokens.begin()) {
  1004. // User load tokens remove themselves from the map on destruction.
  1005. memdelete(user_load_tokens.begin()->value);
  1006. }
  1007. user_load_tokens.clear();
  1008. thread_load_tasks.clear();
  1009. cleaning_tasks = false;
  1010. thread_load_mutex.unlock();
  1011. }
  1012. void ResourceLoader::load_path_remaps() {
  1013. if (!ProjectSettings::get_singleton()->has_setting("path_remap/remapped_paths")) {
  1014. return;
  1015. }
  1016. Vector<String> remaps = GLOBAL_GET("path_remap/remapped_paths");
  1017. int rc = remaps.size();
  1018. ERR_FAIL_COND(rc & 1); //must be even
  1019. const String *r = remaps.ptr();
  1020. for (int i = 0; i < rc; i += 2) {
  1021. path_remaps[r[i]] = r[i + 1];
  1022. }
  1023. }
  1024. void ResourceLoader::clear_path_remaps() {
  1025. path_remaps.clear();
  1026. }
  1027. void ResourceLoader::set_load_callback(ResourceLoadedCallback p_callback) {
  1028. _loaded_callback = p_callback;
  1029. }
  1030. ResourceLoadedCallback ResourceLoader::_loaded_callback = nullptr;
  1031. Ref<ResourceFormatLoader> ResourceLoader::_find_custom_resource_format_loader(const String &path) {
  1032. for (int i = 0; i < loader_count; ++i) {
  1033. if (loader[i]->get_script_instance() && loader[i]->get_script_instance()->get_script()->get_path() == path) {
  1034. return loader[i];
  1035. }
  1036. }
  1037. return Ref<ResourceFormatLoader>();
  1038. }
  1039. bool ResourceLoader::add_custom_resource_format_loader(const String &script_path) {
  1040. if (_find_custom_resource_format_loader(script_path).is_valid()) {
  1041. return false;
  1042. }
  1043. Ref<Resource> res = ResourceLoader::load(script_path);
  1044. ERR_FAIL_COND_V(res.is_null(), false);
  1045. ERR_FAIL_COND_V(!res->is_class("Script"), false);
  1046. Ref<Script> s = res;
  1047. StringName ibt = s->get_instance_base_type();
  1048. bool valid_type = ClassDB::is_parent_class(ibt, "ResourceFormatLoader");
  1049. ERR_FAIL_COND_V_MSG(!valid_type, false, vformat("Failed to add a custom resource loader, script '%s' does not inherit 'ResourceFormatLoader'.", script_path));
  1050. Object *obj = ClassDB::instantiate(ibt);
  1051. ERR_FAIL_NULL_V_MSG(obj, false, vformat("Failed to add a custom resource loader, cannot instantiate '%s'.", ibt));
  1052. Ref<ResourceFormatLoader> crl = Object::cast_to<ResourceFormatLoader>(obj);
  1053. crl->set_script(s);
  1054. ResourceLoader::add_resource_format_loader(crl);
  1055. return true;
  1056. }
  1057. void ResourceLoader::set_create_missing_resources_if_class_unavailable(bool p_enable) {
  1058. create_missing_resources_if_class_unavailable = p_enable;
  1059. }
  1060. void ResourceLoader::add_custom_loaders() {
  1061. // Custom loaders registration exploits global class names
  1062. String custom_loader_base_class = ResourceFormatLoader::get_class_static();
  1063. List<StringName> global_classes;
  1064. ScriptServer::get_global_class_list(&global_classes);
  1065. for (const StringName &class_name : global_classes) {
  1066. StringName base_class = ScriptServer::get_global_class_native_base(class_name);
  1067. if (base_class == custom_loader_base_class) {
  1068. String path = ScriptServer::get_global_class_path(class_name);
  1069. add_custom_resource_format_loader(path);
  1070. }
  1071. }
  1072. }
  1073. void ResourceLoader::remove_custom_loaders() {
  1074. Vector<Ref<ResourceFormatLoader>> custom_loaders;
  1075. for (int i = 0; i < loader_count; ++i) {
  1076. if (loader[i]->get_script_instance()) {
  1077. custom_loaders.push_back(loader[i]);
  1078. }
  1079. }
  1080. for (int i = 0; i < custom_loaders.size(); ++i) {
  1081. remove_resource_format_loader(custom_loaders[i]);
  1082. }
  1083. }
  1084. bool ResourceLoader::is_cleaning_tasks() {
  1085. MutexLock lock(thread_load_mutex);
  1086. return cleaning_tasks;
  1087. }
  1088. void ResourceLoader::initialize() {}
  1089. void ResourceLoader::finalize() {}
  1090. ResourceLoadErrorNotify ResourceLoader::err_notify = nullptr;
  1091. DependencyErrorNotify ResourceLoader::dep_err_notify = nullptr;
  1092. bool ResourceLoader::create_missing_resources_if_class_unavailable = false;
  1093. bool ResourceLoader::abort_on_missing_resource = true;
  1094. bool ResourceLoader::timestamp_on_load = false;
  1095. thread_local int ResourceLoader::load_nesting = 0;
  1096. thread_local WorkerThreadPool::TaskID ResourceLoader::caller_task_id = 0;
  1097. thread_local Vector<String> *ResourceLoader::load_paths_stack = nullptr;
  1098. thread_local HashMap<int, HashMap<String, Ref<Resource>>> ResourceLoader::res_ref_overrides;
  1099. template <>
  1100. thread_local uint32_t SafeBinaryMutex<ResourceLoader::BINARY_MUTEX_TAG>::count = 0;
  1101. SafeBinaryMutex<ResourceLoader::BINARY_MUTEX_TAG> ResourceLoader::thread_load_mutex;
  1102. HashMap<String, ResourceLoader::ThreadLoadTask> ResourceLoader::thread_load_tasks;
  1103. bool ResourceLoader::cleaning_tasks = false;
  1104. HashMap<String, ResourceLoader::LoadToken *> ResourceLoader::user_load_tokens;
  1105. SelfList<Resource>::List ResourceLoader::remapped_list;
  1106. HashMap<String, Vector<String>> ResourceLoader::translation_remaps;
  1107. HashMap<String, String> ResourceLoader::path_remaps;
  1108. ResourceLoaderImport ResourceLoader::import = nullptr;