mirror of
https://github.com/scratchfoundation/scratch-vm.git
synced 2025-01-10 15:02:06 -05:00
Merge pull request #104 from tmickel/feature/io
VM "I/O devices"; clock, mouse as demo
This commit is contained in:
commit
fd5d85ed73
8 changed files with 151 additions and 2 deletions
|
@ -88,6 +88,24 @@ window.onload = function() {
|
||||||
workspace.reportValue(data.id, data.value);
|
workspace.reportValue(data.id, data.value);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Feed mouse events as VM I/O events.
|
||||||
|
document.addEventListener('mousemove', function (e) {
|
||||||
|
var rect = canvas.getBoundingClientRect();
|
||||||
|
var coordinates = {
|
||||||
|
x: e.clientX - rect.left - rect.width / 2,
|
||||||
|
y: e.clientY - rect.top - rect.height / 2
|
||||||
|
};
|
||||||
|
window.vm.postIOData('mouse', coordinates);
|
||||||
|
});
|
||||||
|
canvas.addEventListener('mousedown', function (e) {
|
||||||
|
window.vm.postIOData('mouse', {isDown: true});
|
||||||
|
e.preventDefault();
|
||||||
|
});
|
||||||
|
canvas.addEventListener('mouseup', function (e) {
|
||||||
|
window.vm.postIOData('mouse', {isDown: false});
|
||||||
|
e.preventDefault();
|
||||||
|
});
|
||||||
|
|
||||||
// Run threads
|
// Run threads
|
||||||
vm.start();
|
vm.start();
|
||||||
|
|
||||||
|
|
43
src/blocks/scratch3_sensing.js
Normal file
43
src/blocks/scratch3_sensing.js
Normal file
|
@ -0,0 +1,43 @@
|
||||||
|
function Scratch3SensingBlocks(runtime) {
|
||||||
|
/**
|
||||||
|
* The runtime instantiating this block package.
|
||||||
|
* @type {Runtime}
|
||||||
|
*/
|
||||||
|
this.runtime = runtime;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieve the block primitives implemented by this package.
|
||||||
|
* @return {Object.<string, Function>} Mapping of opcode to Function.
|
||||||
|
*/
|
||||||
|
Scratch3SensingBlocks.prototype.getPrimitives = function() {
|
||||||
|
return {
|
||||||
|
'sensing_timer': this.getTimer,
|
||||||
|
'sensing_resettimer': this.resetTimer,
|
||||||
|
'sensing_mousex': this.getMouseX,
|
||||||
|
'sensing_mousey': this.getMouseY,
|
||||||
|
'sensing_mousedown': this.getMouseDown
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
Scratch3SensingBlocks.prototype.getTimer = function (args, util) {
|
||||||
|
return util.ioQuery('clock', 'projectTimer');
|
||||||
|
};
|
||||||
|
|
||||||
|
Scratch3SensingBlocks.prototype.resetTimer = function (args, util) {
|
||||||
|
util.ioQuery('clock', 'resetProjectTimer');
|
||||||
|
};
|
||||||
|
|
||||||
|
Scratch3SensingBlocks.prototype.getMouseX = function (args, util) {
|
||||||
|
return util.ioQuery('mouse', 'getX');
|
||||||
|
};
|
||||||
|
|
||||||
|
Scratch3SensingBlocks.prototype.getMouseY = function (args, util) {
|
||||||
|
return util.ioQuery('mouse', 'getY');
|
||||||
|
};
|
||||||
|
|
||||||
|
Scratch3SensingBlocks.prototype.getMouseDown = function (args, util) {
|
||||||
|
return util.ioQuery('mouse', 'getIsDown');
|
||||||
|
};
|
||||||
|
|
||||||
|
module.exports = Scratch3SensingBlocks;
|
|
@ -77,7 +77,14 @@ var execute = function (sequencer, thread) {
|
||||||
startBranch: function (branchNum) {
|
startBranch: function (branchNum) {
|
||||||
sequencer.stepToBranch(thread, branchNum);
|
sequencer.stepToBranch(thread, branchNum);
|
||||||
},
|
},
|
||||||
target: target
|
target: target,
|
||||||
|
ioQuery: function (device, func, args) {
|
||||||
|
// Find the I/O device and execute the query/function call.
|
||||||
|
if (runtime.ioDevices[device] && runtime.ioDevices[device][func]) {
|
||||||
|
var devObject = runtime.ioDevices[device];
|
||||||
|
return devObject[func].call(devObject, args);
|
||||||
|
}
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// Deal with any reported value.
|
// Deal with any reported value.
|
||||||
|
|
|
@ -3,12 +3,17 @@ var Sequencer = require('./sequencer');
|
||||||
var Thread = require('./thread');
|
var Thread = require('./thread');
|
||||||
var util = require('util');
|
var util = require('util');
|
||||||
|
|
||||||
|
// Virtual I/O devices.
|
||||||
|
var Clock = require('../io/clock');
|
||||||
|
var Mouse = require('../io/mouse');
|
||||||
|
|
||||||
var defaultBlockPackages = {
|
var defaultBlockPackages = {
|
||||||
'scratch3_control': require('../blocks/scratch3_control'),
|
'scratch3_control': require('../blocks/scratch3_control'),
|
||||||
'scratch3_event': require('../blocks/scratch3_event'),
|
'scratch3_event': require('../blocks/scratch3_event'),
|
||||||
'scratch3_looks': require('../blocks/scratch3_looks'),
|
'scratch3_looks': require('../blocks/scratch3_looks'),
|
||||||
'scratch3_motion': require('../blocks/scratch3_motion'),
|
'scratch3_motion': require('../blocks/scratch3_motion'),
|
||||||
'scratch3_operators': require('../blocks/scratch3_operators')
|
'scratch3_operators': require('../blocks/scratch3_operators'),
|
||||||
|
'scratch3_sensing': require('../blocks/scratch3_sensing')
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -43,6 +48,11 @@ function Runtime (targets) {
|
||||||
*/
|
*/
|
||||||
this._primitives = {};
|
this._primitives = {};
|
||||||
this._registerBlockPackages();
|
this._registerBlockPackages();
|
||||||
|
|
||||||
|
this.ioDevices = {
|
||||||
|
'clock': new Clock(),
|
||||||
|
'mouse': new Mouse()
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
14
src/index.js
14
src/index.js
|
@ -101,6 +101,17 @@ VirtualMachine.prototype.animationFrame = function () {
|
||||||
this.runtime.animationFrame();
|
this.runtime.animationFrame();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Post I/O data to the virtual devices.
|
||||||
|
* @param {?string} device Name of virtual I/O device.
|
||||||
|
* @param {Object} data Any data object to post to the I/O device.
|
||||||
|
*/
|
||||||
|
VirtualMachine.prototype.postIOData = function (device, data) {
|
||||||
|
if (this.runtime.ioDevices[device]) {
|
||||||
|
this.runtime.ioDevices[device].postData(data);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Worker handlers: for all public methods available above,
|
* Worker handlers: for all public methods available above,
|
||||||
* we must also provide a message handler in case the VM is run
|
* we must also provide a message handler in case the VM is run
|
||||||
|
@ -140,6 +151,9 @@ if (ENV_WORKER) {
|
||||||
case 'animationFrame':
|
case 'animationFrame':
|
||||||
self.vmInstance.animationFrame();
|
self.vmInstance.animationFrame();
|
||||||
break;
|
break;
|
||||||
|
case 'postIOData':
|
||||||
|
self.vmInstance.postIOData(messageData.device, messageData.data);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
if (e.data.id == 'RendererConnected') {
|
if (e.data.id == 'RendererConnected') {
|
||||||
//initRenderWorker();
|
//initRenderWorker();
|
||||||
|
|
16
src/io/clock.js
Normal file
16
src/io/clock.js
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
var Timer = require('../util/timer');
|
||||||
|
|
||||||
|
function Clock () {
|
||||||
|
this._projectTimer = new Timer();
|
||||||
|
this._projectTimer.start();
|
||||||
|
}
|
||||||
|
|
||||||
|
Clock.prototype.projectTimer = function () {
|
||||||
|
return this._projectTimer.timeElapsed() / 1000;
|
||||||
|
};
|
||||||
|
|
||||||
|
Clock.prototype.resetProjectTimer = function () {
|
||||||
|
this._projectTimer.start();
|
||||||
|
};
|
||||||
|
|
||||||
|
module.exports = Clock;
|
33
src/io/mouse.js
Normal file
33
src/io/mouse.js
Normal file
|
@ -0,0 +1,33 @@
|
||||||
|
var MathUtil = require('../util/math-util');
|
||||||
|
|
||||||
|
function Mouse () {
|
||||||
|
this._x = 0;
|
||||||
|
this._y = 0;
|
||||||
|
this._isDown = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
Mouse.prototype.postData = function(data) {
|
||||||
|
if (data.x) {
|
||||||
|
this._x = data.x;
|
||||||
|
}
|
||||||
|
if (data.y) {
|
||||||
|
this._y = data.y;
|
||||||
|
}
|
||||||
|
if (typeof data.isDown !== 'undefined') {
|
||||||
|
this._isDown = data.isDown;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
Mouse.prototype.getX = function () {
|
||||||
|
return MathUtil.clamp(this._x, -240, 240);
|
||||||
|
};
|
||||||
|
|
||||||
|
Mouse.prototype.getY = function () {
|
||||||
|
return MathUtil.clamp(-this._y, -180, 180);
|
||||||
|
};
|
||||||
|
|
||||||
|
Mouse.prototype.getIsDown = function () {
|
||||||
|
return this._isDown;
|
||||||
|
};
|
||||||
|
|
||||||
|
module.exports = Mouse;
|
|
@ -51,6 +51,14 @@ VirtualMachine.prototype.getPlaygroundData = function () {
|
||||||
this.vmWorker.postMessage({method: 'getPlaygroundData'});
|
this.vmWorker.postMessage({method: 'getPlaygroundData'});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
VirtualMachine.prototype.postIOData = function (device, data) {
|
||||||
|
this.vmWorker.postMessage({
|
||||||
|
method: 'postIOData',
|
||||||
|
device: device,
|
||||||
|
data: data
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
VirtualMachine.prototype.start = function () {
|
VirtualMachine.prototype.start = function () {
|
||||||
this.vmWorker.postMessage({method: 'start'});
|
this.vmWorker.postMessage({method: 'start'});
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in a new issue