diff --git a/src/blocks/scratch3_pen.js b/src/blocks/scratch3_pen.js index a55074040..b2f7d4b6d 100644 --- a/src/blocks/scratch3_pen.js +++ b/src/blocks/scratch3_pen.js @@ -55,6 +55,7 @@ class Scratch3PenBlocks { penDown: false, hue: 120, shade: 50, + transparency: 0, penAttributes: { color4f: [0, 0, 1, 1], diameter: 1 @@ -168,7 +169,8 @@ class Scratch3PenBlocks { } /** - * Update the cached RGB color from the hue & shade values in the provided PenState object. + * Update the cached color from the hue, shade and transparency values in the provided + * PenState object. * @param {PenState} penState - the pen state to update. * @private */ @@ -183,11 +185,11 @@ class Scratch3PenBlocks { penState.penAttributes.color4f[0] = rgb.r / 255.0; penState.penAttributes.color4f[1] = rgb.g / 255.0; penState.penAttributes.color4f[2] = rgb.b / 255.0; - penState.penAttributes.color4f[3] = 1; + penState.penAttributes.color4f[3] = this._transparencyToAlpha(penState.transparency); } /** - * Wrap a pen hue or shade values to the range [0,200). + * Wrap a pen hue or shade values to the range (0,200). * @param {number} value - the pen hue or shade value to the proper range. * @returns {number} the wrapped value. * @private @@ -198,6 +200,40 @@ class Scratch3PenBlocks { return value; } + /** + * Clamp a pen transparency value to the range (0,100). + * @param {number} value - the pen transparency value to be clamped. + * @returns {number} the clamped value. + * @private + */ + _clampTransparency (value) { + return MathUtil.clamp(value, 0, 100); + } + + /** + * Convert an alpha value to a pen transparency value. + * Alpha ranges from 0 to 1, where 0 is transparent and 1 is opaque. + * Transparency ranges from 0 to 100, where 0 is opaque and 100 is transparent. + * @param {number} alpha - the input alpha value. + * @returns {number} the transparency value. + * @private + */ + _alphaToTransparency (alpha) { + return (1.0 - alpha) * 100.0; + } + + /** + * Convert a pen transparency value to an alpha value. + * Alpha ranges from 0 to 1, where 0 is transparent and 1 is opaque. + * Transparency ranges from 0 to 100, where 0 is opaque and 100 is transparent. + * @param {number} transparency - the input transparency value. + * @returns {number} the alpha value. + * @private + */ + _transparencyToAlpha (transparency) { + return 1.0 - (transparency / 100.0); + } + /** * Retrieve the block primitives implemented by this package. * @return {object.} Mapping of opcode to Function. @@ -214,7 +250,9 @@ class Scratch3PenBlocks { pen_changepenshadeby: this.changePenShadeBy, pen_setpenshadeto: this.setPenShadeToNumber, pen_changepensizeby: this.changePenSizeBy, - pen_setpensizeto: this.setPenSizeTo + pen_setpensizeto: this.setPenSizeTo, + pen_changepentransparencyby: this.changePenTransparencyBy, + pen_setpentransparencyto: this.setPenTransparencyTo }; } @@ -300,6 +338,7 @@ class Scratch3PenBlocks { } else { penState.penAttributes.color4f[3] = 1; } + penState.transparency = this._alphaToTransparency(penState.penAttributes.color4f[3]); } /** @@ -371,6 +410,30 @@ class Scratch3PenBlocks { const penAttributes = this._getPenState(util.target).penAttributes; penAttributes.diameter = this._clampPenSize(Cast.toNumber(args.SIZE)); } + + /** + * The pen "change pen transparency by {number}" block changes the RGBA "transparency" of the pen. + * @param {object} args - the block arguments. + * @property {number} TRANSPARENCY - the amount of desired transparency change. + * @param {object} util - utility object provided by the runtime. + */ + changePenTransparencyBy (args, util) { + const penState = this._getPenState(util.target); + penState.transparency = this._clampTransparency(penState.transparency + Cast.toNumber(args.TRANSPARENCY)); + this._updatePenColor(penState); + } + + /** + * The pen "set pen transparency to {number}" block sets the RGBA "transparency" of the pen. + * @param {object} args - the block arguments. + * @property {number} TRANSPARENCY - the amount of desired transparency change. + * @param {object} util - utility object provided by the runtime. + */ + setPenTransparencyTo (args, util) { + const penState = this._getPenState(util.target); + penState.transparency = this._clampTransparency(Cast.toNumber(args.TRANSPARENCY)); + this._updatePenColor(penState); + } } module.exports = Scratch3PenBlocks;