mirror of
https://github.com/4ian/GDevelop.git
synced 2026-10-12 02:01:17 +00:00
Fix silent exceptions when resource loading finished after an instance was reset/removed (#7054)
Only show in developer changelog
This commit is contained in:
@@ -2203,6 +2203,8 @@ module.exports = {
|
||||
if (!texture.baseTexture.valid) {
|
||||
// Post pone texture update if texture is not loaded.
|
||||
texture.once('update', () => {
|
||||
if (this._wasDestroyed) return;
|
||||
|
||||
this.updateTexture();
|
||||
this.updatePIXISprite();
|
||||
});
|
||||
@@ -2375,6 +2377,7 @@ module.exports = {
|
||||
getFaceMaterial(this._project, materialIndexToFaceIndex[4]),
|
||||
getFaceMaterial(this._project, materialIndexToFaceIndex[5]),
|
||||
]);
|
||||
if (this._wasDestroyed) return;
|
||||
|
||||
this._threeObject.material[0] = materials[0];
|
||||
this._threeObject.material[1] = materials[1];
|
||||
@@ -2823,6 +2826,7 @@ module.exports = {
|
||||
this._pixiResourcesLoader
|
||||
.get3DModel(project, modelResourceName)
|
||||
.then((model3d) => {
|
||||
if (this._wasDestroyed) return;
|
||||
const clonedModel3D = THREE_ADDONS.SkeletonUtils.clone(
|
||||
model3d.scene
|
||||
);
|
||||
@@ -3338,6 +3342,7 @@ module.exports = {
|
||||
this._pixiResourcesLoader
|
||||
.get3DModel(this._project, modelResourceName)
|
||||
.then((model3d) => {
|
||||
if (this._wasDestroyed) return;
|
||||
this._clonedModel3D = THREE_ADDONS.SkeletonUtils.clone(
|
||||
model3d.scene
|
||||
);
|
||||
|
||||
@@ -697,6 +697,8 @@ module.exports = {
|
||||
this._currentBitmapFontResourceName,
|
||||
this._currentTextureAtlasResourceName
|
||||
).then((bitmapFont) => {
|
||||
if (this._wasDestroyed) return;
|
||||
|
||||
this._pixiObject.fontName = bitmapFont.font;
|
||||
this._pixiObject.fontSize = bitmapFont.size;
|
||||
this._pixiObject.dirty = true;
|
||||
|
||||
Vendored
+8
-2
@@ -14,9 +14,12 @@ class RenderedInstance {
|
||||
_associatedObjectConfiguration: gd.ObjectConfiguration;
|
||||
_pixiContainer: PIXI.Container;
|
||||
_pixiResourcesLoader: Class<PixiResourcesLoader>;
|
||||
_pixiObject: PIXI.DisplayObject;
|
||||
_pixiObject: PIXI.DisplayObject | null;
|
||||
wasUsed: boolean;
|
||||
|
||||
/** Set to true when onRemovedFromScene is called. Allows to cancel promises/asynchronous operations (notably: waiting for a resource load). */
|
||||
_wasDestroyed: boolean;
|
||||
|
||||
constructor(
|
||||
project: gdProject,
|
||||
instance: gdInitialInstance,
|
||||
@@ -89,10 +92,13 @@ class Rendered3DInstance {
|
||||
_pixiContainer: PIXI.Container;
|
||||
_threeGroup: THREE.Group;
|
||||
_pixiResourcesLoader: Class<PixiResourcesLoader>;
|
||||
_pixiObject: PIXI.DisplayObject;
|
||||
_pixiObject: PIXI.DisplayObject | null;
|
||||
_threeObject: THREE.Object3D | null;
|
||||
wasUsed: boolean;
|
||||
|
||||
/** Set to true when onRemovedFromScene is called. Allows to cancel promises/asynchronous operations (notably: waiting for a resource load). */
|
||||
_wasDestroyed: boolean;
|
||||
|
||||
constructor(
|
||||
project: gdProject,
|
||||
instance: gdInitialInstance,
|
||||
|
||||
@@ -323,6 +323,7 @@ module.exports = {
|
||||
this._pixiResourcesLoader
|
||||
.getSpineData(this._project, this._spineResourceName)
|
||||
.then((spineDataOrLoadingError) => {
|
||||
if (this._wasDestroyed) return;
|
||||
if (this._spine) this._pixiObject.removeChild(this._spine);
|
||||
|
||||
if (!spineDataOrLoadingError.skeleton) {
|
||||
|
||||
@@ -711,6 +711,7 @@ module.exports = {
|
||||
this._pixiResourcesLoader
|
||||
.loadFontFamily(this._project, fontResourceName)
|
||||
.then((fontFamily) => {
|
||||
if (this._wasDestroyed) return;
|
||||
this._pixiText.style.fontFamily = fontFamily;
|
||||
this._pixiText.dirty = true;
|
||||
})
|
||||
|
||||
@@ -1760,6 +1760,7 @@ module.exports = {
|
||||
levelIndex,
|
||||
pako,
|
||||
(tileMap) => {
|
||||
if (this._wasDestroyed) return;
|
||||
if (!tileMap) {
|
||||
this._onLoadingError();
|
||||
// _loadTileMapWithCallback already log errors
|
||||
@@ -1781,6 +1782,7 @@ module.exports = {
|
||||
tilesetJsonFile,
|
||||
levelIndex,
|
||||
(textureCache) => {
|
||||
if (this._wasDestroyed) return;
|
||||
if (!textureCache) {
|
||||
this._onLoadingError();
|
||||
// getOrLoadTextureCache already log warns and errors.
|
||||
@@ -1809,6 +1811,7 @@ module.exports = {
|
||||
} else {
|
||||
// Wait for the atlas image to load.
|
||||
atlasTexture.once('update', () => {
|
||||
if (this._wasDestroyed) return;
|
||||
loadTileMap();
|
||||
});
|
||||
}
|
||||
@@ -1855,6 +1858,7 @@ module.exports = {
|
||||
tilesetJsonFile,
|
||||
levelIndex,
|
||||
(textureCache) => {
|
||||
if (this._wasDestroyed) return;
|
||||
if (!textureCache) {
|
||||
this._onLoadingError();
|
||||
// getOrLoadTextureCache already log warns and errors.
|
||||
@@ -2208,6 +2212,7 @@ module.exports = {
|
||||
columnCount,
|
||||
rowCount,
|
||||
(tileMap) => {
|
||||
if (this._wasDestroyed) return;
|
||||
if (!tileMap) {
|
||||
this._onLoadingError();
|
||||
console.error('Could not parse tilemap.');
|
||||
@@ -2230,6 +2235,7 @@ module.exports = {
|
||||
/** @type {TileMapHelper.TileTextureCache | null} */
|
||||
textureCache
|
||||
) => {
|
||||
if (this._wasDestroyed) return;
|
||||
this._onLoadingSuccess();
|
||||
if (!this._editableTileMap) return;
|
||||
|
||||
@@ -2257,6 +2263,7 @@ module.exports = {
|
||||
} else {
|
||||
// Wait for the atlas image to load.
|
||||
atlasTexture.once('update', () => {
|
||||
if (this._wasDestroyed) return;
|
||||
loadTileMap();
|
||||
});
|
||||
}
|
||||
@@ -2293,6 +2300,7 @@ module.exports = {
|
||||
/** @type {TileMapHelper.TileTextureCache | null} */
|
||||
textureCache
|
||||
) => {
|
||||
if (this._wasDestroyed) return;
|
||||
this._onLoadingSuccess();
|
||||
if (!this._editableTileMap) return;
|
||||
|
||||
@@ -2536,6 +2544,7 @@ module.exports = {
|
||||
0, // levelIndex
|
||||
pako,
|
||||
(tileMap) => {
|
||||
if (this._wasDestroyed) return;
|
||||
if (!tileMap) {
|
||||
this._onLoadingError();
|
||||
// _loadTiledMapWithCallback already log errors
|
||||
|
||||
@@ -609,6 +609,7 @@ module.exports = {
|
||||
|
||||
that._pixiObject.texture.on('error', function () {
|
||||
that._pixiObject.texture.off('error', this);
|
||||
if (this._wasDestroyed) return;
|
||||
|
||||
that._pixiObject.texture = that._pixiResourcesLoader.getInvalidPIXITexture();
|
||||
});
|
||||
|
||||
@@ -18,6 +18,7 @@ export default class Rendered3DInstance {
|
||||
_pixiObject: PIXI.DisplayObject;
|
||||
_threeObject: THREE.Object3D | null;
|
||||
wasUsed: boolean;
|
||||
_wasDestroyed: boolean;
|
||||
|
||||
constructor(
|
||||
project: gdProject,
|
||||
@@ -36,6 +37,7 @@ export default class Rendered3DInstance {
|
||||
this._project = project;
|
||||
this._pixiResourcesLoader = pixiResourcesLoader;
|
||||
this.wasUsed = true; //Used by InstancesRenderer to track rendered instance that are not used anymore.
|
||||
this._wasDestroyed = false;
|
||||
}
|
||||
|
||||
isRenderedIn3D(): boolean {
|
||||
@@ -89,6 +91,7 @@ export default class Rendered3DInstance {
|
||||
* the default implementation of the method does.
|
||||
*/
|
||||
onRemovedFromScene() {
|
||||
this._wasDestroyed = true;
|
||||
if (this._pixiObject !== null)
|
||||
this._pixiContainer.removeChild(this._pixiObject);
|
||||
if (this._threeObject !== null) this._threeGroup.remove(this._threeObject);
|
||||
|
||||
@@ -179,6 +179,12 @@ export default class RenderedCustomObjectInstance extends Rendered3DInstance
|
||||
for (const [i, renderedInstance] of this.renderedInstances) {
|
||||
if (!renderedInstance.wasUsed) {
|
||||
renderedInstance.onRemovedFromScene();
|
||||
if (!renderedInstance._wasDestroyed)
|
||||
console.error(
|
||||
'Rendered instance was not marked as destroyed by onRemovedFromScene - verify the implementation.',
|
||||
renderedInstance
|
||||
);
|
||||
|
||||
this.renderedInstances.delete(i);
|
||||
this.layoutedInstances.delete(i);
|
||||
}
|
||||
@@ -196,6 +202,11 @@ export default class RenderedCustomObjectInstance extends Rendered3DInstance
|
||||
// Destroy all instances
|
||||
for (const renderedInstance of this.renderedInstances.values()) {
|
||||
renderedInstance.onRemovedFromScene();
|
||||
if (!renderedInstance._wasDestroyed)
|
||||
console.error(
|
||||
'Rendered instance (of a custom object) was not marked as destroyed by onRemovedFromScene - verify the implementation.',
|
||||
renderedInstance
|
||||
);
|
||||
}
|
||||
this.renderedInstances.clear();
|
||||
this.layoutedInstances.clear();
|
||||
|
||||
@@ -14,6 +14,7 @@ export default class RenderedInstance {
|
||||
_pixiResourcesLoader: Class<PixiResourcesLoader>;
|
||||
_pixiObject: PIXI.DisplayObject;
|
||||
wasUsed: boolean;
|
||||
_wasDestroyed: boolean;
|
||||
|
||||
constructor(
|
||||
project: gdProject,
|
||||
@@ -29,6 +30,7 @@ export default class RenderedInstance {
|
||||
this._project = project;
|
||||
this._pixiResourcesLoader = pixiResourcesLoader;
|
||||
this.wasUsed = true; //Used by InstancesRenderer to track rendered instance that are not used anymore.
|
||||
this._wasDestroyed = false;
|
||||
}
|
||||
|
||||
isRenderedIn3D(): boolean {
|
||||
@@ -63,6 +65,7 @@ export default class RenderedInstance {
|
||||
* the default implementation of the method does.
|
||||
*/
|
||||
onRemovedFromScene(): void {
|
||||
this._wasDestroyed = true;
|
||||
if (this._pixiObject !== null)
|
||||
this._pixiContainer.removeChild(this._pixiObject);
|
||||
}
|
||||
|
||||
@@ -265,7 +265,10 @@ export default class RenderedPanelSpriteInstance extends RenderedInstance {
|
||||
);
|
||||
if (!texture.baseTexture.valid) {
|
||||
// Post pone texture update if texture is not loaded.
|
||||
texture.once('update', () => this.updateTextures());
|
||||
texture.once('update', () => {
|
||||
if (this._wasDestroyed) return;
|
||||
this.updateTextures();
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -199,7 +199,10 @@ export default class RenderedSprite3DInstance extends Rendered3DInstance {
|
||||
|
||||
if (!texture.baseTexture.valid) {
|
||||
// Post pone texture update if texture is not loaded.
|
||||
texture.once('update', () => this.updateTextureAndSprite());
|
||||
texture.once('update', () => {
|
||||
if (this._wasDestroyed) return;
|
||||
this.updateTextureAndSprite();
|
||||
});
|
||||
return;
|
||||
}
|
||||
this._textureWidth = texture.width;
|
||||
@@ -212,6 +215,7 @@ export default class RenderedSprite3DInstance extends Rendered3DInstance {
|
||||
useTransparentTexture: true,
|
||||
}
|
||||
);
|
||||
if (this._wasDestroyed) return;
|
||||
if (this._threeObject) {
|
||||
this._threeObject.material = material;
|
||||
}
|
||||
|
||||
@@ -187,7 +187,10 @@ export default class RenderedSpriteInstance extends RenderedInstance {
|
||||
|
||||
if (!texture.baseTexture.valid) {
|
||||
// Post pone texture update if texture is not loaded.
|
||||
texture.once('update', () => this.updatePIXITextureAndSprite());
|
||||
texture.once('update', () => {
|
||||
if (this._wasDestroyed) return;
|
||||
this.updatePIXITextureAndSprite();
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -140,6 +140,8 @@ export default class RenderedTextInstance extends RenderedInstance {
|
||||
textObjectConfiguration.getFontName()
|
||||
)
|
||||
.then(fontFamily => {
|
||||
if (this._wasDestroyed) return;
|
||||
|
||||
// Once the font is loaded, we can use the given fontFamily.
|
||||
this._fontFamily = fontFamily;
|
||||
this._styleFontDirty = true;
|
||||
|
||||
Reference in New Issue
Block a user