mirror of
https://github.com/Heretek-AI/GDevelop.git
synced 2026-08-24 22:31:30 -04:00
Deduplicate concurrent reloadResource calls for the same resource
When multiple SceneEditors are open, each one registers a callback for resource changes. All callbacks fire concurrently (forEach without await), so reloadResource is called multiple times for the same resource in parallel. The second call would unload the texture the first call just loaded, leaving the first SceneEditor with a destroyed texture and causing null-baseTexture crashes (width/containsPoint errors). Track in-flight reload promises per resource name. If a reload is already in progress, subsequent callers await the same promise instead of starting a new unload/load cycle. https://claude.ai/code/session_012hFLUQDBXEuzxCEDUGVvew
This commit is contained in:
@@ -45,6 +45,12 @@ type ResourcePromise<T> = { [resourceName: string]: Promise<T> };
|
||||
let loadedBitmapFonts = {};
|
||||
let loadedFontFamilies = {};
|
||||
let loadedTextures = {};
|
||||
// Tracks in-flight reload promises so that concurrent reloadResource calls
|
||||
// for the same resource name are deduplicated. Without this, when multiple
|
||||
// SceneEditors are open, each one fires its own reloadResource — the second
|
||||
// call would unload the texture that the first call just loaded, causing
|
||||
// crashes (null baseTexture / width).
|
||||
let pendingReloads: { [resourceName: string]: Promise<void> } = {};
|
||||
const invalidTexture = PIXI.Texture.from('res/invalid_texture.png');
|
||||
const loadingTexture = PIXI.Texture.from(
|
||||
'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAgAAAAIAQMAAAD+wSzIAAAAA1BMVEXX19f5cgrAAAAAAXRSTlMz/za5cAAAAApJREFUCNdjQAMAABAAAbSqgB8AAAAASUVORK5CYII='
|
||||
@@ -284,6 +290,24 @@ export default class PixiResourcesLoader {
|
||||
}
|
||||
|
||||
static async reloadResource(project: gdProject, resourceName: string) {
|
||||
// Deduplicate concurrent calls for the same resource. When multiple
|
||||
// SceneEditors are open, each one calls reloadResource for the same
|
||||
// resource. Without deduplication, the second call would unload the
|
||||
// texture that the first call just loaded, causing null-baseTexture crashes.
|
||||
if (pendingReloads[resourceName]) {
|
||||
return pendingReloads[resourceName];
|
||||
}
|
||||
|
||||
const promise = this._doReloadResource(project, resourceName);
|
||||
pendingReloads[resourceName] = promise;
|
||||
try {
|
||||
await promise;
|
||||
} finally {
|
||||
delete pendingReloads[resourceName];
|
||||
}
|
||||
}
|
||||
|
||||
static async _doReloadResource(project: gdProject, resourceName: string) {
|
||||
// $FlowFixMe[invalid-computed-prop]
|
||||
const loadedTexture = loadedTextures[resourceName];
|
||||
if (loadedTexture === invalidTexture) {
|
||||
|
||||
Reference in New Issue
Block a user