mirror of
https://github.com/scratchfoundation/scratch-vm.git
synced 2025-06-28 07:10:27 -04:00
Better shadow evaluation (#160)
* Better shadow evaluation * Audit and improve casting for all primitives * Force repeat times to int * Remove colorPicker shadow menu
This commit is contained in:
parent
ebbfe881db
commit
bbea1af5a3
8 changed files with 132 additions and 134 deletions
|
@ -1,3 +1,4 @@
|
|||
var Cast = require('../util/cast');
|
||||
var Promise = require('promise');
|
||||
|
||||
function Scratch3ControlBlocks(runtime) {
|
||||
|
@ -25,9 +26,10 @@ Scratch3ControlBlocks.prototype.getPrimitives = function() {
|
|||
};
|
||||
|
||||
Scratch3ControlBlocks.prototype.repeat = function(args, util) {
|
||||
var times = Math.floor(Cast.toNumber(args.TIMES));
|
||||
// Initialize loop
|
||||
if (util.stackFrame.loopCounter === undefined) {
|
||||
util.stackFrame.loopCounter = parseInt(args.TIMES);
|
||||
util.stackFrame.loopCounter = times;
|
||||
}
|
||||
// Only execute once per frame.
|
||||
// When the branch finishes, `repeat` will be executed again and
|
||||
|
@ -47,13 +49,14 @@ Scratch3ControlBlocks.prototype.repeat = function(args, util) {
|
|||
};
|
||||
|
||||
Scratch3ControlBlocks.prototype.repeatUntil = function(args, util) {
|
||||
var condition = Cast.toBoolean(args.CONDITION);
|
||||
// Only execute once per frame.
|
||||
// When the branch finishes, `repeat` will be executed again and
|
||||
// the second branch will be taken, yielding for the rest of the frame.
|
||||
if (!util.stackFrame.executedInFrame) {
|
||||
util.stackFrame.executedInFrame = true;
|
||||
// If the condition is true, start the branch.
|
||||
if (!args.CONDITION) {
|
||||
if (!condition) {
|
||||
util.startBranch();
|
||||
}
|
||||
} else {
|
||||
|
@ -76,30 +79,33 @@ Scratch3ControlBlocks.prototype.forever = function(args, util) {
|
|||
};
|
||||
|
||||
Scratch3ControlBlocks.prototype.wait = function(args) {
|
||||
var duration = Cast.toNumber(args.DURATION);
|
||||
return new Promise(function(resolve) {
|
||||
setTimeout(function() {
|
||||
resolve();
|
||||
}, 1000 * args.DURATION);
|
||||
}, 1000 * duration);
|
||||
});
|
||||
};
|
||||
|
||||
Scratch3ControlBlocks.prototype.if = function(args, util) {
|
||||
var condition = Cast.toBoolean(args.CONDITION);
|
||||
// Only execute one time. `if` will be returned to
|
||||
// when the branch finishes, but it shouldn't execute again.
|
||||
if (util.stackFrame.executedInFrame === undefined) {
|
||||
util.stackFrame.executedInFrame = true;
|
||||
if (args.CONDITION) {
|
||||
if (condition) {
|
||||
util.startBranch();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
Scratch3ControlBlocks.prototype.ifElse = function(args, util) {
|
||||
var condition = Cast.toBoolean(args.CONDITION);
|
||||
// Only execute one time. `ifElse` will be returned to
|
||||
// when the branch finishes, but it shouldn't execute again.
|
||||
if (util.stackFrame.executedInFrame === undefined) {
|
||||
util.stackFrame.executedInFrame = true;
|
||||
if (args.CONDITION) {
|
||||
if (condition) {
|
||||
util.startBranch(1);
|
||||
} else {
|
||||
util.startBranch(2);
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
var Cast = require('../util/cast');
|
||||
|
||||
function Scratch3EventBlocks(runtime) {
|
||||
/**
|
||||
* The runtime instantiating this block package.
|
||||
|
@ -43,26 +45,30 @@ Scratch3EventBlocks.prototype.getHats = function () {
|
|||
};
|
||||
|
||||
Scratch3EventBlocks.prototype.hatGreaterThanPredicate = function (args, util) {
|
||||
var option = Cast.toString(args.WHENGREATERTHANMENU).toLowerCase();
|
||||
var value = Cast.toNumber(args.VALUE);
|
||||
// @todo: Other cases :)
|
||||
if (args.WHENGREATERTHANMENU == 'TIMER') {
|
||||
return util.ioQuery('clock', 'projectTimer') > args.VALUE;
|
||||
if (option == 'timer') {
|
||||
return util.ioQuery('clock', 'projectTimer') > value;
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
||||
Scratch3EventBlocks.prototype.broadcast = function(args, util) {
|
||||
var broadcastOption = Cast.toString(args.BROADCAST_OPTION);
|
||||
util.startHats('event_whenbroadcastreceived', {
|
||||
'BROADCAST_OPTION': args.BROADCAST_OPTION
|
||||
'BROADCAST_OPTION': broadcastOption
|
||||
});
|
||||
};
|
||||
|
||||
Scratch3EventBlocks.prototype.broadcastAndWait = function (args, util) {
|
||||
var broadcastOption = Cast.toString(args.BROADCAST_OPTION);
|
||||
// Have we run before, starting threads?
|
||||
if (!util.stackFrame.startedThreads) {
|
||||
// No - start hats for this broadcast.
|
||||
util.stackFrame.startedThreads = util.startHats(
|
||||
'event_whenbroadcastreceived', {
|
||||
'BROADCAST_OPTION': args.BROADCAST_OPTION
|
||||
'BROADCAST_OPTION': broadcastOption
|
||||
}
|
||||
);
|
||||
if (util.stackFrame.startedThreads.length == 0) {
|
||||
|
|
|
@ -20,14 +20,11 @@ Scratch3LooksBlocks.prototype.getPrimitives = function() {
|
|||
'looks_thinkforsecs': this.sayforsecs,
|
||||
'looks_show': this.show,
|
||||
'looks_hide': this.hide,
|
||||
'looks_backdrops': this.backdropMenu,
|
||||
'looks_costume': this.costumeMenu,
|
||||
'looks_switchcostumeto': this.switchCostume,
|
||||
'looks_switchbackdropto': this.switchBackdrop,
|
||||
'looks_switchbackdroptoandwait': this.switchBackdropAndWait,
|
||||
'looks_nextcostume': this.nextCostume,
|
||||
'looks_nextbackdrop': this.nextBackdrop,
|
||||
'looks_effectmenu': this.effectMenu,
|
||||
'looks_changeeffectby': this.changeEffect,
|
||||
'looks_seteffectto': this.setEffect,
|
||||
'looks_cleargraphiceffects': this.clearEffects,
|
||||
|
@ -119,11 +116,6 @@ Scratch3LooksBlocks.prototype._setCostumeOrBackdrop = function (target,
|
|||
return [];
|
||||
};
|
||||
|
||||
// @todo(GH-146): Remove.
|
||||
Scratch3LooksBlocks.prototype.costumeMenu = function (args) {
|
||||
return args.COSTUME;
|
||||
};
|
||||
|
||||
Scratch3LooksBlocks.prototype.switchCostume = function (args, util) {
|
||||
this._setCostumeOrBackdrop(util.target, args.COSTUME);
|
||||
};
|
||||
|
@ -134,11 +126,6 @@ Scratch3LooksBlocks.prototype.nextCostume = function (args, util) {
|
|||
);
|
||||
};
|
||||
|
||||
// @todo(GH-146): Remove.
|
||||
Scratch3LooksBlocks.prototype.backdropMenu = function (args) {
|
||||
return args.BACKDROP;
|
||||
};
|
||||
|
||||
Scratch3LooksBlocks.prototype.switchBackdrop = function (args) {
|
||||
this._setCostumeOrBackdrop(this.runtime.getTargetForStage(), args.BACKDROP);
|
||||
};
|
||||
|
@ -175,17 +162,18 @@ Scratch3LooksBlocks.prototype.nextBackdrop = function () {
|
|||
);
|
||||
};
|
||||
|
||||
Scratch3LooksBlocks.prototype.effectMenu = function (args) {
|
||||
return args.EFFECT.toLowerCase();
|
||||
};
|
||||
|
||||
Scratch3LooksBlocks.prototype.changeEffect = function (args, util) {
|
||||
var newValue = args.CHANGE + util.target.effects[args.EFFECT];
|
||||
util.target.setEffect(args.EFFECT, newValue);
|
||||
var effect = Cast.toString(args.EFFECT).toLowerCase();
|
||||
var change = Cast.toNumber(args.CHANGE);
|
||||
if (!util.target.effects.hasOwnProperty(effect)) return;
|
||||
var newValue = change + util.target.effects[effect];
|
||||
util.target.setEffect(effect, newValue);
|
||||
};
|
||||
|
||||
Scratch3LooksBlocks.prototype.setEffect = function (args, util) {
|
||||
util.target.setEffect(args.EFFECT, args.VALUE);
|
||||
var effect = Cast.toString(args.EFFECT).toLowerCase();
|
||||
var value = Cast.toNumber(args.VALUE);
|
||||
util.target.setEffect(effect, value);
|
||||
};
|
||||
|
||||
Scratch3LooksBlocks.prototype.clearEffects = function (args, util) {
|
||||
|
@ -193,11 +181,13 @@ Scratch3LooksBlocks.prototype.clearEffects = function (args, util) {
|
|||
};
|
||||
|
||||
Scratch3LooksBlocks.prototype.changeSize = function (args, util) {
|
||||
util.target.setSize(util.target.size + args.CHANGE);
|
||||
var change = Cast.toNumber(args.CHANGE);
|
||||
util.target.setSize(util.target.size + change);
|
||||
};
|
||||
|
||||
Scratch3LooksBlocks.prototype.setSize = function (args, util) {
|
||||
util.target.setSize(args.SIZE);
|
||||
var size = Cast.toNumber(args.SIZE);
|
||||
util.target.setSize(size);
|
||||
};
|
||||
|
||||
Scratch3LooksBlocks.prototype.getSize = function (args, util) {
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
var Cast = require('../util/cast');
|
||||
var MathUtil = require('../util/math-util');
|
||||
|
||||
function Scratch3MotionBlocks(runtime) {
|
||||
|
@ -30,42 +31,52 @@ Scratch3MotionBlocks.prototype.getPrimitives = function() {
|
|||
};
|
||||
|
||||
Scratch3MotionBlocks.prototype.moveSteps = function (args, util) {
|
||||
var steps = Cast.toNumber(args.STEPS);
|
||||
var radians = MathUtil.degToRad(util.target.direction);
|
||||
var dx = args.STEPS * Math.cos(radians);
|
||||
var dy = args.STEPS * Math.sin(radians);
|
||||
var dx = steps * Math.cos(radians);
|
||||
var dy = steps * Math.sin(radians);
|
||||
util.target.setXY(util.target.x + dx, util.target.y + dy);
|
||||
};
|
||||
|
||||
Scratch3MotionBlocks.prototype.goToXY = function (args, util) {
|
||||
util.target.setXY(args.X, args.Y);
|
||||
var x = Cast.toNumber(args.X);
|
||||
var y = Cast.toNumber(args.Y);
|
||||
util.target.setXY(x, y);
|
||||
};
|
||||
|
||||
Scratch3MotionBlocks.prototype.turnRight = function (args, util) {
|
||||
util.target.setDirection(util.target.direction + args.DEGREES);
|
||||
var degrees = Cast.toNumber(args.DEGREES);
|
||||
util.target.setDirection(util.target.direction + degrees);
|
||||
};
|
||||
|
||||
Scratch3MotionBlocks.prototype.turnLeft = function (args, util) {
|
||||
util.target.setDirection(util.target.direction - args.DEGREES);
|
||||
var degrees = Cast.toNumber(args.DEGREES);
|
||||
util.target.setDirection(util.target.direction - degrees);
|
||||
};
|
||||
|
||||
Scratch3MotionBlocks.prototype.pointInDirection = function (args, util) {
|
||||
util.target.setDirection(args.DIRECTION);
|
||||
var direction = Cast.toNumber(args.DIRECTION);
|
||||
util.target.setDirection(direction);
|
||||
};
|
||||
|
||||
Scratch3MotionBlocks.prototype.changeX = function (args, util) {
|
||||
util.target.setXY(util.target.x + args.DX, util.target.y);
|
||||
var dx = Cast.toNumber(args.DX);
|
||||
util.target.setXY(util.target.x + dx, util.target.y);
|
||||
};
|
||||
|
||||
Scratch3MotionBlocks.prototype.setX = function (args, util) {
|
||||
util.target.setXY(args.X, util.target.y);
|
||||
var x = Cast.toNumber(args.X);
|
||||
util.target.setXY(x, util.target.y);
|
||||
};
|
||||
|
||||
Scratch3MotionBlocks.prototype.changeY = function (args, util) {
|
||||
util.target.setXY(util.target.x, util.target.y + args.DY);
|
||||
var dy = Cast.toNumber(args.DY);
|
||||
util.target.setXY(util.target.x, util.target.y + dy);
|
||||
};
|
||||
|
||||
Scratch3MotionBlocks.prototype.setY = function (args, util) {
|
||||
util.target.setXY(util.target.x, args.Y);
|
||||
var y = Cast.toNumber(args.Y);
|
||||
util.target.setXY(util.target.x, y);
|
||||
};
|
||||
|
||||
Scratch3MotionBlocks.prototype.getX = function (args, util) {
|
||||
|
|
|
@ -14,11 +14,6 @@ function Scratch3OperatorsBlocks(runtime) {
|
|||
*/
|
||||
Scratch3OperatorsBlocks.prototype.getPrimitives = function() {
|
||||
return {
|
||||
'math_number': this.number,
|
||||
'math_positive_number': this.number,
|
||||
'math_whole_number': this.number,
|
||||
'math_angle': this.number,
|
||||
'text': this.text,
|
||||
'operator_add': this.add,
|
||||
'operator_subtract': this.subtract,
|
||||
'operator_multiply': this.multiply,
|
||||
|
@ -35,19 +30,10 @@ Scratch3OperatorsBlocks.prototype.getPrimitives = function() {
|
|||
'operator_length': this.length,
|
||||
'operator_mod': this.mod,
|
||||
'operator_round': this.round,
|
||||
'operator_mathop_menu': this.mathopMenu,
|
||||
'operator_mathop': this.mathop
|
||||
};
|
||||
};
|
||||
|
||||
Scratch3OperatorsBlocks.prototype.number = function (args) {
|
||||
return Cast.toNumber(args.NUM);
|
||||
};
|
||||
|
||||
Scratch3OperatorsBlocks.prototype.text = function (args) {
|
||||
return Cast.toString(args.TEXT);
|
||||
};
|
||||
|
||||
Scratch3OperatorsBlocks.prototype.add = function (args) {
|
||||
return Cast.toNumber(args.NUM1) + Cast.toNumber(args.NUM2);
|
||||
};
|
||||
|
@ -77,20 +63,22 @@ Scratch3OperatorsBlocks.prototype.gt = function (args) {
|
|||
};
|
||||
|
||||
Scratch3OperatorsBlocks.prototype.and = function (args) {
|
||||
return Cast.toBoolean(args.OPERAND1 && args.OPERAND2);
|
||||
return Cast.toBoolean(args.OPERAND1) && Cast.toBoolean(args.OPERAND2);
|
||||
};
|
||||
|
||||
Scratch3OperatorsBlocks.prototype.or = function (args) {
|
||||
return Cast.toBoolean(args.OPERAND1 || args.OPERAND2);
|
||||
return Cast.toBoolean(args.OPERAND1) || Cast.toBoolean(args.OPERAND2);
|
||||
};
|
||||
|
||||
Scratch3OperatorsBlocks.prototype.not = function (args) {
|
||||
return Cast.toBoolean(!args.OPERAND);
|
||||
return !Cast.toBoolean(args.OPERAND);
|
||||
};
|
||||
|
||||
Scratch3OperatorsBlocks.prototype.random = function (args) {
|
||||
var low = args.FROM <= args.TO ? args.FROM : args.TO;
|
||||
var high = args.FROM <= args.TO ? args.TO : args.FROM;
|
||||
var nFrom = Cast.toNumber(args.FROM);
|
||||
var nTo = Cast.toNumber(args.TO);
|
||||
var low = nFrom <= nTo ? nFrom : nTo;
|
||||
var high = nFrom <= nTo ? nTo : nFrom;
|
||||
if (low == high) return low;
|
||||
// If both low and high are ints, truncate the result to an int.
|
||||
var lowInt = low == parseInt(low);
|
||||
|
@ -132,10 +120,6 @@ Scratch3OperatorsBlocks.prototype.round = function (args) {
|
|||
return Math.round(Cast.toNumber(args.NUM));
|
||||
};
|
||||
|
||||
Scratch3OperatorsBlocks.prototype.mathopMenu = function (args) {
|
||||
return args.OPERATOR;
|
||||
};
|
||||
|
||||
Scratch3OperatorsBlocks.prototype.mathop = function (args) {
|
||||
var operator = Cast.toString(args.OPERATOR).toLowerCase();
|
||||
var n = Cast.toNumber(args.NUM);
|
||||
|
|
|
@ -14,7 +14,6 @@ function Scratch3SensingBlocks(runtime) {
|
|||
*/
|
||||
Scratch3SensingBlocks.prototype.getPrimitives = function() {
|
||||
return {
|
||||
'colour_picker': this.colorPicker,
|
||||
'sensing_touchingcolor': this.touchingColor,
|
||||
'sensing_coloristouchingcolor': this.colorTouchingColor,
|
||||
'sensing_timer': this.getTimer,
|
||||
|
@ -22,17 +21,11 @@ Scratch3SensingBlocks.prototype.getPrimitives = function() {
|
|||
'sensing_mousex': this.getMouseX,
|
||||
'sensing_mousey': this.getMouseY,
|
||||
'sensing_mousedown': this.getMouseDown,
|
||||
'sensing_keyoptions': this.keyOptions,
|
||||
'sensing_keypressed': this.getKeyPressed,
|
||||
'sensing_current': this.current,
|
||||
'sensing_currentmenu': this.currentMenu
|
||||
'sensing_current': this.current
|
||||
};
|
||||
};
|
||||
|
||||
Scratch3SensingBlocks.prototype.colorPicker = function (args) {
|
||||
return args.COLOUR;
|
||||
};
|
||||
|
||||
Scratch3SensingBlocks.prototype.touchingColor = function (args, util) {
|
||||
var color = Cast.toRgbColorList(args.COLOR);
|
||||
return util.target.isTouchingColor(color);
|
||||
|
@ -65,8 +58,9 @@ Scratch3SensingBlocks.prototype.getMouseDown = function (args, util) {
|
|||
};
|
||||
|
||||
Scratch3SensingBlocks.prototype.current = function (args) {
|
||||
var menuOption = Cast.toString(args.CURRENTMENU).toLowerCase();
|
||||
var date = new Date();
|
||||
switch (args.CURRENTMENU) {
|
||||
switch (menuOption) {
|
||||
case 'year': return date.getFullYear();
|
||||
case 'month': return date.getMonth() + 1; // getMonth is zero-based
|
||||
case 'date': return date.getDate();
|
||||
|
@ -75,14 +69,7 @@ Scratch3SensingBlocks.prototype.current = function (args) {
|
|||
case 'minute': return date.getMinutes();
|
||||
case 'second': return date.getSeconds();
|
||||
}
|
||||
};
|
||||
|
||||
Scratch3SensingBlocks.prototype.currentMenu = function (args) {
|
||||
return args.CURRENTMENU.toLowerCase();
|
||||
};
|
||||
|
||||
Scratch3SensingBlocks.prototype.keyOptions = function (args) {
|
||||
return args.KEY_OPTION.toLowerCase();
|
||||
return 0;
|
||||
};
|
||||
|
||||
Scratch3SensingBlocks.prototype.getKeyPressed = function (args, util) {
|
||||
|
|
|
@ -22,40 +22,91 @@ var execute = function (sequencer, thread) {
|
|||
var currentBlockId = thread.peekStack();
|
||||
var currentStackFrame = thread.peekStackFrame();
|
||||
|
||||
// Query info about the block.
|
||||
var opcode = target.blocks.getOpcode(currentBlockId);
|
||||
var blockFunction = runtime.getOpcodeFunction(opcode);
|
||||
var isHat = runtime.getIsHat(opcode);
|
||||
var fields = target.blocks.getFields(currentBlockId);
|
||||
var inputs = target.blocks.getInputs(currentBlockId);
|
||||
|
||||
if (!opcode) {
|
||||
console.warn('Could not get opcode for block: ' + currentBlockId);
|
||||
return;
|
||||
}
|
||||
|
||||
var blockFunction = runtime.getOpcodeFunction(opcode);
|
||||
var isHat = runtime.getIsHat(opcode);
|
||||
|
||||
// Hats are implemented slightly differently from regular blocks.
|
||||
// If they have an associated block function, it's treated as a predicate;
|
||||
// if not, execution will proceed right through it (as a no-op).
|
||||
if (!blockFunction) {
|
||||
if (!isHat) {
|
||||
console.warn('Could not get implementation for opcode: ' + opcode);
|
||||
/**
|
||||
* Handle any reported value from the primitive, either directly returned
|
||||
* or after a promise resolves.
|
||||
* @param {*} resolvedValue Value eventually returned from the primitive.
|
||||
*/
|
||||
var handleReport = function (resolvedValue) {
|
||||
thread.pushReportedValue(resolvedValue);
|
||||
if (isHat) {
|
||||
// Hat predicate was evaluated.
|
||||
if (runtime.getIsEdgeActivatedHat(opcode)) {
|
||||
// If this is an edge-activated hat, only proceed if
|
||||
// the value is true and used to be false.
|
||||
var oldEdgeValue = runtime.updateEdgeActivatedValue(
|
||||
currentBlockId,
|
||||
resolvedValue
|
||||
);
|
||||
var edgeWasActivated = !oldEdgeValue && resolvedValue;
|
||||
if (!edgeWasActivated) {
|
||||
sequencer.retireThread(thread);
|
||||
}
|
||||
} else {
|
||||
// Not an edge-activated hat: retire the thread
|
||||
// if predicate was false.
|
||||
if (!resolvedValue) {
|
||||
sequencer.retireThread(thread);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// In a non-hat, report the value visually if necessary if
|
||||
// at the top of the thread stack.
|
||||
if (typeof resolvedValue !== 'undefined' && thread.atStackTop()) {
|
||||
runtime.visualReport(currentBlockId, resolvedValue);
|
||||
}
|
||||
// Finished any yields.
|
||||
thread.setStatus(Thread.STATUS_RUNNING);
|
||||
}
|
||||
};
|
||||
|
||||
// Hats and single-field shadows are implemented slightly differently
|
||||
// from regular blocks.
|
||||
// For hats: if they have an associated block function,
|
||||
// it's treated as a predicate; if not, execution will proceed as a no-op.
|
||||
// For single-field shadows: If the block has a single field, and no inputs,
|
||||
// immediately return the value of the field.
|
||||
if (!blockFunction) {
|
||||
if (isHat) {
|
||||
// Skip through the block (hat with no predicate).
|
||||
return;
|
||||
} else {
|
||||
if (Object.keys(fields).length == 1 &&
|
||||
Object.keys(inputs).length == 0) {
|
||||
// One field and no inputs - treat as arg.
|
||||
for (var fieldKey in fields) { // One iteration.
|
||||
handleReport(fields[fieldKey].value);
|
||||
}
|
||||
} else {
|
||||
console.warn('Could not get implementation for opcode: ' +
|
||||
opcode);
|
||||
}
|
||||
thread.requestScriptGlowInFrame = true;
|
||||
return;
|
||||
}
|
||||
// Skip through the block.
|
||||
// (either hat with no predicate, or missing op).
|
||||
thread.requestScriptGlowInFrame = true;
|
||||
return;
|
||||
}
|
||||
|
||||
// Generate values for arguments (inputs).
|
||||
var argValues = {};
|
||||
|
||||
// Add all fields on this block to the argValues.
|
||||
var fields = target.blocks.getFields(currentBlockId);
|
||||
for (var fieldName in fields) {
|
||||
argValues[fieldName] = fields[fieldName].value;
|
||||
}
|
||||
|
||||
// Recursively evaluate input blocks.
|
||||
var inputs = target.blocks.getInputs(currentBlockId);
|
||||
for (var inputName in inputs) {
|
||||
var input = inputs[inputName];
|
||||
var inputBlockId = input.block;
|
||||
|
@ -117,44 +168,6 @@ var execute = function (sequencer, thread) {
|
|||
thread.requestScriptGlowInFrame = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle any reported value from the primitive, either directly returned
|
||||
* or after a promise resolves.
|
||||
* @param {*} resolvedValue Value eventually returned from the primitive.
|
||||
*/
|
||||
var handleReport = function (resolvedValue) {
|
||||
thread.pushReportedValue(resolvedValue);
|
||||
if (isHat) {
|
||||
// Hat predicate was evaluated.
|
||||
if (runtime.getIsEdgeActivatedHat(opcode)) {
|
||||
// If this is an edge-activated hat, only proceed if
|
||||
// the value is true and used to be false.
|
||||
var oldEdgeValue = runtime.updateEdgeActivatedValue(
|
||||
currentBlockId,
|
||||
resolvedValue
|
||||
);
|
||||
var edgeWasActivated = !oldEdgeValue && resolvedValue;
|
||||
if (!edgeWasActivated) {
|
||||
sequencer.retireThread(thread);
|
||||
}
|
||||
} else {
|
||||
// Not an edge-activated hat: retire the thread
|
||||
// if predicate was false.
|
||||
if (!resolvedValue) {
|
||||
sequencer.retireThread(thread);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// In a non-hat, report the value visually if necessary if
|
||||
// at the top of the thread stack.
|
||||
if (typeof resolvedValue !== 'undefined' && thread.atStackTop()) {
|
||||
runtime.visualReport(currentBlockId, resolvedValue);
|
||||
}
|
||||
// Finished any yields.
|
||||
thread.setStatus(Thread.STATUS_RUNNING);
|
||||
}
|
||||
};
|
||||
|
||||
// If it's a promise, wait until promise resolves.
|
||||
if (isPromise(primitiveReportedValue)) {
|
||||
if (thread.status === Thread.STATUS_RUNNING) {
|
||||
|
|
|
@ -198,6 +198,7 @@ Clone.prototype.setSize = function (size) {
|
|||
* @param {!number} value Numerical magnitude of effect.
|
||||
*/
|
||||
Clone.prototype.setEffect = function (effectName, value) {
|
||||
if (!this.effects.hasOwnProperty(effectName)) return;
|
||||
this.effects[effectName] = value;
|
||||
if (this.renderer) {
|
||||
var props = {};
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue