diff --git a/src/Drawable.js b/src/Drawable.js index d6d665813..c55806e50 100644 --- a/src/Drawable.js +++ b/src/Drawable.js @@ -5,6 +5,7 @@ const RenderConstants = require('./RenderConstants'); const ShaderManager = require('./ShaderManager'); const Skin = require('./Skin'); const EffectTransform = require('./EffectTransform'); +const log = require('./util/log'); /** * An internal workspace for calculating texture locations from world vectors @@ -452,6 +453,8 @@ class Drawable { /** * Check if the world position touches the skin. + * The caller is responsible for ensuring this drawable's inverse matrix & its skin's silhouette are up-to-date. + * @see updateCPURenderAttributes * @param {twgl.v3} vec World coordinate vector. * @return {boolean} True if the world position touches the skin. */ @@ -632,6 +635,19 @@ class Drawable { } } + /** + * Update everything necessary to render this drawable on the CPU. + */ + updateCPURenderAttributes () { + this.updateMatrix(); + // CPU rendering always occurs at the "native" size, so no need to scale up this._scale + if (this.skin) { + this.skin.updateSilhouette(this._scale); + } else { + log.warn(`Could not find skin for drawable with id: ${this._id}`); + } + } + /** * Respond to an internal change in the current Skin. * @private @@ -676,6 +692,8 @@ class Drawable { /** * Sample a color from a drawable's texture. + * The caller is responsible for ensuring this drawable's inverse matrix & its skin's silhouette are up-to-date. + * @see updateCPURenderAttributes * @param {twgl.v3} vec The scratch space [x,y] vector * @param {Drawable} drawable The drawable to sample the texture from * @param {Uint8ClampedArray} dst The "color4b" representation of the texture at point. diff --git a/src/RenderWebGL.js b/src/RenderWebGL.js index 5c9580bc1..7103f5ef1 100644 --- a/src/RenderWebGL.js +++ b/src/RenderWebGL.js @@ -985,12 +985,7 @@ class RenderWebGL extends EventEmitter { const bounds = this.clientSpaceToScratchBounds(centerX, centerY, touchWidth, touchHeight); const worldPos = twgl.v3.create(); - drawable.updateMatrix(); - if (drawable.skin) { - drawable.skin.updateSilhouette(this._getDrawableScreenSpaceScale(drawable)); - } else { - log.warn(`Could not find skin for drawable with id: ${drawableID}`); - } + drawable.updateCPURenderAttributes(); for (worldPos[1] = bounds.bottom; worldPos[1] <= bounds.top; worldPos[1]++) { for (worldPos[0] = bounds.left; worldPos[0] <= bounds.right; worldPos[0]++) { @@ -1021,12 +1016,7 @@ class RenderWebGL extends EventEmitter { const drawable = this._allDrawables[id]; // default pick list ignores visible and ghosted sprites. if (drawable.getVisible() && drawable.getUniforms().u_ghost !== 0) { - drawable.updateMatrix(); - if (drawable.skin) { - drawable.skin.updateSilhouette(this._getDrawableScreenSpaceScale(drawable)); - } else { - log.warn(`Could not find skin for drawable with id: ${id}`); - } + drawable.updateCPURenderAttributes(); return true; } return false; @@ -1258,8 +1248,8 @@ class RenderWebGL extends EventEmitter { /** @todo remove this once URL-based skin setting is removed. */ if (!drawable.skin || !drawable.skin.getTexture([100, 100])) return null; - drawable.updateMatrix(); - drawable.skin.updateSilhouette(this._getDrawableScreenSpaceScale(drawable)); + + drawable.updateCPURenderAttributes(); const bounds = drawable.getFastBounds(); // Limit queries to the stage size. @@ -1296,8 +1286,7 @@ class RenderWebGL extends EventEmitter { const drawable = this._allDrawables[id]; if (drawable.skin && drawable._visible) { // Update the CPU position data - drawable.updateMatrix(); - drawable.skin.updateSilhouette(this._getDrawableScreenSpaceScale(drawable)); + drawable.updateCPURenderAttributes(); const candidateBounds = drawable.getFastBounds(); if (bounds.intersects(candidateBounds)) { result.push({ @@ -1775,8 +1764,7 @@ class RenderWebGL extends EventEmitter { _getConvexHullPointsForDrawable (drawableID) { const drawable = this._allDrawables[drawableID]; - drawable.updateMatrix(); - drawable.skin.updateSilhouette(this._getDrawableScreenSpaceScale(drawable)); + drawable.updateCPURenderAttributes(); const [width, height] = drawable.skin.size; // No points in the hull if invisible or size is 0. diff --git a/src/SVGSkin.js b/src/SVGSkin.js index 9699b4592..8da356f4b 100644 --- a/src/SVGSkin.js +++ b/src/SVGSkin.js @@ -105,7 +105,7 @@ class SVGSkin extends Skin { return mip; } - updateSilhouette (scale = 1) { + updateSilhouette (scale = [100, 100]) { // Ensure a silhouette exists. this.getTexture(scale); } diff --git a/src/Skin.js b/src/Skin.js index 06cedd857..3a740a8f0 100644 --- a/src/Skin.js +++ b/src/Skin.js @@ -222,6 +222,9 @@ class Skin extends EventEmitter { /** * Does this point touch an opaque or translucent point on this skin? * Nearest Neighbor version + * The caller is responsible for ensuring this skin's silhouette is up-to-date. + * @see updateSilhouette + * @see Drawable.updateCPURenderAttributes * @param {twgl.v3} vec A texture coordinate. * @return {boolean} Did it touch? */ @@ -232,6 +235,9 @@ class Skin extends EventEmitter { /** * Does this point touch an opaque or translucent point on this skin? * Linear Interpolation version + * The caller is responsible for ensuring this skin's silhouette is up-to-date. + * @see updateSilhouette + * @see Drawable.updateCPURenderAttributes * @param {twgl.v3} vec A texture coordinate. * @return {boolean} Did it touch? */ diff --git a/test/integration/cpu-render.html b/test/integration/cpu-render.html index 26a79c3f4..7eec0a612 100644 --- a/test/integration/cpu-render.html +++ b/test/integration/cpu-render.html @@ -42,8 +42,7 @@ if (!(drawable._visible && drawable.skin)) { return; } - drawable.updateMatrix(); - drawable.skin.updateSilhouette(); + drawable.updateCPURenderAttributes(); return { id, drawable }; }).reverse().filter(Boolean); const color = new Uint8ClampedArray(3);