diff --git a/src/Drawable.js b/src/Drawable.js index 1d90a2977..dc17ff3ae 100644 --- a/src/Drawable.js +++ b/src/Drawable.js @@ -184,55 +184,98 @@ class Drawable { } /** - * Update the position, direction, scale, or effect properties of this Drawable. - * @param {object.} properties The new property values to set. + * Update the position if it is different. Marks the transform as dirty. + * @param {Array.} position A new position. */ - updateProperties (properties) { - let dirty = false; - if ('position' in properties && ( - this._position[0] !== properties.position[0] || - this._position[1] !== properties.position[1])) { - this._position[0] = Math.round(properties.position[0]); - this._position[1] = Math.round(properties.position[1]); - dirty = true; - } - if ('direction' in properties && this._direction !== properties.direction) { - this._direction = properties.direction; + updatePosition (position) { + if (this._position[0] !== position[0] || + this._position[1] !== position[1]) { + this._position[0] = Math.round(position[0]); + this._position[1] = Math.round(position[1]); + this.setTransformDirty(); + } + } + + /** + * Update the direction if it is different. Marks the transform as dirty. + * @param {number} direction A new direction. + */ + updateDirection (direction) { + if (this._direction !== direction) { + this._direction = direction; this._rotationTransformDirty = true; - dirty = true; + this.setTransformDirty(); } - if ('scale' in properties && ( - this._scale[0] !== properties.scale[0] || - this._scale[1] !== properties.scale[1])) { - this._scale[0] = properties.scale[0]; - this._scale[1] = properties.scale[1]; + } + + /** + * Update the scale if it is different. Marks the transform as dirty. + * @param {Array.} scale A new scale. + */ + updateScale (scale) { + if (this._scale[0] !== scale[0] || + this._scale[1] !== scale[1]) { + this._scale[0] = scale[0]; + this._scale[1] = scale[1]; this._rotationCenterDirty = true; this._skinScaleDirty = true; - dirty = true; + this.setTransformDirty(); } - if ('visible' in properties) { - this._visible = properties.visible; + } + + /** + * Update visibility if it is different. Marks the convex hull as dirty. + * @param {boolean} visible A new visibility state. + */ + updateVisible (visible) { + if (this._visible !== visible) { + this._visible = visible; this.setConvexHullDirty(); } - if (dirty) { - this.setTransformDirty(); + } + + /** + * Update an effect. Marks the convex hull as dirty if the effect changes shape. + * @param {string} effectName The name of the effect. + * @param {number} rawValue A new effect value. + */ + updateEffect (effectName, rawValue) { + const effectInfo = ShaderManager.EFFECT_INFO[effectName]; + if (rawValue) { + this._effectBits |= effectInfo.mask; + } else { + this._effectBits &= ~effectInfo.mask; + } + const converter = effectInfo.converter; + this._uniforms[effectInfo.uniformName] = converter(rawValue); + if (effectInfo.shapeChanges) { + this.setConvexHullDirty(); + } + } + + /** + * Update the position, direction, scale, or effect properties of this Drawable. + * @deprecated Use specific update* methods instead. + * @param {object.} properties The new property values to set. + */ + updateProperties (properties) { + if ('position' in properties) { + this.updatePosition(properties.position); + } + if ('direction' in properties) { + this.updateDirection(properties.direction); + } + if ('scale' in properties) { + this.updateScale(properties.scale); + } + if ('visible' in properties) { + this.updateVisible(properties.visible); } const numEffects = ShaderManager.EFFECTS.length; for (let index = 0; index < numEffects; ++index) { const effectName = ShaderManager.EFFECTS[index]; if (effectName in properties) { - const rawValue = properties[effectName]; - const effectInfo = ShaderManager.EFFECT_INFO[effectName]; - if (rawValue) { - this._effectBits |= effectInfo.mask; - } else { - this._effectBits &= ~effectInfo.mask; - } - const converter = effectInfo.converter; - this._uniforms[effectInfo.uniformName] = converter(rawValue); - if (effectInfo.shapeChanges) { - this.setConvexHullDirty(); - } + this.updateEffect(effectName, properties[effectName]); } } } diff --git a/src/RenderWebGL.js b/src/RenderWebGL.js index 478245512..a8350e266 100644 --- a/src/RenderWebGL.js +++ b/src/RenderWebGL.js @@ -1313,9 +1313,122 @@ class RenderWebGL extends EventEmitter { }, null); } + /** + * Update a drawable's skin. + * @param {number} drawableID The drawable's id. + * @param {number} skinId The skin to update to. + */ + updateDrawableSkinId (drawableID, skinId) { + const drawable = this._allDrawables[drawableID]; + // TODO: https://github.com/LLK/scratch-vm/issues/2288 + if (!drawable) return; + drawable.skin = this._allSkins[skinId]; + } + + /** + * Update a drawable's skin rotation center. + * @param {number} drawableID The drawable's id. + * @param {Array.} rotationCenter The rotation center for the skin. + */ + updateDrawableRotationCenter (drawableID, rotationCenter) { + const drawable = this._allDrawables[drawableID]; + // TODO: https://github.com/LLK/scratch-vm/issues/2288 + if (!drawable) return; + drawable.skin.setRotationCenter(rotationCenter[0], rotationCenter[1]); + } + + /** + * Update a drawable's skin and rotation center together. + * @param {number} drawableID The drawable's id. + * @param {number} skinId The skin to update to. + * @param {Array.} rotationCenter The rotation center for the skin. + */ + updateDrawableSkinIdRotationCenter (drawableID, skinId, rotationCenter) { + const drawable = this._allDrawables[drawableID]; + // TODO: https://github.com/LLK/scratch-vm/issues/2288 + if (!drawable) return; + drawable.skin = this._allSkins[skinId]; + drawable.skin.setRotationCenter(rotationCenter[0], rotationCenter[1]); + } + + /** + * Update a drawable's position. + * @param {number} drawableID The drawable's id. + * @param {Array.} position The new position. + */ + updateDrawablePosition (drawableID, position) { + const drawable = this._allDrawables[drawableID]; + // TODO: https://github.com/LLK/scratch-vm/issues/2288 + if (!drawable) return; + drawable.updatePosition(position); + } + + /** + * Update a drawable's direction. + * @param {number} drawableID The drawable's id. + * @param {number} direction A new direction. + */ + updateDrawableDirection (drawableID, direction) { + const drawable = this._allDrawables[drawableID]; + // TODO: https://github.com/LLK/scratch-vm/issues/2288 + if (!drawable) return; + drawable.updateDirection(direction); + } + + /** + * Update a drawable's scale. + * @param {number} drawableID The drawable's id. + * @param {Array.} scale A new scale. + */ + updateDrawableScale (drawableID, scale) { + const drawable = this._allDrawables[drawableID]; + // TODO: https://github.com/LLK/scratch-vm/issues/2288 + if (!drawable) return; + drawable.updateScale(scale); + } + + /** + * Update a drawable's direction and scale together. + * @param {number} drawableID The drawable's id. + * @param {number} direction A new direction. + * @param {Array.} scale A new scale. + */ + updateDrawableDirectionScale (drawableID, direction, scale) { + const drawable = this._allDrawables[drawableID]; + // TODO: https://github.com/LLK/scratch-vm/issues/2288 + if (!drawable) return; + drawable.updateDirection(direction); + drawable.updateScale(scale); + } + + /** + * Update a drawable's visibility. + * @param {number} drawableID The drawable's id. + * @param {boolean} visible Will the drawable be visible? + */ + updateDrawableVisible (drawableID, visible) { + const drawable = this._allDrawables[drawableID]; + // TODO: https://github.com/LLK/scratch-vm/issues/2288 + if (!drawable) return; + drawable.updateVisible(visible); + } + + /** + * Update a drawable's visual effect. + * @param {number} drawableID The drawable's id. + * @param {string} effectName The effect to change. + * @param {number} value A new effect value. + */ + updateDrawableEffect (drawableID, effectName, value) { + const drawable = this._allDrawables[drawableID]; + // TODO: https://github.com/LLK/scratch-vm/issues/2288 + if (!drawable) return; + drawable.updateEffect(effectName, value); + } /** * Update the position, direction, scale, or effect properties of this Drawable. + * @deprecated Use specific updateDrawable* methods instead. * @param {int} drawableID The ID of the Drawable to update. * @param {object.} properties The new property values to set. */ @@ -1323,17 +1436,16 @@ class RenderWebGL extends EventEmitter { const drawable = this._allDrawables[drawableID]; if (!drawable) { /** - * @todo fix whatever's wrong in the VM which causes this, then add a warning or throw here. + * @todo(https://github.com/LLK/scratch-vm/issues/2288) fix whatever's wrong in the VM which causes this, then add a warning or throw here. * Right now this happens so much on some projects that a warning or exception here can hang the browser. */ return; } if ('skinId' in properties) { - drawable.skin = this._allSkins[properties.skinId]; + this.updateDrawableSkinId(drawableID, properties.skinId); } if ('rotationCenter' in properties) { - const newRotationCenter = properties.rotationCenter; - drawable.skin.setRotationCenter(newRotationCenter[0], newRotationCenter[1]); + this.updateDrawableRotationCenter(drawableID, properties.rotationCenter); } drawable.updateProperties(properties); } @@ -1350,7 +1462,7 @@ class RenderWebGL extends EventEmitter { const drawable = this._allDrawables[drawableID]; if (!drawable) { - // TODO: fix whatever's wrong in the VM which causes this, then add a warning or throw here. + // @todo(https://github.com/LLK/scratch-vm/issues/2288) fix whatever's wrong in the VM which causes this, then add a warning or throw here. // Right now this happens so much on some projects that a warning or exception here can hang the browser. return [x, y]; } @@ -1627,14 +1739,14 @@ class RenderWebGL extends EventEmitter { } twgl.setUniforms(currentShader, uniforms); - + /* adjust blend function for this skin */ if (drawable.skin.hasPremultipliedAlpha){ gl.blendFuncSeparate(gl.ONE, gl.ONE_MINUS_SRC_ALPHA, gl.ONE, gl.ONE_MINUS_SRC_ALPHA); } else { gl.blendFuncSeparate(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA, gl.ONE, gl.ONE_MINUS_SRC_ALPHA); } - + twgl.drawBufferInfo(gl, this._bufferInfo, gl.TRIANGLES); }