Keyboard events, "key is down" reporter (#117)

* Keyboard events, "key is down" reporter

* Update comment about inputs

* Simplify/generalize keyMap into a keys-pressed list

* Cast values passed to scratchKeyToKeyCode appropriately.

* Cut unspaced key values

* Fix lint from merge commit
This commit is contained in:
Tim Mickel 2016-09-02 11:23:09 -04:00 committed by GitHub
parent 86f136dd10
commit e831866789
4 changed files with 94 additions and 0 deletions

View file

@ -166,6 +166,31 @@ window.onload = function() {
e.preventDefault();
});
// Feed keyboard events as VM I/O events.
document.addEventListener('keydown', function (e) {
// Don't capture keys intended for Blockly inputs.
if (e.target != document && e.target != document.body) {
return;
}
window.vm.postIOData('keyboard', {
keyCode: e.keyCode,
isDown: true
});
e.preventDefault();
});
document.addEventListener('keyup', function(e) {
// Always capture up events,
// even those that have switched to other targets.
window.vm.postIOData('keyboard', {
keyCode: e.keyCode,
isDown: false
});
// E.g., prevent scroll.
if (e.target != document && e.target != document.body) {
e.preventDefault();
}
});
// Run threads
vm.start();

View file

@ -17,6 +17,8 @@ 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
};
@ -59,4 +61,12 @@ Scratch3SensingBlocks.prototype.currentMenu = function (args) {
return args.CURRENTMENU.toLowerCase();
};
Scratch3SensingBlocks.prototype.keyOptions = function (args) {
return args.KEY_OPTION.toLowerCase();
};
Scratch3SensingBlocks.prototype.getKeyPressed = function (args, util) {
return util.ioQuery('keyboard', 'getKeyIsDown', args.KEY_OPTIONS);
};
module.exports = Scratch3SensingBlocks;

View file

@ -5,6 +5,7 @@ var util = require('util');
// Virtual I/O devices.
var Clock = require('../io/clock');
var Keyboard = require('../io/keyboard');
var Mouse = require('../io/mouse');
var defaultBlockPackages = {
@ -53,6 +54,7 @@ function Runtime () {
this.ioDevices = {
'clock': new Clock(),
'keyboard': new Keyboard(),
'mouse': new Mouse()
};
}

57
src/io/keyboard.js Normal file
View file

@ -0,0 +1,57 @@
var Cast = require('../util/cast');
function Keyboard () {
/**
* List of currently pressed keys.
* @type{Array.<number>}
*/
this._keysPressed = [];
}
/**
* Convert a Scratch key name to a DOM keyCode.
* @param {Any} keyName Scratch key argument.
* @return {number} Key code corresponding to a DOM event.
*/
Keyboard.prototype._scratchKeyToKeyCode = function (keyName) {
if (typeof keyName == 'number') {
// Key codes placed in with number blocks.
return keyName;
}
var keyString = Cast.toString(keyName);
switch (keyString) {
case 'space': return 32;
case 'left arrow': return 37;
case 'up arrow': return 38;
case 'right arrow': return 39;
case 'down arrow': return 40;
// @todo: Consider adding other special keys here.
}
// Keys reported by DOM keyCode are upper case.
return keyString.toUpperCase().charCodeAt(0);
};
Keyboard.prototype.postData = function (data) {
if (data.keyCode) {
var index = this._keysPressed.indexOf(data.keyCode);
if (data.isDown) {
// If not already present, add to the list.
if (index < 0) {
this._keysPressed.push(data.keyCode);
}
} else if (index > -1) {
// If already present, remove from the list.
this._keysPressed.splice(index, 1);
}
}
};
Keyboard.prototype.getKeyIsDown = function (key) {
if (key == 'any') {
return this._keysPressed.length > 0;
}
var keyCode = this._scratchKeyToKeyCode(key);
return this._keysPressed.indexOf(keyCode) > -1;
};
module.exports = Keyboard;