mirror of
https://github.com/scratchfoundation/scratch-vm.git
synced 2024-12-23 14:32:59 -05:00
Merge pull request #745 from paulkaplan/legacy-pen-blocks
Support legacy hue and shade pen blocks
This commit is contained in:
commit
3fb48319c2
4 changed files with 138 additions and 3 deletions
|
@ -71,6 +71,7 @@ class Scratch3PenBlocks {
|
|||
saturation: 100,
|
||||
brightness: 100,
|
||||
transparency: 0,
|
||||
_shade: 50, // Used only for legacy `change shade by` blocks
|
||||
penAttributes: {
|
||||
color4f: [0, 0, 1, 1],
|
||||
diameter: 1
|
||||
|
@ -316,6 +317,55 @@ class Scratch3PenBlocks {
|
|||
defaultValue: 1
|
||||
}
|
||||
}
|
||||
},
|
||||
/* Legacy blocks, should not be shown in flyout */
|
||||
{
|
||||
opcode: 'setPenShadeToNumber',
|
||||
blockType: BlockType.COMMAND,
|
||||
text: 'set pen shade to [SHADE]',
|
||||
arguments: {
|
||||
SHADE: {
|
||||
type: ArgumentType.NUMBER,
|
||||
defaultValue: 1
|
||||
}
|
||||
},
|
||||
hideFromPalette: true
|
||||
},
|
||||
{
|
||||
opcode: 'changePenShadeBy',
|
||||
blockType: BlockType.COMMAND,
|
||||
text: 'change pen shade by [SHADE]',
|
||||
arguments: {
|
||||
SHADE: {
|
||||
type: ArgumentType.NUMBER,
|
||||
defaultValue: 1
|
||||
}
|
||||
},
|
||||
hideFromPalette: true
|
||||
},
|
||||
{
|
||||
opcode: 'setPenHueToNumber',
|
||||
blockType: BlockType.COMMAND,
|
||||
text: 'set pen hue to [HUE]',
|
||||
arguments: {
|
||||
HUE: {
|
||||
type: ArgumentType.NUMBER,
|
||||
defaultValue: 1
|
||||
}
|
||||
},
|
||||
hideFromPalette: true
|
||||
},
|
||||
{
|
||||
opcode: 'changePenHueBy',
|
||||
blockType: BlockType.COMMAND,
|
||||
text: 'change pen hue by [HUE]',
|
||||
arguments: {
|
||||
HUE: {
|
||||
type: ArgumentType.NUMBER,
|
||||
defaultValue: 1
|
||||
}
|
||||
},
|
||||
hideFromPalette: true
|
||||
}
|
||||
],
|
||||
menus: {
|
||||
|
@ -402,6 +452,10 @@ class Scratch3PenBlocks {
|
|||
penState.saturation = hsv.s * 100;
|
||||
penState.brightness = hsv.v * 100;
|
||||
penState.transparency = 0;
|
||||
|
||||
// Set the legacy "shade" value the same way scratch 2 did.
|
||||
penState._shade = penState.brightness / 2;
|
||||
|
||||
this._updatePenColor(penState);
|
||||
}
|
||||
|
||||
|
@ -498,6 +552,85 @@ class Scratch3PenBlocks {
|
|||
const penAttributes = this._getPenState(util.target).penAttributes;
|
||||
penAttributes.diameter = this._clampPenSize(Cast.toNumber(args.SIZE));
|
||||
}
|
||||
|
||||
/* LEGACY OPCODES */
|
||||
/**
|
||||
* Scratch 2 "hue" param is equivelant to twice the new "color" param.
|
||||
* @param {object} args - the block arguments.
|
||||
* @property {number} HUE - the amount to set the hue to.
|
||||
* @param {object} util - utility object provided by the runtime.
|
||||
*/
|
||||
setPenHueToNumber (args, util) {
|
||||
const penState = this._getPenState(util.target);
|
||||
const hueValue = Cast.toNumber(args.HUE);
|
||||
const colorValue = hueValue / 2;
|
||||
this._setOrChangeColorParam(ColorParam.COLOR, colorValue, penState, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Scratch 2 "hue" param is equivelant to twice the new "color" param.
|
||||
* @param {object} args - the block arguments.
|
||||
* @property {number} HUE - the amount of desired hue change.
|
||||
* @param {object} util - utility object provided by the runtime.
|
||||
*/
|
||||
changePenHueBy (args, util) {
|
||||
const penState = this._getPenState(util.target);
|
||||
const hueChange = Cast.toNumber(args.HUE);
|
||||
const colorChange = hueChange / 2;
|
||||
this._setOrChangeColorParam(ColorParam.COLOR, colorChange, penState, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Use legacy "set shade" code to calculate RGB value for shade,
|
||||
* then convert back to HSV and store those components.
|
||||
* It is important to also track the given shade in penState._shade
|
||||
* because it cannot be accurately backed out of the new HSV later.
|
||||
* @param {object} args - the block arguments.
|
||||
* @property {number} SHADE - the amount to set the shade to.
|
||||
* @param {object} util - utility object provided by the runtime.
|
||||
*/
|
||||
setPenShadeToNumber (args, util) {
|
||||
const penState = this._getPenState(util.target);
|
||||
let newShade = Cast.toNumber(args.SHADE);
|
||||
|
||||
// Wrap clamp the new shade value the way scratch 2 did.
|
||||
newShade = newShade % 200;
|
||||
if (newShade < 0) newShade += 200;
|
||||
|
||||
// Create the new color in RGB using the scratch 2 "shade" model
|
||||
let rgb = Color.hsvToRgb({h: penState.color * 360 / 100, s: 1, v: 1});
|
||||
const shade = (newShade > 100) ? 200 - newShade : newShade;
|
||||
if (shade < 50) {
|
||||
rgb = Color.mixRgb(Color.RGB_BLACK, rgb, (10 + shade) / 60);
|
||||
} else {
|
||||
rgb = Color.mixRgb(rgb, Color.RGB_WHITE, (shade - 50) / 60);
|
||||
}
|
||||
|
||||
// Update the pen state according to new color
|
||||
const hsv = Color.rgbToHsv(rgb);
|
||||
penState.color = 100 * hsv.h / 360;
|
||||
penState.saturation = 100 * hsv.s;
|
||||
penState.brightness = 100 * hsv.v;
|
||||
|
||||
// And store the shade that was used to compute this new color for later use.
|
||||
penState._shade = newShade;
|
||||
|
||||
this._updatePenColor(penState);
|
||||
}
|
||||
|
||||
/**
|
||||
* Because "shade" cannot be backed out of hsv consistently, use the previously
|
||||
* stored penState._shade to make the shade change.
|
||||
* @param {object} args - the block arguments.
|
||||
* @property {number} SHADE - the amount of desired shade change.
|
||||
* @param {object} util - utility object provided by the runtime.
|
||||
*/
|
||||
changePenShadeBy (args, util) {
|
||||
const penState = this._getPenState(util.target);
|
||||
const shadeChange = Cast.toNumber(args.SHADE);
|
||||
this.setPenShadeToNumber({SHADE: penState._shade + shadeChange}, util);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
module.exports = Scratch3PenBlocks;
|
||||
|
|
|
@ -630,8 +630,9 @@ class Runtime extends EventEmitter {
|
|||
const xmlParts = [];
|
||||
for (const categoryInfo of this._blockInfo) {
|
||||
const {name, color1, color2} = categoryInfo;
|
||||
const paletteBlocks = categoryInfo.blocks.filter(block => !block.info.hideFromPalette);
|
||||
xmlParts.push(`<category name="${name}" colour="${color1}" secondaryColour="${color2}">`);
|
||||
xmlParts.push.apply(xmlParts, categoryInfo.blocks.map(blockInfo => blockInfo.xml));
|
||||
xmlParts.push.apply(xmlParts, paletteBlocks.map(block => block.xml));
|
||||
xmlParts.push('</category>');
|
||||
}
|
||||
return xmlParts.join('\n');
|
||||
|
|
|
@ -30,6 +30,7 @@ const builtinExtensions = {
|
|||
* @property {object.<string,ArgumentInfo>|undefined} arguments - information about this block's arguments, if any
|
||||
* @property {string|Function|undefined} func - the method for this block on the extension service (default: opcode)
|
||||
* @property {Array.<string>|undefined} filter - the list of targets for which this block should appear (default: all)
|
||||
* @property {Boolean|undefined} hideFromPalette - true if should not be appear in the palette. (default false)
|
||||
*/
|
||||
|
||||
/**
|
||||
|
|
|
@ -535,7 +535,7 @@ const specMap = {
|
|||
{
|
||||
type: 'input',
|
||||
inputOp: 'math_number',
|
||||
inputName: 'COLOR'
|
||||
inputName: 'HUE'
|
||||
}
|
||||
]
|
||||
},
|
||||
|
@ -545,7 +545,7 @@ const specMap = {
|
|||
{
|
||||
type: 'input',
|
||||
inputOp: 'math_number',
|
||||
inputName: 'COLOR'
|
||||
inputName: 'HUE'
|
||||
}
|
||||
]
|
||||
},
|
||||
|
|
Loading…
Reference in a new issue