diff --git a/packages/graphics/src/image.js b/packages/graphics/src/image.js index ce75dfc..ead0272 100644 --- a/packages/graphics/src/image.js +++ b/packages/graphics/src/image.js @@ -26,17 +26,16 @@ export default class Image extends Resource { }; } - destroy() { - if (!this.texture.isFake) { - this.texture.destroy(); - } - } + // @todo Implement refcount with PIXI cache and we can do this. + // destroy() { + // if (!this.texture.isFake) { + // this.texture.destroy(); + // } + // } - static from(O) { - // eslint-disable-next-line global-require - const {Texture} = require('@pixi/core'); + static async from(O) { const image = new Image(); - image.texture = Texture.from(O); + image.texture = await this.pixiTextureFromElement(O); return image; } @@ -55,10 +54,8 @@ export default class Image extends Resource { }; return; } - // eslint-disable-next-line global-require - const {Texture} = require('@pixi/core'); if (cache.has(uri)) { - this.texture = Texture.from((await cache.get(uri)).cloneNode()); + this.texture = await this.constructor.pixiTextureFromElement(await cache.get(uri)); return; } const image = window.document.createElement('img'); @@ -71,7 +68,7 @@ export default class Image extends Resource { }); }); cache.set(uri, promise); - this.texture = Texture.from((await promise).cloneNode()); + this.texture = await this.constructor.pixiTextureFromElement(await promise); } else { this.texture = { @@ -82,6 +79,28 @@ export default class Image extends Resource { } } + // This is a little wonky, but basically we're reaching into PIXI's guts a bit. + // @todo this will probably break image loading at some point. + static pixiTextureFromElement(element) { + // eslint-disable-next-line global-require + const {Texture} = require('@pixi/core'); + const clone = element.cloneNode(); + // eslint-disable-next-line no-param-reassign, no-underscore-dangle + clone._pixiId = element._pixiId; + const texture = Texture.from(clone); + // Cache hit. + if (texture.valid) { + return texture; + } + return new Promise((resolve) => { + texture.once('update', () => { + // eslint-disable-next-line no-param-reassign, no-underscore-dangle + element._pixiId = clone._pixiId; + resolve(texture); + }); + }); + } + get size() { return [this.width, this.height]; } diff --git a/packages/topdown/src/renderable/tiles.js b/packages/topdown/src/renderable/tiles.js index 7dbb5c4..b0e8655 100644 --- a/packages/topdown/src/renderable/tiles.js +++ b/packages/topdown/src/renderable/tiles.js @@ -91,8 +91,8 @@ export default class TilesView extends Container { for (let i = 0; i < chunks.length; ++i) { const chunk = chunks[i]; const rendered = this.rendered[this.constructor.hashChunk(chunk)]; - this.wrapper.removeChild(rendered); if (rendered) { + this.wrapper.removeChild(rendered); rendered.destroy(true); } this.renderChunk(chunk); @@ -103,7 +103,7 @@ export default class TilesView extends Container { this.invalidateChunks(this.chunksForUnitExtent([x, y, w, h])); } - renderChunk([cux, cuy]) { + async renderChunk([cux, cuy]) { if (cux < 0 || cuy < 0) { return; } @@ -120,7 +120,7 @@ export default class TilesView extends Container { const [tw, th] = this.tiles.tileSize; const slice = this.tiles.slice([cx - 1, cy - 1, sw + 2, sh + 2]); const container = new Container(); - const mask = this.renderMask(slice, [sw + 2, sh + 2]); + const mask = await this.renderMask(slice, [sw + 2, sh + 2]); if (mask) { container.mask = mask; mask.anchor = [0, 0]; @@ -175,7 +175,7 @@ export default class TilesView extends Container { } } - renderMask(slice, size) { + async renderMask(slice, size) { const hulls = this.tiles.constructor.indexHulls( new Set([342, 456, 103, 104, 407, 408, 423, 424]), slice, @@ -232,7 +232,7 @@ export default class TilesView extends Container { ctx.closePath(); ctx.fill(); } - return new Sprite(Image.from(canvas)); + return new Sprite(await Image.from(canvas)); } }