mirror of
https://github.com/scratchfoundation/scratch-vm.git
synced 2024-12-23 14:32:59 -05:00
Merge branch 'develop' into feature/serialization
This commit is contained in:
commit
6c9701f4b2
8 changed files with 70 additions and 12 deletions
|
@ -40,9 +40,9 @@
|
||||||
"lodash.defaultsdeep": "4.6.0",
|
"lodash.defaultsdeep": "4.6.0",
|
||||||
"minilog": "3.1.0",
|
"minilog": "3.1.0",
|
||||||
"promise": "7.1.1",
|
"promise": "7.1.1",
|
||||||
"scratch-audio": "latest",
|
"scratch-audio": "^0.1.0-prerelease.0",
|
||||||
"scratch-blocks": "latest",
|
"scratch-blocks": "^0.1.0-prerelease.0",
|
||||||
"scratch-render": "latest",
|
"scratch-render": "^0.1.0-prerelease.0",
|
||||||
"scratch-storage": "^0.1.0",
|
"scratch-storage": "^0.1.0",
|
||||||
"script-loader": "0.7.0",
|
"script-loader": "0.7.0",
|
||||||
"stats.js": "^0.17.0",
|
"stats.js": "^0.17.0",
|
||||||
|
|
|
@ -194,7 +194,7 @@ class Blocks {
|
||||||
// UI event: clicked scripts toggle in the runtime.
|
// UI event: clicked scripts toggle in the runtime.
|
||||||
if (e.element === 'stackclick') {
|
if (e.element === 'stackclick') {
|
||||||
if (optRuntime) {
|
if (optRuntime) {
|
||||||
optRuntime.toggleScript(e.blockId);
|
optRuntime.toggleScript(e.blockId, {showVisualReport: true});
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -273,16 +273,22 @@ class Blocks {
|
||||||
*/
|
*/
|
||||||
changeBlock (args) {
|
changeBlock (args) {
|
||||||
// Validate
|
// Validate
|
||||||
if (args.element !== 'field' && args.element !== 'mutation') return;
|
if (['field', 'mutation', 'checkbox'].indexOf(args.element) === -1) return;
|
||||||
const block = this._blocks[args.id];
|
const block = this._blocks[args.id];
|
||||||
if (typeof block === 'undefined') return;
|
if (typeof block === 'undefined') return;
|
||||||
|
|
||||||
if (args.element === 'field') {
|
switch (args.element) {
|
||||||
|
case 'field':
|
||||||
// Update block value
|
// Update block value
|
||||||
if (!block.fields[args.name]) return;
|
if (!block.fields[args.name]) return;
|
||||||
block.fields[args.name].value = args.value;
|
block.fields[args.name].value = args.value;
|
||||||
} else if (args.element === 'mutation') {
|
break;
|
||||||
|
case 'mutation':
|
||||||
block.mutation = mutationAdapter(args.value);
|
block.mutation = mutationAdapter(args.value);
|
||||||
|
break;
|
||||||
|
case 'checkbox':
|
||||||
|
block.isMonitored = args.value;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -342,6 +348,20 @@ class Blocks {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Block management: run all blocks.
|
||||||
|
* @param {!object} runtime Runtime to run all blocks in.
|
||||||
|
*/
|
||||||
|
runAllMonitored (runtime) {
|
||||||
|
Object.keys(this._blocks).forEach(blockId => {
|
||||||
|
if (this.getBlock(blockId).isMonitored) {
|
||||||
|
// @todo handle specific targets (e.g. apple x position)
|
||||||
|
runtime.toggleScript(blockId);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Block management: delete blocks and their associated scripts.
|
* Block management: delete blocks and their associated scripts.
|
||||||
* @param {!object} e Blockly delete event to be processed.
|
* @param {!object} e Blockly delete event to be processed.
|
||||||
|
|
|
@ -85,7 +85,7 @@ const execute = function (sequencer, thread) {
|
||||||
} else {
|
} else {
|
||||||
// In a non-hat, report the value visually if necessary if
|
// In a non-hat, report the value visually if necessary if
|
||||||
// at the top of the thread stack.
|
// at the top of the thread stack.
|
||||||
if (typeof resolvedValue !== 'undefined' && thread.atStackTop()) {
|
if (typeof resolvedValue !== 'undefined' && thread.showVisualReport && thread.atStackTop()) {
|
||||||
runtime.visualReport(currentBlockId, resolvedValue);
|
runtime.visualReport(currentBlockId, resolvedValue);
|
||||||
}
|
}
|
||||||
// Finished any yields.
|
// Finished any yields.
|
||||||
|
|
|
@ -52,6 +52,13 @@ class Runtime extends EventEmitter {
|
||||||
*/
|
*/
|
||||||
this.flyoutBlocks = new Blocks();
|
this.flyoutBlocks = new Blocks();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Storage container for monitor blocks.
|
||||||
|
* These will execute on a target maybe
|
||||||
|
* @type {!Blocks}
|
||||||
|
*/
|
||||||
|
this.monitorBlocks = new Blocks();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Currently known editing target for the VM.
|
* Currently known editing target for the VM.
|
||||||
* @type {?Target}
|
* @type {?Target}
|
||||||
|
@ -362,11 +369,13 @@ class Runtime extends EventEmitter {
|
||||||
* Create a thread and push it to the list of threads.
|
* Create a thread and push it to the list of threads.
|
||||||
* @param {!string} id ID of block that starts the stack.
|
* @param {!string} id ID of block that starts the stack.
|
||||||
* @param {!Target} target Target to run thread on.
|
* @param {!Target} target Target to run thread on.
|
||||||
|
* @param {?boolean} optShowVisualReport true if the script should show speech bubble for its value
|
||||||
* @return {!Thread} The newly created thread.
|
* @return {!Thread} The newly created thread.
|
||||||
*/
|
*/
|
||||||
_pushThread (id, target) {
|
_pushThread (id, target, optShowVisualReport) {
|
||||||
const thread = new Thread(id);
|
const thread = new Thread(id);
|
||||||
thread.target = target;
|
thread.target = target;
|
||||||
|
thread.showVisualReport = optShowVisualReport;
|
||||||
thread.pushStack(id);
|
thread.pushStack(id);
|
||||||
this.threads.push(thread);
|
this.threads.push(thread);
|
||||||
return thread;
|
return thread;
|
||||||
|
@ -416,8 +425,11 @@ class Runtime extends EventEmitter {
|
||||||
/**
|
/**
|
||||||
* Toggle a script.
|
* Toggle a script.
|
||||||
* @param {!string} topBlockId ID of block that starts the script.
|
* @param {!string} topBlockId ID of block that starts the script.
|
||||||
|
* @param {?object} opts optional arguments to toggle script
|
||||||
|
* @param {?string} opts.target target ID for target to run script on. If not supplied, uses editing target.
|
||||||
|
* @param {?boolean} opts.showVisualReport true if the speech bubble should pop up on the block, false if not.
|
||||||
*/
|
*/
|
||||||
toggleScript (topBlockId) {
|
toggleScript (topBlockId, opts) {
|
||||||
// Remove any existing thread.
|
// Remove any existing thread.
|
||||||
for (let i = 0; i < this.threads.length; i++) {
|
for (let i = 0; i < this.threads.length; i++) {
|
||||||
if (this.threads[i].topBlock === topBlockId) {
|
if (this.threads[i].topBlock === topBlockId) {
|
||||||
|
@ -426,7 +438,10 @@ class Runtime extends EventEmitter {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Otherwise add it.
|
// Otherwise add it.
|
||||||
this._pushThread(topBlockId, this._editingTarget);
|
this._pushThread(
|
||||||
|
topBlockId,
|
||||||
|
opts && opts.target ? opts.target : this._editingTarget,
|
||||||
|
opts ? opts.showVisualReport : false);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -632,6 +647,7 @@ class Runtime extends EventEmitter {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
this.redrawRequested = false;
|
this.redrawRequested = false;
|
||||||
|
this._pushMonitors();
|
||||||
const doneThreads = this.sequencer.stepThreads();
|
const doneThreads = this.sequencer.stepThreads();
|
||||||
this._updateGlows(doneThreads);
|
this._updateGlows(doneThreads);
|
||||||
this._setThreadCount(this.threads.length + doneThreads.length);
|
this._setThreadCount(this.threads.length + doneThreads.length);
|
||||||
|
@ -641,6 +657,13 @@ class Runtime extends EventEmitter {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Queue monitor blocks to sequencer to be run.
|
||||||
|
*/
|
||||||
|
_pushMonitors () {
|
||||||
|
this.monitorBlocks.runAllMonitored(this);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set the current editing target known by the runtime.
|
* Set the current editing target known by the runtime.
|
||||||
* @param {!Target} editingTarget New editing target.
|
* @param {!Target} editingTarget New editing target.
|
||||||
|
|
|
@ -20,7 +20,7 @@ class Target extends EventEmitter {
|
||||||
super();
|
super();
|
||||||
|
|
||||||
if (!blocks) {
|
if (!blocks) {
|
||||||
blocks = new Blocks(this);
|
blocks = new Blocks();
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
* A unique ID for this target.
|
* A unique ID for this target.
|
||||||
|
|
|
@ -92,6 +92,7 @@ window.onload = function () {
|
||||||
workspace.addChangeListener(vm.blockListener);
|
workspace.addChangeListener(vm.blockListener);
|
||||||
const flyoutWorkspace = workspace.getFlyout().getWorkspace();
|
const flyoutWorkspace = workspace.getFlyout().getWorkspace();
|
||||||
flyoutWorkspace.addChangeListener(vm.flyoutBlockListener);
|
flyoutWorkspace.addChangeListener(vm.flyoutBlockListener);
|
||||||
|
flyoutWorkspace.addChangeListener(vm.monitorBlockListener);
|
||||||
|
|
||||||
// Create FPS counter.
|
// Create FPS counter.
|
||||||
const stats = new window.Stats();
|
const stats = new window.Stats();
|
||||||
|
|
|
@ -696,6 +696,7 @@ class RenderedTarget extends Target {
|
||||||
newClone.effects = JSON.parse(JSON.stringify(this.effects));
|
newClone.effects = JSON.parse(JSON.stringify(this.effects));
|
||||||
newClone.variables = JSON.parse(JSON.stringify(this.variables));
|
newClone.variables = JSON.parse(JSON.stringify(this.variables));
|
||||||
newClone.lists = JSON.parse(JSON.stringify(this.lists));
|
newClone.lists = JSON.parse(JSON.stringify(this.lists));
|
||||||
|
newClone._customState = JSON.parse(JSON.stringify(this._customState));
|
||||||
newClone.initDrawable();
|
newClone.initDrawable();
|
||||||
newClone.updateAllDrawableProperties();
|
newClone.updateAllDrawableProperties();
|
||||||
// Place behind the current target.
|
// Place behind the current target.
|
||||||
|
|
|
@ -59,6 +59,7 @@ class VirtualMachine extends EventEmitter {
|
||||||
|
|
||||||
this.blockListener = this.blockListener.bind(this);
|
this.blockListener = this.blockListener.bind(this);
|
||||||
this.flyoutBlockListener = this.flyoutBlockListener.bind(this);
|
this.flyoutBlockListener = this.flyoutBlockListener.bind(this);
|
||||||
|
this.monitorBlockListener = this.monitorBlockListener.bind(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -413,6 +414,18 @@ class VirtualMachine extends EventEmitter {
|
||||||
this.runtime.flyoutBlocks.blocklyListen(e, this.runtime);
|
this.runtime.flyoutBlocks.blocklyListen(e, this.runtime);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handle a Blockly event for the flyout to be passed to the monitor container.
|
||||||
|
* @param {!Blockly.Event} e Any Blockly event.
|
||||||
|
*/
|
||||||
|
monitorBlockListener (e) {
|
||||||
|
// Filter events by type, since monitor blocks only need to listen to these events.
|
||||||
|
// Monitor blocks shouldn't be destroyed when flyout blocks are deleted.
|
||||||
|
if (['create', 'change'].indexOf(e.type) !== -1) {
|
||||||
|
this.runtime.monitorBlocks.blocklyListen(e, this.runtime);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set an editing target. An editor UI can use this function to switch
|
* Set an editing target. An editor UI can use this function to switch
|
||||||
* between editing different targets, sprites, etc.
|
* between editing different targets, sprites, etc.
|
||||||
|
|
Loading…
Reference in a new issue