Add support for controlling the printer with an NES retro-style USB controller. As long as it has 10 buttons.

This commit is contained in:
Matt McWilliams 2024-11-26 13:27:31 -05:00
parent 93ac73f69e
commit 498b585b67
21 changed files with 444 additions and 69 deletions

View File

@ -1,5 +1,5 @@
{ {
"version": "1.8.150", "version": "1.8.151",
"ext_port": 1111, "ext_port": 1111,
"profiles": { "profiles": {
"mcopy": { "mcopy": {

View File

@ -2501,6 +2501,7 @@ const timing = require('./lib/ui/timing.js');
const Mscript = require('./lib/mscript'); const Mscript = require('./lib/mscript');
const { delay } = require('./lib/delay'); const { delay } = require('./lib/delay');
const alertObj = require('./lib/ui/alert.js'); const alertObj = require('./lib/ui/alert.js');
const gamecontroller = require('./lib/ui/gamecontroller.js');
const { Log } = require('./lib/log'); const { Log } = require('./lib/log');
let log; let log;
@ -2533,4 +2534,5 @@ async function init () {
capper.init(); capper.init();
alertObj.init(); alertObj.init();
timing.init(); timing.init();
gamecontroller.init(seq, cmd, cam, proj);
}; };

View File

@ -29,6 +29,15 @@ cam.set = function (dir, callback) {
cam.lock = true; cam.lock = true;
}; };
cam.setAsync = async function (dir) {
return new Promise((resolve, reject) => {
return cam.set(dir, function (ms) {
setTimeout(reject, 10000);
return resolve(ms);
});
});
}
cam.setValue = function (val) { cam.setValue = function (val) {
'use strict'; 'use strict';
var obj = { var obj = {
@ -55,6 +64,16 @@ cam.move = function (callback) {
cam.queue[obj.id] = obj; cam.queue[obj.id] = obj;
cam.lock = true; cam.lock = true;
}; };
cam.moveAsync = async function () {
return new Promise((resolve, reject) => {
return cam.move(function (ms) {
setTimeout(reject, 10000);
return resolve(ms);
});
});
}
cam.end = function (c, id, ms) { cam.end = function (c, id, ms) {
'use strict'; 'use strict';
if (c === cfg.arduino.cmd.camera_forward) { if (c === cfg.arduino.cmd.camera_forward) {
@ -85,6 +104,8 @@ cam.end = function (c, id, ms) {
if (typeof cam.queue[id] !== 'undefined') { if (typeof cam.queue[id] !== 'undefined') {
if (typeof cam.queue[id].callback !== 'undefined') { if (typeof cam.queue[id].callback !== 'undefined') {
cam.queue[id].callback(ms); cam.queue[id].callback(ms);
} else {
log.info('NO CAM CALLBACK')
} }
delete cam.queue[id]; delete cam.queue[id];
cam.lock = false; cam.lock = false;

View File

@ -15,14 +15,14 @@ cmd.projector_forward = function (callback) {
$('#cmd_proj_forward').addClass('active'); $('#cmd_proj_forward').addClass('active');
if (!proj.dir) { if (!proj.dir) {
proj.set(true, function (ms) { proj.set(true, function (ms) {
setTimeout(function () { //setTimeout(function () {
proj.move(res); proj.move(res);
}, cfg.arduino.serialDelay); //}, cfg.arduino.serialDelay);
}); });
} else { } else {
setTimeout(function () { //setTimeout(function () {
proj.move(res); proj.move(res);
}, cfg.arduino.serialDelay); //}, cfg.arduino.serialDelay);
} }
}; };
/** /**
@ -40,14 +40,14 @@ cmd.projector_backward = function (callback) {
$('#cmd_proj_backward').addClass('active'); $('#cmd_proj_backward').addClass('active');
if (proj.dir) { if (proj.dir) {
proj.set(false, function (ms) { proj.set(false, function (ms) {
setTimeout(function () { //setTimeout(function () {
proj.move(res); proj.move(res);
}, cfg.arduino.serialDelay); //}, cfg.arduino.serialDelay);
}); });
} else { } else {
setTimeout(function () { //setTimeout(function () {
proj.move(res); proj.move(res);
}, cfg.arduino.serialDelay); //}, cfg.arduino.serialDelay);
} }
}; };
@ -61,14 +61,14 @@ cmd.projector_second_forward = function (callback) {
$('#cmd_proj2_forward').addClass('active'); $('#cmd_proj2_forward').addClass('active');
if (!proj.second.dir) { if (!proj.second.dir) {
proj.second.set(true, function (ms) { proj.second.set(true, function (ms) {
setTimeout(function () { //setTimeout(function () {
proj.second.move(res); proj.second.move(res);
}, cfg.arduino.serialDelay); //}, cfg.arduino.serialDelay);
}); });
} else { } else {
setTimeout(function () { //setTimeout(function () {
proj.second.move(res); proj.second.move(res);
}, cfg.arduino.serialDelay); //}, cfg.arduino.serialDelay);
} }
}; };
cmd.projector_second_backward = function (callback) { cmd.projector_second_backward = function (callback) {
@ -81,14 +81,14 @@ cmd.projector_second_backward = function (callback) {
$('#cmd_proj2_backward').addClass('active'); $('#cmd_proj2_backward').addClass('active');
if (proj.second.dir) { if (proj.second.dir) {
proj.second.set(false, function (ms) { proj.second.set(false, function (ms) {
setTimeout(function () { //setTimeout(function () {
proj.second.move(res); proj.second.move(res);
}, cfg.arduino.serialDelay); //}, cfg.arduino.serialDelay);
}); });
} else { } else {
setTimeout(function () { //setTimeout(function () {
proj.second.move(res); proj.second.move(res);
}, cfg.arduino.serialDelay); //}, cfg.arduino.serialDelay);
} }
}; };
@ -112,32 +112,32 @@ cmd.camera_forward = function (rgb, callback) {
var off = [0, 0, 0]; var off = [0, 0, 0];
var res = function (ms) { var res = function (ms) {
gui.updateState(); gui.updateState();
setTimeout(function () { //setTimeout(function () {
light.display(off); light.display(off);
light.set(off, function () { light.set(off, function () {
$('#cmd_cam_forward').removeClass('active'); $('#cmd_cam_forward').removeClass('active');
if (callback) { callback(ms); } if (callback) { callback(ms); }
}); });
}, cfg.arduino.serialDelay); //}, cfg.arduino.serialDelay);
}; };
$('#cmd_cam_forward').addClass('active'); $('#cmd_cam_forward').addClass('active');
if (!cam.dir) { if (!cam.dir) {
cam.set(true, function () { cam.set(true, function () {
setTimeout( function () { //setTimeout( function () {
light.display(rgb); light.display(rgb);
light.set(rgb, function () { light.set(rgb, function () {
setTimeout( function () { //setTimeout( function () {
cam.move(res); cam.move(res);
}, cfg.arduino.serialDelay); //}, cfg.arduino.serialDelay);
}); });
}, cfg.arduino.serialDelay); //}, cfg.arduino.serialDelay);
}); });
} else { } else {
light.display(rgb); light.display(rgb);
light.set(rgb, function () { light.set(rgb, function () {
setTimeout(function () { //setTimeout(function () {
cam.move(res); cam.move(res);
}, cfg.arduino.serialDelay); //}, cfg.arduino.serialDelay);
}); });
} }
}; };
@ -234,20 +234,20 @@ cmd.camera_backward = function (rgb, callback) {
$('#cmd_cam_backward').addClass('active'); $('#cmd_cam_backward').addClass('active');
if (cam.dir) { if (cam.dir) {
cam.set(false, function () { cam.set(false, function () {
setTimeout(function () { //setTimeout(function () {
light.display(rgb); light.display(rgb);
light.set(rgb, function () { light.set(rgb, function () {
cam.move(res); cam.move(res);
}); });
}, cfg.arduino.serialDelay); //}, cfg.arduino.serialDelay);
}); });
} else { } else {
setTimeout(function () { //setTimeout(function () {
light.display(rgb); light.display(rgb);
light.set(rgb, function () { light.set(rgb, function () {
cam.move(res); cam.move(res);
}); });
}, cfg.arduino.serialDelay); //}, cfg.arduino.serialDelay);
} }
}; };
/** /**
@ -284,12 +284,12 @@ cmd.black_backward = function (callback) {
}); });
} else { } else {
cam.set(false, function () { cam.set(false, function () {
setTimeout(function () { //setTimeout(function () {
light.display(off); light.display(off);
light.set(off, function () { light.set(off, function () {
cam.move(res); cam.move(res);
}); });
}, cfg.arduino.serialDelay); //}, cfg.arduino.serialDelay);
}); });
} }
} else { } else {
@ -309,12 +309,12 @@ cmd.black_backward = function (callback) {
}, cfg.arduino.serialDelay); }, cfg.arduino.serialDelay);
}); });
} else { } else {
setTimeout(function () { //setTimeout(function () {
light.display(off); light.display(off);
light.set(off, function () { light.set(off, function () {
cam.move(res); cam.move(res);
}); });
}, cfg.arduino.serialDelay); //}, cfg.arduino.serialDelay);
} }
} }
}; };
@ -339,32 +339,32 @@ cmd.camera_second_forward = function (callback) {
var off = [0, 0, 0]; var off = [0, 0, 0];
var res = function (ms) { var res = function (ms) {
gui.updateState(); gui.updateState();
setTimeout(function () { //setTimeout(function () {
light.display(off); light.display(off);
light.set(off, function () { light.set(off, function () {
$('#cmd_cam2_forward').removeClass('active'); $('#cmd_cam2_forward').removeClass('active');
if (callback) { callback(ms); } if (callback) { callback(ms); }
}); });
}, cfg.arduino.serialDelay); //}, cfg.arduino.serialDelay);
}; };
$('#cmd_cam2_forward').addClass('active'); $('#cmd_cam2_forward').addClass('active');
if (!cam.second.dir) { if (!cam.second.dir) {
cam.second.set(true, function () { cam.second.set(true, function () {
setTimeout( function () { //setTimeout( function () {
light.display(rgb); light.display(rgb);
light.set(rgb, function () { light.set(rgb, function () {
setTimeout( function () { setTimeout( function () {
cam.second.move(res); cam.second.move(res);
}, cfg.arduino.serialDelay); }, cfg.arduino.serialDelay);
}); });
}, cfg.arduino.serialDelay); //}, cfg.arduino.serialDelay);
}); });
} else { } else {
light.display(rgb); light.display(rgb);
light.set(rgb, function () { light.set(rgb, function () {
setTimeout(function () { //setTimeout(function () {
cam.second.move(res); cam.second.move(res);
}, cfg.arduino.serialDelay); //}, cfg.arduino.serialDelay);
}); });
} }
}; };
@ -382,20 +382,20 @@ cmd.camera_second_backward = function (callback) {
$('#cmd_cam_backward').addClass('active'); $('#cmd_cam_backward').addClass('active');
if (cam.second.dir) { if (cam.second.dir) {
cam.second.set(false, function () { cam.second.set(false, function () {
setTimeout(function () { //setTimeout(function () {
light.display(rgb); light.display(rgb);
light.set(rgb, function () { light.set(rgb, function () {
cam.second.move(res); cam.second.move(res);
}); });
}, cfg.arduino.serialDelay); //}, cfg.arduino.serialDelay);
}); });
} else { } else {
setTimeout(function () { //setTimeout(function () {
light.display(rgb); light.display(rgb);
light.set(rgb, function () { light.set(rgb, function () {
cam.second.move(res); cam.second.move(res);
}); });
}, cfg.arduino.serialDelay); //}, cfg.arduino.serialDelay);
} }
}; };
@ -410,21 +410,21 @@ cmd.black_second_forward = function (callback) {
$('#cmd_black2_forward').addClass('active'); $('#cmd_black2_forward').addClass('active');
if (!cam.second.dir) { if (!cam.second.dir) {
cam.second.set(true, function () { cam.second.set(true, function () {
setTimeout( function () { //setTimeout( function () {
light.display(off); light.display(off);
light.set(off, function () { light.set(off, function () {
setTimeout( function () { //setTimeout( function () {
cam.second.move(res); cam.second.move(res);
}, cfg.arduino.serialDelay); //}, cfg.arduino.serialDelay);
}); });
}, cfg.arduino.serialDelay); //}, cfg.arduino.serialDelay);
}); });
} else { } else {
light.display(off); light.display(off);
light.set(off, function () { light.set(off, function () {
setTimeout(function () { //setTimeout(function () {
cam.second.move(res); cam.second.move(res);
}, cfg.arduino.serialDelay); //}, cfg.arduino.serialDelay);
}); });
} }
}; };
@ -440,20 +440,20 @@ cmd.black2_backward = function (callback) {
$('#cmd_black2_backward').addClass('active'); $('#cmd_black2_backward').addClass('active');
if (cam.second.dir) { if (cam.second.dir) {
cam.second.set(false, function () { cam.second.set(false, function () {
setTimeout(function () { //setTimeout(function () {
light.display(off); light.display(off);
light.set(off, function () { light.set(off, function () {
cam.second.move(res); cam.second.move(res);
}); });
}, cfg.arduino.serialDelay); //}, cfg.arduino.serialDelay);
}); });
} else { } else {
setTimeout(function () { //setTimeout(function () {
light.display(off); light.display(off);
light.set(off, function () { light.set(off, function () {
cam.second.move(res); cam.second.move(res);
}); });
}, cfg.arduino.serialDelay); //}, cfg.arduino.serialDelay);
} }
}; };

View File

@ -0,0 +1,159 @@
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
let gamecontroller;
class GameController {
constructor() {
this.cameraMoving = false;
this.projectorMoving = false;
}
init(seq, cmd, cam, proj) {
this.seq = seq;
this.cmd = cmd;
this.cam = cam;
this.proj = proj;
window.addEventListener('gamepadconnected', (e) => {
const gamepads = navigator.getGamepads();
if (gamepads.length > 0) {
console.dir(gamepads[0]);
this.pressed = gamepads[0].buttons.map((button) => { return button.pressed; });
if (gamepads[0].id.indexOf("USB Gamepad") !== -1 && gamepads[0].buttons.length === 10) {
gui.notify('GAMEPAD CONNECTED', 'NES Controller');
}
else {
gui.notify('GAMEPAD CONNECTED', 'Unknown');
}
}
this.handleController();
});
window.addEventListener('gamepaddisconnected', (e) => {
gui.notify('GAMEPAD DISCONNECTED', '');
});
}
handleController() {
const gamepads = navigator.getGamepads();
if (gamepads.length === 0) {
return;
}
const gamepad = gamepads[0];
if (gamepad.id.indexOf("USB Gamepad") !== -1 && gamepad.buttons.length === 10) {
this.handleNESController(gamepad);
}
requestAnimationFrame(this.handleController.bind(this));
}
handleNESController(gamepad) {
const leftStickX = gamepad.axes[0];
const leftStickY = gamepad.axes[1];
//log.info(leftStickX + ',' + leftStickY)
//select == 8
//start == 9
//A == 2
//B == 1
for (let i = 0; i < gamepad.buttons.length; i++) {
if (gamepad.buttons[i].pressed && !this.pressed[i]) {
log.info(`Button[${i}] pressed`);
if (i === 2) {
if (!this.cameraMoving)
this.camera();
}
else if (i === 1) {
if (!this.projectorMoving)
this.projector();
}
else if (i == 9) {
this.sequence();
}
}
}
this.pressed = gamepad.buttons.map((button) => { return button.pressed; });
this.cameraDirection(leftStickX);
this.projectorDirection(leftStickY);
}
camera(silent = false) {
return __awaiter(this, void 0, void 0, function* () {
const dir = this.cam.dir ? 'camera_forward' : 'camera_backward';
if (!silent)
log.info(`Gamepad A ${dir}`);
this.cameraMoving = true;
yield this.cam.moveAsync();
this.cameraMoving = false;
});
}
projector(silent = false) {
return __awaiter(this, void 0, void 0, function* () {
const dir = this.cam.dir ? 'projector_forward' : 'projector_backward';
if (!silent)
log.info(`Gamepad B ${dir}`);
this.projectorMoving = true;
yield this.proj.moveAsync();
this.projectorMoving = false;
});
}
cameraDirection(dir) {
return __awaiter(this, void 0, void 0, function* () {
if (dir !== 0 && this.cameraMoving) {
log.info('Camera D-PAD blocked');
return;
}
if (dir === 1) {
log.info('Gamepad D-pad camera_forward');
if (!this.cam.dir) {
this.cameraMoving = true;
yield this.proj.setAsync(true);
}
yield this.camera(true);
}
else if (dir === -1) {
log.info('Gamepad D-pad camera_backward');
if (this.cam.dir) {
this.cameraMoving = true;
yield this.cam.setAsync(true);
}
yield this.camera(true);
}
});
}
projectorDirection(dir) {
return __awaiter(this, void 0, void 0, function* () {
if (dir !== 0 && this.projectorMoving) {
log.info('Projector D-PAD blocked');
return;
}
if (dir === -1) {
log.info('Gamepad D-pad projector_forward');
if (!this.proj.dir) {
this.projectorMoving = true;
yield this.proj.setAsync(true);
}
yield this.projector(true);
}
else if (dir === 1) {
log.info('Gamepad D-pad projector_backward');
if (this.proj.dir) {
this.projectorMoving = true;
yield this.proj.setAsync(false);
}
yield this.projector(true);
}
});
}
sequence() {
return __awaiter(this, void 0, void 0, function* () {
if (!this.seq.isRunning()) {
this.seq.start();
}
else {
this.seq.cancel();
}
});
}
}
gamecontroller = new GameController();
module.exports = gamecontroller;
//# sourceMappingURL=gamecontroller.js.map

View File

@ -0,0 +1 @@
{"version":3,"file":"gamecontroller.js","sourceRoot":"","sources":["../../src/lib/ui/gamecontroller.ts"],"names":[],"mappings":"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"}

View File

@ -28,6 +28,16 @@ proj.set = function (dir, callback) {
proj.queue[obj.id] = obj; proj.queue[obj.id] = obj;
proj.lock = true; proj.lock = true;
}; };
proj.setAsync = async function (dir) {
return new Promise((resolve, reject) => {
return proj.set(dir, function (ms) {
setTimeout(reject, 10000);
return resolve(ms);
});
});
}
proj.move = function (callback) { proj.move = function (callback) {
'use strict'; 'use strict';
var obj; var obj;
@ -46,6 +56,16 @@ proj.move = function (callback) {
proj.queue[obj.id] = obj; proj.queue[obj.id] = obj;
proj.lock = true; proj.lock = true;
}; };
proj.moveAsync = async function () {
return new Promise((resolve, reject) => {
return proj.move(function (ms) {
setTimeout(reject, 10000);
return resolve(ms);
});
});
}
proj.end = function (c, id, ms) { proj.end = function (c, id, ms) {
'use strict'; 'use strict';
if (c === cfg.arduino.cmd.projector_forward) { if (c === cfg.arduino.cmd.projector_forward) {
@ -75,6 +95,8 @@ proj.end = function (c, id, ms) {
if (typeof proj.queue[id] !== 'undefined') { if (typeof proj.queue[id] !== 'undefined') {
if (typeof proj.queue[id].callback !== 'undefined') { if (typeof proj.queue[id].callback !== 'undefined') {
proj.queue[id].callback(ms); proj.queue[id].callback(ms);
} else {
log.info('NO PROJ CALLBACK')
} }
delete proj.queue[id]; delete proj.queue[id];
proj.lock = false; proj.lock = false;

View File

@ -21,6 +21,7 @@ class Sequence {
let timeStr; let timeStr;
//console.log(JSON.stringify(arg)) //console.log(JSON.stringify(arg))
if (arg.start) { if (arg.start) {
this.running = true;
if (typeof arg.loop !== 'undefined' && typeof arg.step !== 'undefined') { if (typeof arg.loop !== 'undefined' && typeof arg.step !== 'undefined') {
this.activeStep(arg.step); this.activeStep(arg.step);
log.info(`Step ${arg.step + 1}/${this.arr.length}, Loop ${arg.loop + 1}/${this.loops}`, 'SERIAL', true); log.info(`Step ${arg.step + 1}/${this.arr.length}, Loop ${arg.loop + 1}/${this.loops}`, 'SERIAL', true);
@ -33,6 +34,7 @@ class Sequence {
} }
} }
else if (arg.stop) { else if (arg.stop) {
this.running = false;
if (typeof arg.loop !== 'undefined' && typeof arg.step !== 'undefined') { if (typeof arg.loop !== 'undefined' && typeof arg.step !== 'undefined') {
//console.log(JSON.stringify(arg)) //console.log(JSON.stringify(arg))
this.progress(arg.step + 1, arg.loop); this.progress(arg.step + 1, arg.loop);
@ -218,9 +220,11 @@ class Sequence {
} }
cancel() { cancel() {
gui.spinner(true, `Cancelling sequence...`); gui.spinner(true, `Cancelling sequence...`);
this.running = false;
this.stop(); this.stop();
} }
isRunning() {
return this.running;
}
} }
seq = new Sequence(); seq = new Sequence();
module.exports = seq; module.exports = seq;

File diff suppressed because one or more lines are too long

4
app/package-lock.json generated
View File

@ -1,12 +1,12 @@
{ {
"name": "mcopy-app", "name": "mcopy-app",
"version": "1.8.150", "version": "1.8.151",
"lockfileVersion": 2, "lockfileVersion": 2,
"requires": true, "requires": true,
"packages": { "packages": {
"": { "": {
"name": "mcopy-app", "name": "mcopy-app",
"version": "1.8.109", "version": "1.8.150",
"hasInstallScript": true, "hasInstallScript": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {

View File

@ -1,6 +1,6 @@
{ {
"name": "mcopy-app", "name": "mcopy-app",
"version": "1.8.150", "version": "1.8.151",
"description": "GUI for the mcopy small gauge film optical printer platform", "description": "GUI for the mcopy small gauge film optical printer platform",
"main": "main.js", "main": "main.js",
"scripts": { "scripts": {

View File

@ -27,6 +27,7 @@ const timing = require('./lib/ui/timing.js');
const Mscript = require('./lib/mscript'); const Mscript = require('./lib/mscript');
const { delay } = require('./lib/delay'); const { delay } = require('./lib/delay');
const alertObj = require('./lib/ui/alert.js'); const alertObj = require('./lib/ui/alert.js');
const gamecontroller = require('./lib/ui/gamecontroller.js');
const { Log } = require('./lib/log'); const { Log } = require('./lib/log');
let log; let log;
@ -59,4 +60,5 @@ async function init () {
capper.init(); capper.init();
alertObj.init(); alertObj.init();
timing.init(); timing.init();
gamecontroller.init(seq, cmd, cam, proj);
}; };

View File

@ -0,0 +1,155 @@
let gamecontroller : GameController;
class GameController {
private seq : Sequence;
private cmd : any;
private cam : any;
private proj : any;
private pressed : boolean[];
private cameraMoving : boolean = false;
private projectorMoving : boolean = false;
constructor () {
}
public init (seq : Sequence, cmd : any, cam : any, proj : any) {
this.seq = seq;
this.cmd = cmd;
this.cam = cam;
this.proj = proj;
window.addEventListener('gamepadconnected', (e) => {
const gamepads = navigator.getGamepads();
if (gamepads.length > 0) {
console.dir(gamepads[0]);
this.pressed = gamepads[0].buttons.map((button: GamepadButton) => { return button.pressed; });
if (gamepads[0].id.indexOf("USB Gamepad") !== -1 && gamepads[0].buttons.length === 10) {
gui.notify('GAMEPAD CONNECTED', 'NES Controller');
} else {
gui.notify('GAMEPAD CONNECTED', 'Unknown');
}
}
this.handleController();
});
window.addEventListener('gamepaddisconnected', (e) => {
gui.notify('GAMEPAD DISCONNECTED', '');
});
}
handleController () {
const gamepads = navigator.getGamepads();
if (gamepads.length === 0) {
return;
}
const gamepad : Gamepad = gamepads[0];
if (gamepad.id.indexOf("USB Gamepad") !== -1 && gamepad.buttons.length === 10) {
this.handleNESController(gamepad);
}
requestAnimationFrame(this.handleController.bind(this));
}
handleNESController (gamepad : Gamepad) {
const leftStickX : number = gamepad.axes[0];
const leftStickY : number = gamepad.axes[1];
//log.info(leftStickX + ',' + leftStickY)
//select == 8
//start == 9
//A == 2
//B == 1
for (let i = 0; i < gamepad.buttons.length; i++) {
if (gamepad.buttons[i].pressed && !this.pressed[i]) {
log.info(`Button[${i}] pressed`);
if (i === 2) {
if (!this.cameraMoving) this.camera();
} else if (i === 1) {
if (!this.projectorMoving) this.projector();
} else if (i == 9) {
this.sequence();
}
}
}
this.pressed = gamepad.buttons.map((button: GamepadButton) => { return button.pressed; });
this.cameraDirection(leftStickX);
this.projectorDirection(leftStickY);
}
async camera (silent : boolean = false) {
const dir : string = this.cam.dir ? 'camera_forward' : 'camera_backward';
if (!silent) log.info(`Gamepad A ${dir}`);
this.cameraMoving = true;
await this.cam.moveAsync();
this.cameraMoving = false;
}
async projector (silent : boolean = false) {
const dir : string = this.cam.dir ? 'projector_forward' : 'projector_backward';
if (!silent) log.info(`Gamepad B ${dir}`);
this.projectorMoving = true;
await this.proj.moveAsync();
this.projectorMoving = false;
}
async cameraDirection (dir: number) {
if (dir !== 0 && this.cameraMoving) {
log.info('Camera D-PAD blocked')
return;
}
if (dir === 1) {
log.info('Gamepad D-pad camera_forward');
if (!this.cam.dir) {
this.cameraMoving = true;
await this.proj.setAsync(true);
}
await this.camera(true);
} else if (dir === -1) {
log.info('Gamepad D-pad camera_backward');
if (this.cam.dir) {
this.cameraMoving = true;
await this.cam.setAsync(true);
}
await this.camera(true);
}
}
async projectorDirection (dir : number) {
if (dir !== 0 && this.projectorMoving) {
log.info('Projector D-PAD blocked')
return;
}
if (dir === -1) {
log.info('Gamepad D-pad projector_forward');
if (!this.proj.dir) {
this.projectorMoving = true;
await this.proj.setAsync(true);
}
await this.projector(true);
} else if (dir === 1) {
log.info('Gamepad D-pad projector_backward');
if (this.proj.dir) {
this.projectorMoving = true;
await this.proj.setAsync(false);
}
await this.projector(true);
}
}
async sequence () {
if (!this.seq.isRunning()) {
this.seq.start();
} else {
this.seq.cancel();
}
}
}
gamecontroller = new GameController();
module.exports = gamecontroller;

View File

@ -49,6 +49,7 @@ class Sequence {
let timeStr; let timeStr;
//console.log(JSON.stringify(arg)) //console.log(JSON.stringify(arg))
if (arg.start) { if (arg.start) {
this.running = true;
if (typeof arg.loop !== 'undefined' && typeof arg.step !== 'undefined') { if (typeof arg.loop !== 'undefined' && typeof arg.step !== 'undefined') {
this.activeStep(arg.step); this.activeStep(arg.step);
log.info(`Step ${arg.step + 1}/${this.arr.length}, Loop ${arg.loop + 1}/${this.loops}`, 'SERIAL', true); log.info(`Step ${arg.step + 1}/${this.arr.length}, Loop ${arg.loop + 1}/${this.loops}`, 'SERIAL', true);
@ -58,6 +59,7 @@ class Sequence {
this.progress(0, 0); this.progress(0, 0);
} }
} else if (arg.stop) { } else if (arg.stop) {
this.running = false;
if (typeof arg.loop !== 'undefined' && typeof arg.step !== 'undefined') { if (typeof arg.loop !== 'undefined' && typeof arg.step !== 'undefined') {
//console.log(JSON.stringify(arg)) //console.log(JSON.stringify(arg))
this.progress(arg.step + 1, arg.loop); this.progress(arg.step + 1, arg.loop);
@ -257,9 +259,12 @@ class Sequence {
public cancel () { public cancel () {
gui.spinner(true, `Cancelling sequence...`); gui.spinner(true, `Cancelling sequence...`);
this.running = false;
this.stop(); this.stop();
} }
public isRunning () : boolean {
return this.running;
}
} }
seq = new Sequence(); seq = new Sequence();

View File

@ -1,5 +1,5 @@
{ {
"version": "1.8.150", "version": "1.8.151",
"ext_port": 1111, "ext_port": 1111,
"profiles": { "profiles": {
"mcopy": { "mcopy": {

2
notes/controller_test.js Normal file
View File

@ -0,0 +1,2 @@
var HID = require('node-hid');
console.log(HID.devices());

4
package-lock.json generated
View File

@ -1,12 +1,12 @@
{ {
"name": "mcopy", "name": "mcopy",
"version": "1.8.150", "version": "1.8.151",
"lockfileVersion": 2, "lockfileVersion": 2,
"requires": true, "requires": true,
"packages": { "packages": {
"": { "": {
"name": "mcopy", "name": "mcopy",
"version": "1.8.150", "version": "1.8.151",
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"alert": "file:app/lib/alert", "alert": "file:app/lib/alert",

View File

@ -1,6 +1,6 @@
{ {
"name": "mcopy", "name": "mcopy",
"version": "1.8.150", "version": "1.8.151",
"description": "Small gauge film optical printer platform", "description": "Small gauge film optical printer platform",
"main": "build.js", "main": "build.js",
"directories": { "directories": {

View File

@ -1,5 +1,5 @@
{ {
"version": "1.8.150", "version": "1.8.151",
"ext_port": 1111, "ext_port": 1111,
"profiles": { "profiles": {
"mcopy": { "mcopy": {

View File

@ -231,7 +231,7 @@ module debug () {
} }
} }
PART = "9pin_plug"; PART = "9pin_socket";
if (PART == "9pin_plug") { if (PART == "9pin_plug") {
rotate([180, 0, 0]) cpc_9pin_plug(); rotate([180, 0, 0]) cpc_9pin_plug();

View File

@ -565,6 +565,7 @@ module slide_rail (pos = [0, 0, 0], side = "A") {
BoltSlotY = 1.5; BoltSlotY = 1.5;
BoltSlotOffsetY = side == "A" ? BoltSlotY : -BoltSlotY; BoltSlotOffsetY = side == "A" ? BoltSlotY : -BoltSlotY;
BoltsOffsetY = side == "A" ? -1 / 2 : 1 / 2; BoltsOffsetY = side == "A" ? -1 / 2 : 1 / 2;
NutVoidY = side == "A" ? -4.5 : 4.5;
translate(pos) { translate(pos) {
difference() { difference() {
cube([7, 9, BodyZ - 16], center = true); cube([7, 9, BodyZ - 16], center = true);
@ -574,6 +575,7 @@ module slide_rail (pos = [0, 0, 0], side = "A") {
slide_rail_bolt_slot([0, BoltsOffsetY, SlideRailBoltSpacingZ / 2], [0, 90, 0], BoltSlotY, BoltSlotOffsetY); slide_rail_bolt_slot([0, BoltsOffsetY, SlideRailBoltSpacingZ / 2], [0, 90, 0], BoltSlotY, BoltSlotOffsetY);
slide_rail_bolt_slot([0, BoltsOffsetY, -SlideRailBoltSpacingZ / 2], [0, 90, 0], BoltSlotY, BoltSlotOffsetY); slide_rail_bolt_slot([0, BoltsOffsetY, -SlideRailBoltSpacingZ / 2], [0, 90, 0], BoltSlotY, BoltSlotOffsetY);
} }
translate([0, NutVoidY, ((BodyZ - 16) / 2) - (3 / 2) + 0.01]) cube([7 + 1, 7 , 3], center = true);
} }
} }
} }
@ -724,12 +726,12 @@ module front_block (pos = [0, 0, 0], rot = [0, 0, 0]) {
//for pegs //for pegs
translate([12.25, 0, -1.75]) { translate([12.25, 0, -1.75]) {
translate([3.5, 0, 0]) rounded_cube([33.4, 31.4, 4], d = 3, center = true, $fn = 30); translate([3.5, 0, 0]) rounded_cube([33.6, 31.6, 4], d = 3, center = true, $fn = 30);
translate([-3, 12, -2]) { translate([-5, 12, -2]) {
cylinder(r = R(2.75), h = 20, center = true, $fn = 40); cylinder(r = R(2.75), h = 20, center = true, $fn = 40);
translate([0, 0, 7]) m2_5_nut(4); translate([0, 0, 7]) m2_5_nut(4);
} }
translate([-3, -12, -2]) { translate([-5, -12, -2]) {
cylinder(r = R(2.75), h = 20, center = true, $fn = 40); cylinder(r = R(2.75), h = 20, center = true, $fn = 40);
translate([0, 0, 7]) m2_5_nut(4); translate([0, 0, 7]) m2_5_nut(4);
} }
@ -860,7 +862,7 @@ module debug () {
} }
} }
PART="front_block_16mm"; PART="front_block_16mmx";
if (PART == "front_plate") { if (PART == "front_plate") {
//1 //1