Mscript update #1

Merged
sixteenmillimeter merged 21 commits from mscript into master 2018-06-17 03:25:21 +00:00
18 changed files with 3206 additions and 2613 deletions

View File

@ -4,7 +4,7 @@
#build dmg for mac install #build dmg for mac install
sleep 5s sleep 5s
mkdir ../dist/installers mkdir ../dist/installers
./node_modules/.bin/electron-installer-dmg ../dist/mcopy-darwin-x64/mcopy.app mcopy --out=../dist/installers --icon=assets/icons/icon.icns --overwrite ./node_modules/.bin/electron-installer-dmg ../dist/mcopy-app-darwin-x64/mcopy-app.app mcopy-app --out=../dist/installers --icon=assets/icons/icon.icns --overwrite
# Path to the icon file that will be the app icon in the DMG window. # Path to the icon file that will be the app icon in the DMG window.
# --icon-size=<px> How big to make the icon for the app in the DMG. [Default: `80`]. # --icon-size=<px> How big to make the icon for the app in the DMG. [Default: `80`].
# --background=<path> Path to a PNG image to use as the background of the DMG. # --background=<path> Path to a PNG image to use as the background of the DMG.

8
app/docs.sh Normal file
View File

@ -0,0 +1,8 @@
#!/bin/bash
libs="./lib/*"
for l in $libs
do
echo "Generating documentation for $l"
./node_modules/.bin/jsdoc2md $l/index.js > $l/Readme.md
done

View File

@ -2494,7 +2494,7 @@ const cmd = require('./lib/ui/cmd.js');
const log = require('./lib/ui/log.js'); const log = require('./lib/ui/log.js');
const devices = require('./lib/ui/devices.js'); const devices = require('./lib/ui/devices.js');
const mse = require('./lib/ui/mscript.js'); const mse = require('./lib/ui/mscript.js');
const mscript = require('./lib/mscript'); const Mscript = require('./lib/mscript');

15
app/lib/exec/Readme.md Normal file
View File

@ -0,0 +1,15 @@
<a name="exec"></a>
## exec(cmd, arg, opts) ⇒ <code>Promise.&lt;{stdout: string, stderr: stderr}&gt;</code>
Promisified child_process.exec
**Kind**: global function
| Param | Type | Description |
| --- | --- | --- |
| cmd | | |
| arg | | |
| opts | | See child_process.exec node docs |
| opts.stdout | <code>stream.Writable</code> | If defined, child process stdout will be piped to it. |
| opts.stderr | <code>stream.Writable</code> | If defined, child process stderr will be piped to it. |

179
app/lib/mscript/Readme.md Normal file
View File

@ -0,0 +1,179 @@
<a name="module_lib/mscript"></a>
## lib/mscript
* [lib/mscript](#module_lib/mscript)
* [~Mscript](#module_lib/mscript..Mscript)
* [.clear()](#module_lib/mscript..Mscript+clear)
* [.interpret()](#module_lib/mscript..Mscript+interpret)
* [.basic_cmd()](#module_lib/mscript..Mscript+basic_cmd)
* [.new_loop()](#module_lib/mscript..Mscript+new_loop)
* [.end_loop()](#module_lib/mscript..Mscript+end_loop)
* [.move_cam()](#module_lib/mscript..Mscript+move_cam)
* [.move_proj()](#module_lib/mscript..Mscript+move_proj)
* [.set_state()](#module_lib/mscript..Mscript+set_state)
* [.last_loop()](#module_lib/mscript..Mscript+last_loop)
* [.parent_loop()](#module_lib/mscript..Mscript+parent_loop)
* [.loop_count()](#module_lib/mscript..Mscript+loop_count)
* [.fade()](#module_lib/mscript..Mscript+fade)
* [.fade_count()](#module_lib/mscript..Mscript+fade_count)
* [.fade_start()](#module_lib/mscript..Mscript+fade_start)
* [.fade_end()](#module_lib/mscript..Mscript+fade_end)
* [.update()](#module_lib/mscript..Mscript+update)
* [.str_to_arr()](#module_lib/mscript..Mscript+str_to_arr)
* [.light_to_arr()](#module_lib/mscript..Mscript+light_to_arr)
* [.light_state()](#module_lib/mscript..Mscript+light_state)
* [.fail()](#module_lib/mscript..Mscript+fail)
<a name="module_lib/mscript..Mscript"></a>
### lib/mscript~Mscript
class Mscript
**Kind**: inner class of [<code>lib/mscript</code>](#module_lib/mscript)
* [~Mscript](#module_lib/mscript..Mscript)
* [.clear()](#module_lib/mscript..Mscript+clear)
* [.interpret()](#module_lib/mscript..Mscript+interpret)
* [.basic_cmd()](#module_lib/mscript..Mscript+basic_cmd)
* [.new_loop()](#module_lib/mscript..Mscript+new_loop)
* [.end_loop()](#module_lib/mscript..Mscript+end_loop)
* [.move_cam()](#module_lib/mscript..Mscript+move_cam)
* [.move_proj()](#module_lib/mscript..Mscript+move_proj)
* [.set_state()](#module_lib/mscript..Mscript+set_state)
* [.last_loop()](#module_lib/mscript..Mscript+last_loop)
* [.parent_loop()](#module_lib/mscript..Mscript+parent_loop)
* [.loop_count()](#module_lib/mscript..Mscript+loop_count)
* [.fade()](#module_lib/mscript..Mscript+fade)
* [.fade_count()](#module_lib/mscript..Mscript+fade_count)
* [.fade_start()](#module_lib/mscript..Mscript+fade_start)
* [.fade_end()](#module_lib/mscript..Mscript+fade_end)
* [.update()](#module_lib/mscript..Mscript+update)
* [.str_to_arr()](#module_lib/mscript..Mscript+str_to_arr)
* [.light_to_arr()](#module_lib/mscript..Mscript+light_to_arr)
* [.light_state()](#module_lib/mscript..Mscript+light_state)
* [.fail()](#module_lib/mscript..Mscript+fail)
<a name="module_lib/mscript..Mscript+clear"></a>
#### mscript.clear()
Clear the state of the script
**Kind**: instance method of [<code>Mscript</code>](#module_lib/mscript..Mscript)
<a name="module_lib/mscript..Mscript+interpret"></a>
#### mscript.interpret()
Main function, accepts multi-line string, parses into lines
and interprets the instructions from the text. Returns an array
of steps to be fed into the mcopy.
**Kind**: instance method of [<code>Mscript</code>](#module_lib/mscript..Mscript)
<a name="module_lib/mscript..Mscript+basic_cmd"></a>
#### mscript.basic_cmd()
Apply a basic two character command
**Kind**: instance method of [<code>Mscript</code>](#module_lib/mscript..Mscript)
<a name="module_lib/mscript..Mscript+new_loop"></a>
#### mscript.new_loop()
Start a new loop
**Kind**: instance method of [<code>Mscript</code>](#module_lib/mscript..Mscript)
<a name="module_lib/mscript..Mscript+end_loop"></a>
#### mscript.end_loop()
Close the most recent loop
**Kind**: instance method of [<code>Mscript</code>](#module_lib/mscript..Mscript)
<a name="module_lib/mscript..Mscript+move_cam"></a>
#### mscript.move_cam()
Move camera to explicitly-defined frame
**Kind**: instance method of [<code>Mscript</code>](#module_lib/mscript..Mscript)
<a name="module_lib/mscript..Mscript+move_proj"></a>
#### mscript.move_proj()
Move projector to explicitly-defined frame
**Kind**: instance method of [<code>Mscript</code>](#module_lib/mscript..Mscript)
<a name="module_lib/mscript..Mscript+set_state"></a>
#### mscript.set_state()
Set the state of either the cam or projector
**Kind**: instance method of [<code>Mscript</code>](#module_lib/mscript..Mscript)
<a name="module_lib/mscript..Mscript+last_loop"></a>
#### mscript.last_loop()
Return the last loop
**Kind**: instance method of [<code>Mscript</code>](#module_lib/mscript..Mscript)
<a name="module_lib/mscript..Mscript+parent_loop"></a>
#### mscript.parent_loop()
Return the second-last loop
**Kind**: instance method of [<code>Mscript</code>](#module_lib/mscript..Mscript)
<a name="module_lib/mscript..Mscript+loop_count"></a>
#### mscript.loop_count()
Extract the loop count integer from a LOOP cmd
**Kind**: instance method of [<code>Mscript</code>](#module_lib/mscript..Mscript)
<a name="module_lib/mscript..Mscript+fade"></a>
#### mscript.fade()
Execute a fade of frame length, from color to another color
**Kind**: instance method of [<code>Mscript</code>](#module_lib/mscript..Mscript)
<a name="module_lib/mscript..Mscript+fade_count"></a>
#### mscript.fade_count()
Extract the fade length integer from a FADE cmd
**Kind**: instance method of [<code>Mscript</code>](#module_lib/mscript..Mscript)
<a name="module_lib/mscript..Mscript+fade_start"></a>
#### mscript.fade_start()
Extract the start color from a string
**Kind**: instance method of [<code>Mscript</code>](#module_lib/mscript..Mscript)
<a name="module_lib/mscript..Mscript+fade_end"></a>
#### mscript.fade_end()
Extract the end color from a string
**Kind**: instance method of [<code>Mscript</code>](#module_lib/mscript..Mscript)
<a name="module_lib/mscript..Mscript+update"></a>
#### mscript.update()
Increase the state of a specific object, such as the camera/projector,
by the value defined in val
**Kind**: instance method of [<code>Mscript</code>](#module_lib/mscript..Mscript)
<a name="module_lib/mscript..Mscript+str_to_arr"></a>
#### mscript.str_to_arr()
Split string on command, extract any integers from string
**Kind**: instance method of [<code>Mscript</code>](#module_lib/mscript..Mscript)
<a name="module_lib/mscript..Mscript+light_to_arr"></a>
#### mscript.light_to_arr()
Split a string on a command to extract data for light array
**Kind**: instance method of [<code>Mscript</code>](#module_lib/mscript..Mscript)
<a name="module_lib/mscript..Mscript+light_state"></a>
#### mscript.light_state()
Split a string to extract an rgb color value
**Kind**: instance method of [<code>Mscript</code>](#module_lib/mscript..Mscript)
<a name="module_lib/mscript..Mscript+fail"></a>
#### mscript.fail()
Throw an error with specific message
**Kind**: instance method of [<code>Mscript</code>](#module_lib/mscript..Mscript)

5
app/lib/mscript/TODO.md Normal file
View File

@ -0,0 +1,5 @@
# TODO - mscript
* Add variables and simple evaluation
* Add "Fade" feature
* Add "Light" feature

View File

@ -1,28 +1,10 @@
var fs, 'use strict';
input;
var mscript = {}; /** @module lib/mscript */
mscript.arg = function arg (shrt, lng) { const BLACK = '0,0,0';
'use strict'; const WHITE = '255,255,255';
if (process.argv.indexOf(shrt) !== -1 || const CMD = [
process.argv.indexOf(lng) !== -1) {
return true;
}
return false;
};
mscript.arg_pos = function arg_pos (shrt, lng) {
'use strict';
var pos = -1;
pos = process.argv.indexOf(shrt);
if (pos === -1) {
pos = process.argv.indexOf(lng);
}
return pos;
};
mscript.black = '0,0,0';
mscript.cmd = [
'CF', 'CF',
'PF', 'PF',
'BF', 'BF',
@ -30,515 +12,446 @@ mscript.cmd = [
'PB', 'PB',
'BB' 'BB'
]; ];
mscript.alts = { const ALTS = {
'CF' : ['CAMERA FORWARD', 'CAM FORWARD'], 'CF' : ['CAMERA FORWARD', 'CAM FORWARD'],
'PF' : ['PROJECTOR FORWARD', 'PROJ FORWARD'], 'PF' : ['PROJECTOR FORWARD', 'PROJ FORWARD'],
'BF': ['BLACK FORWARD'], 'BF' : ['BLACK FORWARD', 'BLACK', 'BLANK FORWARD', 'BLANK'],
'CB' : ['CAMERA BACKWARD', 'CAM BACKWARD', 'CAMERA BACK', 'CAM BACK'], 'CB' : ['CAMERA BACKWARD', 'CAM BACKWARD', 'CAMERA BACK', 'CAM BACK'],
'PB' : ['PROJECTOR FORWARD', 'PROJ FORWARD', 'PROJECTOR BACK', 'PROJ BACK'], 'PB' : ['PROJECTOR FORWARD', 'PROJ FORWARD', 'PROJECTOR BACK', 'PROJ BACK'],
'BB' : ['BLACK BACKWARD', 'BLACK BACK'], 'BB' : ['BLACK BACKWARD', 'BLACK BACK', 'BLANK BACK'],
'L ' : ['LIGHT', 'COLOR', 'LAMP'] 'L ' : ['LIGHT', 'COLOR', 'LAMP'],
'F ' : ['FADE']
}; };
mscript.state = {};
mscript.state_clear = function state_clear () { /** class Mscript */
'use strict'; class Mscript {
mscript.state = { constructor () {
cam : 0, this.output = {};
proj : 0, }
color : '', /**
loops : [], * Clear the state of the script
rec : -1 */
}; clear () {
}; this.cam = 0;
mscript.alts_unique = function alts_unique () { this.proj = 0;
'use strict'; this.color = '';
var ids = Object.keys(mscript.alts), this.loops = [];
all = []; this.rec = -1;
for (var i = 0; i < ids.length; i++) {
if (all.indexOf(ids[i]) === -1) { this.two = '';
all.push(ids[i]); this.arr = [];
} else { this.light = [];
mscript.fail("Can't compile"); this.target = 0; //move to target using CAM # or PROJ #
this.dist = 0;
this.output = {};
}
/**
* Main function, accepts multi-line string, parses into lines
* and interprets the instructions from the text. Returns an array
* of steps to be fed into the mcopy.
*/
interpret (text, callback) {
this.clear()
if (typeof text === 'undefined') {
return this.fail('No input');
}
//split string into lines, each containing a command
let lines = text.split('\n');
for (let line of lines) {
line = line.replace(/\t+/g, ""); //strip tabs
line = line.trim(); //remove excess whitespace before and after command
line = line.toUpperCase();
this.two = line.substring(0, 2);
if (CMD.indexOf(this.two) !== -1) {
this.basic_cmd(line);
} else if (line.substring(0, 4) === 'LOOP') {
this.new_loop(line);
} else if (line.substring(0, 2) === 'L ') {
this.light_state(line);
} else if (line.substring(0, 2) === 'F ') {
this.new_loop(line, true);
} else if (line.substring(0, 3) === 'END') {
this.end_loop(line);
} else if (line.substring(0, 3) === 'CAM') { //directly go to that frame (black?)
this.move_cam(line);
} else if (line.substring(0, 4) === 'PROJ') { //directly go to that frame
this.move_proj(line);
} else if (line.substring(0, 3) === 'SET') { //set that state
this.set_state(line);
} else if (line.substring(0, 1) === '#' || line.substring(0, 2) === '//') {
//comments
//ignore while parsing
}
}
this.output.success = true;
this.output.arr = this.arr; //all instructions
this.output.light = this.light; //all light instructions
this.output.cam = this.cam;
this.output.proj = this.proj;
if (typeof callback !== 'undefined') {
//should only be invoked by running mscript.tests()
callback(this.output);
} }
} }
}; /**
mscript.interpret = function interpret (text, callback) { * Apply a basic two character command
'use strict'; */
mscript.state_clear(); basic_cmd (line) {
if (typeof text === 'undefined') { if (this.rec !== -1) {
mscript.fail('No input'); //hold generated arr in state loop array
this.loops[this.rec].arr
.push.apply(this.loops[this.rec].arr,
this.str_to_arr(line,
this.two));
this.loops[this.rec].light
.push.apply(this.loops[this.rec].light,
this.light_to_arr(line,
this.two));
} else {
this.arr.push.apply(this.arr, this.str_to_arr(line, this.two));
this.light.push.apply(this.light, this.light_to_arr(line, this.two))
}
} }
var lines = text.split('\n'), /**
two = '', * Start a new loop
arr = [], */
light = [], new_loop (line, fade) {
target = 0, this.rec++;
dist = 0, //? this.loops[this.rec] = {
output = {}; arr : [],
for (var i = 0; i < lines.length; i++) { light : [],
lines[i] = lines[i].replace(/\t+/g, ""); //strip tabs cam : 0,
lines[i] = lines[i].trim(); //remove excess whitespace before and after command proj : 0,
two = lines[i].substring(0, 2); cmd : line + ''
if (mscript.cmd.indexOf(two) !== -1) { };
if (fade) {
this.fade(line);
}
}
/**
* Close the most recent loop
*/
end_loop (line) {
let light_arr;
let start;
let end;
let len;
if (mscript.state.loops.length > 0) { for (let x = 0; x < this.loop_count(this.loops[this.rec].cmd); x++) {
//hold generated arr in state loop array light_arr = this.loops[this.rec].light;
mscript.state.loops[mscript.state.rec].arr if (this.loops[this.rec].fade) {
.push.apply(mscript.state.loops[mscript.state.rec].arr, start = this.loops[this.rec].start;
mscript.str_to_arr(lines[i], end = this.loops[this.rec].end;
two)); len = this.loops[this.rec].fade_len;
mscript.state.loops[mscript.state.rec].light light_arr = light_arr.map(l => {
.push.apply(mscript.state.loops[mscript.state.rec].light, return this.fade_rgb(start, end, len, x);
mscript.light_to_arr(lines[i], })
two));
} else {
arr.push.apply(arr, mscript.str_to_arr(lines[i], two));
light.push.apply(light, mscript.light_to_arr(lines[i], two))
} }
if (this.rec === 0) {
this.arr.push.apply(this.arr, this.loops[this.rec].arr);
this.light.push.apply(this.light, light_arr);
} else if (this.rec >= 1) {
this.loops[this.rec - 1].arr
.push.apply(this.loops[this.rec - 1].arr,
this.loops[this.rec].arr);
} else if (lines[i].substring(0, 4) === 'LOOP') { this.loops[this.rec - 1].light
mscript.state.rec++; .push.apply(this.loops[this.rec - 1].light,
mscript.state.loops[mscript.state.rec] = { light_arr);
arr : [],
light : [],
cam : 0,
proj : 0,
cmd : lines[i] + ''
};
} else if (lines[i].substring(0, 2) === 'L ') {
mscript.light_state(lines[i]);
} else if (lines[i].substring(0, 3) === 'END') {
for (var x = 0; x < mscript.loop_count(mscript.state.loops[mscript.state.rec].cmd); x++) {
if (mscript.state.rec === 0) {
arr.push.apply(arr, mscript.state.loops[mscript.state.rec].arr);
light.push.apply(light, mscript.state.loops[mscript.state.rec].light);
} else if (mscript.state.rec >= 1) {
mscript.state.loops[mscript.state.rec - 1].arr
.push.apply(mscript.state.loops[mscript.state.rec - 1].arr,
mscript.state.loops[mscript.state.rec].arr);
mscript.state.loops[mscript.state.rec - 1].light
.push.apply(mscript.state.loops[mscript.state.rec - 1].light,
mscript.state.loops[mscript.state.rec].light);
}
} }
mscript.state_update('END', mscript.loop_count(mscript.state.loops[mscript.state.rec].cmd)); }
delete mscript.state.loops[mscript.state.rec]; this.update('END', this.loop_count(this.loops[this.rec].cmd));
mscript.state.rec--; delete this.loops[this.rec];
} else if (lines[i].substring(0, 3) === 'CAM') { //directly go to that frame (black?) this.rec--;
target = parseInt(lines[i].split('CAM ')[1]); }
if (mscript.state.loops.length > 0) { /**
if (target > mscript.state.cam) { * Move camera to explicitly-defined frame
dist = target - mscript.state.cam; */
for (var x = 0; x < dist; x++) { move_cam (line) {
mscript.state.loops[mscript.state.rec].arr.push('BF'); this.target = parseInt(line.split('CAM ')[1]);
mscript.state.loops[mscript.state.rec].light.push(mscript.black); if (this.rec !== -1) {
mscript.state_update('BF'); if (this.target > this.cam) {
} this.dist = this.target - this.cam;
} else { for (let x = 0; x < this.dist; x++) {
dist = mscript.state.cam - target; this.loops[this.rec].arr.push('BF');
for (var x = 0; x < dist; x++) { this.loops[this.rec].light.push(BLACK);
mscript.state.loops[mscript.state.rec].arr.push('BB'); this.update('BF');
mscript.state.loops[mscript.state.rec].light.push(mscript.black);
mscript.state_update('BB');
}
} }
} else { } else {
if (target > mscript.state.cam) { this.dist = this.cam - this.target;
dist = target - mscript.state.cam; for (let x = 0; x < this.dist; x++) {
for (var x = 0; x < dist; x++) { this.loops[this.rec].arr.push('BB');
arr.push('BF'); this.loops[this.rec].light.push(BLACK);
light.push(mscript.black); this.update('BB');
mscript.state_update('BF');
}
} else {
dist = mscript.state.cam - target;
for (var x = 0; x < dist; x++) {
arr.push('BB');
light.push(mscript.black);
mscript.state_update('BB');
}
} }
} }
} else if (lines[i].substring(0, 4) === 'PROJ') { //directly go to that frame } else {
target = parseInt(lines[i].split('PROJ ')[1]); if (target > this.cam) {
if (mscript.state.loops.length > 0) { this.dist = this.target - this.cam;
if (target > mscript.state.proj) { for (let x = 0; x < this.dist; x++) {
dist = target - mscript.state.proj; this.arr.push('BF');
for (var x = 0; x < dist; x++) { this.light.push(BLACK);
mscript.state.loops[mscript.state.rec].arr.push('PF'); this.update('BF');
mscript.state.loops[mscript.state.rec].light.push('');
mscript.state_update('PF');
}
} else {
dist = mscript.state.proj - target;
for (var x = 0; x < dist; x++) {
mscript.state.loops[mscript.state.rec].arr.push('PB');
mscript.state.loops[mscript.state.rec].light.push('');
mscript.state_update('PB');
}
} }
} else { } else {
if (target > mscript.state.proj) { this.dist = this.cam - this.target;
dist = target - mscript.state.proj; for (let x = 0; x < this.dist; x++) {
for (var x = 0; x < dist; x++) { this.arr.push('BB');
arr.push('PF'); this.light.push(BLACK);
light.push(''); this.update('BB');
mscript.state_update('PF');
}
} else {
dist = mscript.state.proj - target;
for (var x = 0; x < dist; x++) {
arr.push('PB');
light.push('');
mscript.state_update('PB');
}
} }
} }
} else if (lines[i].substring(0, 3) === 'SET') { //set that state
if (lines[i].substring(0, 7) === 'SET CAM') {
mscript.state.cam = parseInt(lines[i].split('SET CAM')[1]);
} else if (lines[i].substring(0, 8) === 'SET PROJ') {
mscript.state.proj = parseInt(lines[i].split('SET PROJ')[1]);
}
} else if (lines[i].substring(0, 1) === '#' || lines[i].substring(0, 2) === '//') {
//comments
//ignore while parsing
} }
} }
output.success = true; /**
output.arr = arr; * Move projector to explicitly-defined frame
output.light = light; */
output.cam = mscript.state.cam; move_proj (line) {
output.proj = mscript.state.proj; this.target = parseInt(line.split('PROJ ')[1]);
if (typeof callback !== 'undefined') { if (this.rec !== -1) {
//should only be invoked by running mscript.tests() if (this.target > this.proj) {
callback(output); this.dist = this.target - this.proj;
} else { for (let x = 0; x < this.dist; x++) {
return mscript.output(output); this.loops[this.rec].arr.push('PF');
} this.loops[this.rec].light.push('');
}; this.update('PF');
mscript.last_loop = function last_loop () { }
'use strict'; } else {
return mscript.state.loops[mscript.state.loops.length - 1]; this.dist = this.proj - this.target;
}; for (let x = 0; x < this.dist; x++) {
mscript.parent_loop = function parent_loop () { this.loops[this.rec].arr.push('PB');
'use script'; this.loops[this.rec].light.push('');
return mscript.state.loops[mscript.state.loops.length - 2]; this.update('PB');
}; }
mscript.state_update = function state_update (cmd, val) { }
'use strict'; } else {
if (cmd === 'END') { if (this.target > this.proj) {
for (var i = 0; i < val; i++) { this.dist = this.target - this.proj;
if (mscript.state.rec === 0) { for (let x = 0; x < this.dist; x++) {
mscript.state.cam += mscript.state.loops[mscript.state.rec].cam; this.arr.push('PF');
mscript.state.proj += mscript.state.loops[mscript.state.rec].proj; this.light.push('');
} else if (mscript.state.rec >= 1) { this.update('PF');
mscript.state.loops[mscript.state.rec - 1].cam += mscript.state.loops[mscript.state.rec].cam; }
mscript.state.loops[mscript.state.rec - 1].proj += mscript.state.loops[mscript.state.rec].proj; } else {
this.dist = this.proj - this.target;
for (let x = 0; x < this.dist; x++) {
this.arr.push('PB');
this.light.push('');
this.update('PB');
}
} }
} }
} else if (cmd === 'CF') {
if (mscript.state.loops.length < 1) {
mscript.state.cam++;
} else {
mscript.state.loops[mscript.state.rec].cam++;
}
} else if (cmd === 'CB') {
if (mscript.state.loops.length < 1) {
mscript.state.cam--;
} else {
mscript.state.loops[mscript.state.rec].cam--;
}
} else if (cmd === 'PF') {
if (mscript.state.loops.length < 1) {
mscript.state.proj++;
} else {
mscript.state.loops[mscript.state.rec].proj++;
}
} else if (cmd === 'PB') {
if (mscript.state.loops.length < 1) {
mscript.state.proj--;
} else {
mscript.state.loops[mscript.state.rec].proj--;
}
} else if (cmd === 'BF') {
if (mscript.state.loops.length < 1) {
mscript.state.cam++;
} else {
mscript.state.loops[mscript.state.rec].cam++;
}
} else if (cmd === 'BB') {
if (mscript.state.loops.length < 1) {
mscript.state.cam--;
} else {
mscript.state.loops[mscript.state.rec].cam++;
}
} else if (cmd === 'L ') {
} }
}; /**
mscript.str_to_arr = function str_to_arr (str, cmd) { * Set the state of either the cam or projector
'use strict'; */
var cnt = str.split(cmd), set_state (line) {
c = parseInt(cnt[1]), if (line.substring(0, 7) === 'SET CAM') {
arr = []; this.cam = parseInt(line.split('SET CAM')[1]);
if (cnt[1] === '') { } else if (line.substring(0, 8) === 'SET PROJ') {
c = 1; this.proj = parseInt(line.split('SET PROJ')[1]);
} else {
c = parseInt(cnt[1]);
}
for (var i = 0; i < c; i++) {
arr.push(cmd);
mscript.state_update(cmd);
}
return arr;
};
mscript.light_state = function light_state (str) {
'use strict';
//add parsers for other color spaces
var color = str.replace('L ', '').trim();
mscript.state.color = color;
};
mscript.light_to_arr = function light_to_arr (str, cmd) {
var cnt = str.split(cmd),
c = parseInt(cnt[1]),
arr = [];
if (cnt[1] === '') {
c = 1;
} else {
c = parseInt(cnt[1]);
}
for (var i = 0; i < c; i++) {
if (cmd === 'CF'
|| cmd === 'CB') {
arr.push(mscript.state.color);
} else if (cmd === 'BF'
|| cmd === 'BB') {
arr.push(mscript.black);
} else {
arr.push('');
} }
} }
return arr; /**
}; * Return the last loop
mscript.loop_count = function loop_count (str) { */
'use strict'; last_loop () {
return parseInt(str.split('LOOP ')[1]); return this.loops[this.loops.length - 1];
};
mscript.fail = function fail (reason) {
'use strict';
console.error(JSON.stringify({success: false, error: true, msg : reason}));
if (process) process.exit();
};
mscript.output = function output (data) {
'use strict';
var json = true; //default
if (mscript.arg('-j', '--json')) {
json = true;
} }
/**
if (mscript.arg('-t', '--text')) { * Return the second-last loop
json = false; */
parent_loop () {
return this.loops[this.loops.length - 2];
} }
/**
* Extract the loop count integer from a LOOP cmd
*/
loop_count (str) {
return parseInt(str.split(' ')[1]);
}
/**
* Execute a fade of frame length, from color to another color
*/
fade (line) {
let len = this.fade_count(line);
let start = this.fade_start(line);
let end = this.fade_end(line);
this.loops[this.rec].start = start;
this.loops[this.rec].end = end;
this.loops[this.rec].fade = true;
this.loops[this.rec].fade_count = 0;
this.loops[this.rec].fade_len = len;
}
/**
* Extract the fade length integer from a FADE cmd
*/
fade_count (str) {
return parseInt(str.split(' ')[1]);
}
/**
* Extract the start color from a string
*/
fade_start (str) {
let color = str.split(' ')[2];
return this.rgb(color.trim())
}
/**
* Extract the end color from a string
*/
fade_end (str) {
let color = str.split(' ')[3];
return this.rgb(color.trim())
}
fade_rgb (start, end, len, x) {
let cur = [];
let diff;
for (let i = 0; i < 3; i++) {
if (x === len - 1) {
cur[i] = end[i];
} else if (start[i] >= end[i]) {
diff = start[i] - end[i];
cur[i] = start[i] - Math.round((diff / (len - 1)) * x);
} else {
diff = end[i] - start[i];
cur[i] = start[i] + Math.round((diff / (len - 1)) * x);
}
}
return this.rgb_str(cur);
}
rgb (str) {
let rgb = str.split(',');
return rgb.map( char => {
return parseInt(char);
})
}
rgb_str (arr) {
return arr.join(',');
}
/**
* Increase the state of a specific object, such as the camera/projector,
* by the value defined in val
*/
update (cmd, val = 1) {
if (cmd === 'END') {
//I don't understand this loop
for (let i = 0; i < val; i++) {
if (this.rec === 0) {
this.cam += this.loops[this.rec].cam;
this.proj += this.loops[this.rec].proj;
} else if (this.rec >= 1) {
this.loops[this.rec - 1].cam += this.loops[this.rec].cam;
this.loops[this.rec - 1].proj += this.loops[this.rec].proj;
}
}
} else if (cmd === 'CF') {
if (this.rec === -1) {
this.cam += val;
} else {
this.loops[this.rec].cam += val;
}
} else if (cmd === 'CB') {
if (this.rec === -1) {
this.cam -= val;
} else {
this.loops[this.rec].cam--;
}
} else if (cmd === 'PF') {
if (this.rec === -1) {
this.proj += val;
} else {
this.loops[this.rec].proj += val;
}
} else if (cmd === 'PB') {
if (this.rec === -1) {
this.proj -= val;
} else {
this.loops[this.rec].proj--;
}
} else if (cmd === 'BF') {
if (this.rec === -1) {
this.cam += val;
} else {
this.loops[this.rec].cam += val;
}
} else if (cmd === 'BB') {
if (this.rec === -1) {
this.cam -= val;
} else {
this.loops[this.rec].cam -= val;
}
} else if (cmd === 'L ') {
if (json) {
console.log(JSON.stringify(data));
} else {
var ids = Object.keys(data);
for (var i = 0; i < ids.length; i++) {
console.log(ids[i] + ': ' + data[ids[i]]);
} }
} }
}; /**
mscript.init = function init () { * Split string on command, extract any integers from string
'use strict'; */
if (mscript.arg('-t', '--tests')) { str_to_arr (str, cmd) {
return mscript.tests(); const cnt = str.split(cmd);
let c = parseInt(cnt[1]);
let arr = [];
if (cnt[1] === '') {
c = 1;
} else {
c = parseInt(cnt[1]);
}
arr = new Array(c).fill(cmd);
this.update(cmd, c);
return arr;
}
/**
* Split a string on a command to extract data for light array
*/
light_to_arr (str, cmd) {
const cnt = str.split(cmd);
let c = parseInt(cnt[1]);
let arr = [];
if (cnt[1] === '') {
c = 1;
} else {
c = parseInt(cnt[1]);
}
for (var i = 0; i < c; i++) {
if (cmd === 'CF'
|| cmd === 'CB') {
arr.push(this.color);
} else if (cmd === 'BF'
|| cmd === 'BB') {
arr.push(BLACK);
} else {
arr.push('');
}
}
return arr;
}
/**
* Split a string to extract an rgb color value
*/
light_state (str) {
//add parsers for other color spaces
const color = str.replace('L ', '').trim();
this.color = color;
} }
if (mscript.arg('-v', '--verbose')) { /**
console.time('mscript'); * Throw an error with specific message
*/
fail (msg) {
throw new Error(msg);
} }
if (mscript.arg('-c', '--cam')) {
mscript.state.cam = parseInt(process.argv[mscript.arg_pos('-c', '--cam') + 1]);
}
if (mscript.arg('-p', '--proj')) {
mscript.state.proj = parseInt(process.argv[mscript.arg_pos('-p', '--proj') + 1]);
}
if (mscript.arg('-f', '--file')) {
input = process.argv[mscript.arg_pos('-f', '--file') + 1];
mscript.interpret(fs.readFileSync(input, 'utf8'));
} else {
mscript.interpret(input);
}
if (mscript.arg('-v', '--verbose')) {
console.timeEnd('mscript');
}
};
mscript.tests = function tests () {
'use strict';
console.log('Running mscript tests');
console.time('Tests took');
mscript.alts_unique(); //perform check only during tests
var fail = function (script, obj) {
console.log('...Failed :(');
console.log(script);
console.log(obj);
process.exit();
};
var script = 'CF\nPF\nCB\nPB\nBF\nBB';
console.log('Basic function test...');
mscript.interpret(script, function (obj) {
if (obj.success === true
&& obj.cam === 0
&& obj.proj === 0
&& obj.arr.length === 6) {
console.log('...Passed!');
} else {
fail(script, obj);
}
});
var script = 'CF\nPF\nCB\nPB\nBF\nBB';
console.log('Functions with integers test...');
mscript.interpret(script, function (obj) {
if (obj.success === true
&& obj.cam === 0
&& obj.proj === 0
&& obj.arr.length === 6) {
console.log('...Passed!');
} else {
fail(script, obj);
}
});
script = 'CF 1000\nCB 1000\nSET PROJ 200\nPB 200';
console.log('Basic state test...');
mscript.interpret(script, function (obj) {
if (obj.success === true
&& obj.cam === 0
&& obj.proj === 0) {
console.log('...Passed!');
} else {
fail(script, obj);
}
});
script = 'LOOP 10\nCF 3\nPF 1\nEND LOOP';
console.log('Basic loop test...');
mscript.interpret(script, function (obj) {
if (obj.success === true
&& obj.cam === 30
&& obj.proj === 10
&& obj.arr.length === 40) {
console.log('...Passed!');
} else {
fail(script, obj);
}
});
script = 'LOOP 4\nLOOP 4\nPF\nBF\nEND LOOP\nEND LOOP';
console.log('Recursive loop test...');
mscript.interpret(script, function (obj) {
if (obj.success === true
&& obj.cam === 16
&& obj.proj === 16
&& obj.arr.length === 32) {
console.log('...Passed!');
} else {
fail(script, obj);
}
});
//Lighting tests
script = 'L 255,255,255\nCF\nPF';
console.log('Basic light test...');
mscript.interpret(script, function (obj) {
if (obj.success === true
&& obj.cam === 1
&& obj.proj === 1
&& obj.arr.length === 2
&& obj.light.length === 2
&& obj.light[0] === '255,255,255'
&& obj.light[1] === '') {
console.log('...Passed!');
} else {
fail(script, obj);
}
});
script = 'L 255,255,255\nCF\nPF\nBF';
console.log('Basic black test...');
mscript.interpret(script, function (obj) {
if (obj.success === true
&& obj.cam === 2
&& obj.proj === 1
&& obj.arr.length === 3
&& obj.light.length === 3
&& obj.light[0] === '255,255,255'
&& obj.light[1] === ''
&& obj.light[2] === mscript.black) {
console.log('...Passed!');
} else {
fail(script, obj);
}
});
script = 'LOOP 2\nL 1,1,1\nCF\nL 2,2,2\nCF\nEND';
console.log('Basic light loop test...');
mscript.interpret(script, function (obj) {
if (obj.success === true
&& obj.cam === 4
&& obj.proj === 0
&& obj.arr.length === 4
&& obj.light.length === 4
&& obj.light[0] === '1,1,1'
&& obj.light[3] === '2,2,2') {
console.log('...Passed!');
} else {
fail(script, obj);
}
});
//LOOP W/ CAM and PROJ
script = 'LOOP 2\nCAM 4\nPROJ 4\nEND';
console.log('Basic cam/proj loop test...');
mscript.interpret(script, function (obj) {
if (obj.success === true
&& obj.cam === 8
&& obj.proj === 8
&& obj.arr.length === 16
&& obj.light.length === 16
&& obj.light[0] === mscript.black) {
console.log('...Passed!');
} else {
fail(script, obj);
}
});
console.log('All tests completed');
console.timeEnd('Tests took');
};
if (typeof document === 'undefined'
&& typeof module !== 'undefined'
&& !module.parent) {
//node script
fs = require('fs');
input = process.argv[2];
mscript.init();
} else if (typeof module !== 'undefined' && module.parent) {
//module
fs = require('fs');
module.exports = mscript;
} else {
//web
} }
module.exports = Mscript;
/* /*

View File

@ -0,0 +1,476 @@
'use strict';
/** @module lib/mscript */
let fs;
let input;
/** object mscript */
const mscript = {};
/**
* Check for the presence of specific arguments in process
* argv
*
* @param {string} shrt Short version of argument or flag
* @param {string} lng Long version of argument or flag
*
* @return {boolean} Is flag present
*/
mscript.arg = function arg (shrt, lng) {
if (process.argv.indexOf(shrt) !== -1 ||
process.argv.indexOf(lng) !== -1) {
return true;
}
return false;
};
/**
* Check for the position of specific arguments in process
* argv
*
* @param {string} shrt Short version of argument or flag
* @param {string} lng Long version of argument or flag
*
* @return {boolean} Position of arg or flag, for locating input
*/
mscript.arg_pos = function arg_pos (shrt, lng) {
var pos = -1;
pos = process.argv.indexOf(shrt);
if (pos === -1) {
pos = process.argv.indexOf(lng);
}
return pos;
};
mscript.black = '0,0,0';
mscript.cmd = [
'CF',
'PF',
'BF',
'CB',
'PB',
'BB'
];
mscript.alts = {
'CF' : ['CAMERA FORWARD', 'CAM FORWARD'],
'PF' : ['PROJECTOR FORWARD', 'PROJ FORWARD'],
'BF' : ['BLACK FORWARD', 'BLACK', 'BLANK FORWARD', 'BLANK'],
'CB' : ['CAMERA BACKWARD', 'CAM BACKWARD', 'CAMERA BACK', 'CAM BACK'],
'PB' : ['PROJECTOR FORWARD', 'PROJ FORWARD', 'PROJECTOR BACK', 'PROJ BACK'],
'BB' : ['BLACK BACKWARD', 'BLACK BACK', 'BLANK BACK'],
'L ' : ['LIGHT', 'COLOR', 'LAMP'],
'F ' : ['FADE']
};
mscript.state = {};
/**
* Clear the state object
*/
mscript.state_clear = function state_clear () {
mscript.state = {
cam : 0,
proj : 0,
color : '',
loops : [],
rec : -1
};
};
/**
* This is never used and doesn't do anything?
*/
mscript.alts_unique = function alts_unique () {
var ids = Object.keys(mscript.alts),
all = [];
for (var i = 0; i < ids.length; i++) {
if (all.indexOf(ids[i]) === -1) {
all.push(ids[i]);
} else {
mscript.fail("Can't compile");
}
}
};
/**
*
*/
mscript.interpret = function interpret (text, callback) {
mscript.state_clear();
if (typeof text === 'undefined') {
mscript.fail('No input');
}
var lines = text.split('\n'),
two = '',
arr = [],
light = [],
target = 0,
dist = 0, //?
output = {};
for (var i = 0; i < lines.length; i++) {
lines[i] = lines[i].replace(/\t+/g, ""); //strip tabs
lines[i] = lines[i].trim(); //remove excess whitespace before and after command
two = lines[i].substring(0, 2);
if (mscript.cmd.indexOf(two) !== -1) {
if (mscript.state.loops.length > 0) {
//hold generated arr in state loop array
mscript.state.loops[mscript.state.rec].arr
.push.apply(mscript.state.loops[mscript.state.rec].arr,
mscript.str_to_arr(lines[i],
two));
mscript.state.loops[mscript.state.rec].light
.push.apply(mscript.state.loops[mscript.state.rec].light,
mscript.light_to_arr(lines[i],
two));
} else {
arr.push.apply(arr, mscript.str_to_arr(lines[i], two));
light.push.apply(light, mscript.light_to_arr(lines[i], two))
}
} else if (lines[i].substring(0, 4) === 'LOOP') {
mscript.state.rec++;
mscript.state.loops[mscript.state.rec] = {
arr : [],
light : [],
cam : 0,
proj : 0,
cmd : lines[i] + ''
};
} else if (lines[i].substring(0, 2) === 'L ') {
mscript.light_state(lines[i]);
} else if (lines[i].substring(0, 3) === 'END') {
for (var x = 0; x < mscript.loop_count(mscript.state.loops[mscript.state.rec].cmd); x++) {
if (mscript.state.rec === 0) {
arr.push.apply(arr, mscript.state.loops[mscript.state.rec].arr);
light.push.apply(light, mscript.state.loops[mscript.state.rec].light);
} else if (mscript.state.rec >= 1) {
mscript.state.loops[mscript.state.rec - 1].arr
.push.apply(mscript.state.loops[mscript.state.rec - 1].arr,
mscript.state.loops[mscript.state.rec].arr);
mscript.state.loops[mscript.state.rec - 1].light
.push.apply(mscript.state.loops[mscript.state.rec - 1].light,
mscript.state.loops[mscript.state.rec].light);
}
}
mscript.state_update('END', mscript.loop_count(mscript.state.loops[mscript.state.rec].cmd));
delete mscript.state.loops[mscript.state.rec];
mscript.state.rec--;
} else if (lines[i].substring(0, 3) === 'CAM') { //directly go to that frame (black?)
target = parseInt(lines[i].split('CAM ')[1]);
if (mscript.state.loops.length > 0) {
if (target > mscript.state.cam) {
dist = target - mscript.state.cam;
for (var x = 0; x < dist; x++) {
mscript.state.loops[mscript.state.rec].arr.push('BF');
mscript.state.loops[mscript.state.rec].light.push(mscript.black);
mscript.state_update('BF');
}
} else {
dist = mscript.state.cam - target;
for (var x = 0; x < dist; x++) {
mscript.state.loops[mscript.state.rec].arr.push('BB');
mscript.state.loops[mscript.state.rec].light.push(mscript.black);
mscript.state_update('BB');
}
}
} else {
if (target > mscript.state.cam) {
dist = target - mscript.state.cam;
for (var x = 0; x < dist; x++) {
arr.push('BF');
light.push(mscript.black);
mscript.state_update('BF');
}
} else {
dist = mscript.state.cam - target;
for (var x = 0; x < dist; x++) {
arr.push('BB');
light.push(mscript.black);
mscript.state_update('BB');
}
}
}
} else if (lines[i].substring(0, 4) === 'PROJ') { //directly go to that frame
target = parseInt(lines[i].split('PROJ ')[1]);
if (mscript.state.loops.length > 0) {
if (target > mscript.state.proj) {
dist = target - mscript.state.proj;
for (var x = 0; x < dist; x++) {
mscript.state.loops[mscript.state.rec].arr.push('PF');
mscript.state.loops[mscript.state.rec].light.push('');
mscript.state_update('PF');
}
} else {
dist = mscript.state.proj - target;
for (var x = 0; x < dist; x++) {
mscript.state.loops[mscript.state.rec].arr.push('PB');
mscript.state.loops[mscript.state.rec].light.push('');
mscript.state_update('PB');
}
}
} else {
if (target > mscript.state.proj) {
dist = target - mscript.state.proj;
for (var x = 0; x < dist; x++) {
arr.push('PF');
light.push('');
mscript.state_update('PF');
}
} else {
dist = mscript.state.proj - target;
for (var x = 0; x < dist; x++) {
arr.push('PB');
light.push('');
mscript.state_update('PB');
}
}
}
} else if (lines[i].substring(0, 3) === 'SET') { //set that state
if (lines[i].substring(0, 7) === 'SET CAM') {
mscript.state.cam = parseInt(lines[i].split('SET CAM')[1]);
} else if (lines[i].substring(0, 8) === 'SET PROJ') {
mscript.state.proj = parseInt(lines[i].split('SET PROJ')[1]);
}
} else if (lines[i].substring(0, 1) === '#' || lines[i].substring(0, 2) === '//') {
//comments
//ignore while parsing
}
}
output.success = true;
output.arr = arr;
output.light = light;
output.cam = mscript.state.cam;
output.proj = mscript.state.proj;
if (typeof callback !== 'undefined') {
//should only be invoked by running mscript.tests()
callback(output);
} else {
return mscript.output(output);
}
};
/**
*
*/
mscript.last_loop = function last_loop () {
return mscript.state.loops[mscript.state.loops.length - 1];
};
/**
*
*/
mscript.parent_loop = function parent_loop () {
return mscript.state.loops[mscript.state.loops.length - 2];
};
/**
*
*/
mscript.state_update = function state_update (cmd, val) {
if (cmd === 'END') {
for (var i = 0; i < val; i++) {
if (mscript.state.rec === 0) {
mscript.state.cam += mscript.state.loops[mscript.state.rec].cam;
mscript.state.proj += mscript.state.loops[mscript.state.rec].proj;
} else if (mscript.state.rec >= 1) {
mscript.state.loops[mscript.state.rec - 1].cam += mscript.state.loops[mscript.state.rec].cam;
mscript.state.loops[mscript.state.rec - 1].proj += mscript.state.loops[mscript.state.rec].proj;
}
}
} else if (cmd === 'CF') {
if (mscript.state.loops.length < 1) {
mscript.state.cam++;
} else {
mscript.state.loops[mscript.state.rec].cam++;
}
} else if (cmd === 'CB') {
if (mscript.state.loops.length < 1) {
mscript.state.cam--;
} else {
mscript.state.loops[mscript.state.rec].cam--;
}
} else if (cmd === 'PF') {
if (mscript.state.loops.length < 1) {
mscript.state.proj++;
} else {
mscript.state.loops[mscript.state.rec].proj++;
}
} else if (cmd === 'PB') {
if (mscript.state.loops.length < 1) {
mscript.state.proj--;
} else {
mscript.state.loops[mscript.state.rec].proj--;
}
} else if (cmd === 'BF') {
if (mscript.state.loops.length < 1) {
mscript.state.cam++;
} else {
mscript.state.loops[mscript.state.rec].cam++;
}
} else if (cmd === 'BB') {
if (mscript.state.loops.length < 1) {
mscript.state.cam--;
} else {
mscript.state.loops[mscript.state.rec].cam++;
}
} else if (cmd === 'L ') {
}
};
/**
*
*/
mscript.str_to_arr = function str_to_arr (str, cmd) {
var cnt = str.split(cmd),
c = parseInt(cnt[1]),
arr = [];
if (cnt[1] === '') {
c = 1;
} else {
c = parseInt(cnt[1]);
}
for (var i = 0; i < c; i++) {
arr.push(cmd);
mscript.state_update(cmd);
}
return arr;
};
/**
*
*/
mscript.light_state = function light_state (str) {
//add parsers for other color spaces
var color = str.replace('L ', '').trim();
mscript.state.color = color;
};
/**
*
*/
mscript.light_to_arr = function light_to_arr (str, cmd) {
var cnt = str.split(cmd),
c = parseInt(cnt[1]),
arr = [];
if (cnt[1] === '') {
c = 1;
} else {
c = parseInt(cnt[1]);
}
for (var i = 0; i < c; i++) {
if (cmd === 'CF'
|| cmd === 'CB') {
arr.push(mscript.state.color);
} else if (cmd === 'BF'
|| cmd === 'BB') {
arr.push(mscript.black);
} else {
arr.push('');
}
}
return arr;
};
/**
*
*/
mscript.loop_count = function loop_count (str) {
return parseInt(str.split(' ')[1]);
};
mscript.fade_count = function fade_count (str) {
return parseInt(str.split(' ')[1]);
}
/**
*
*/
mscript.fail = function fail (reason) {
console.error(JSON.stringify({success: false, error: true, msg : reason}));
if (process) process.exit();
};
/**
*
*/
mscript.output = function output (data) {
var json = true; //default
if (mscript.arg('-j', '--json')) {
json = true;
}
if (mscript.arg('-t', '--text')) {
json = false;
}
if (json) {
console.log(JSON.stringify(data));
} else {
var ids = Object.keys(data);
for (var i = 0; i < ids.length; i++) {
console.log(ids[i] + ': ' + data[ids[i]]);
}
}
};
/**
*
*/
mscript.init = function init () {
if (mscript.arg('-t', '--tests')) {
return mscript.tests();
}
if (mscript.arg('-v', '--verbose')) {
console.time('mscript');
}
if (mscript.arg('-c', '--cam')) {
mscript.state.cam = parseInt(process.argv[mscript.arg_pos('-c', '--cam') + 1]);
}
if (mscript.arg('-p', '--proj')) {
mscript.state.proj = parseInt(process.argv[mscript.arg_pos('-p', '--proj') + 1]);
}
if (mscript.arg('-f', '--file')) {
input = process.argv[mscript.arg_pos('-f', '--file') + 1];
mscript.interpret(fs.readFileSync(input, 'utf8'));
} else {
mscript.interpret(input);
}
if (mscript.arg('-v', '--verbose')) {
console.timeEnd('mscript');
}
};
if (typeof document === 'undefined'
&& typeof module !== 'undefined'
&& !module.parent) {
//node script
fs = require('fs');
input = process.argv[2];
mscript.init();
} else if (typeof module !== 'undefined' && module.parent) {
//module
fs = require('fs');
module.exports = mscript;
} else {
//web
}
/*
CAM # - go to camera frame #
PROJ # - go to projector frame #
SET CAM # - sets camera count to #
SET PROJ # - sets projector count to #
LOOP # - begin loop, can nest recursively, # times
END LOOP - (or END) closes loop
L #RGB - sets light to rgb value
FADE
CF - Camera forwards
PF - Projector forwards
BF - Black forwards
CB - Camera backwards
PB - Projector backwards
BB - Black backwards
*/

View File

@ -124,8 +124,6 @@ light.set = function (rgb, callback) { //rgb = [0,0,0]
rgb : rgb, rgb : rgb,
id : uuid.v4() id : uuid.v4()
}; };
console.log(rgb)
console.log(obj)
ipcRenderer.sendSync('light', obj); ipcRenderer.sendSync('light', obj);
if (typeof callback !== 'undefined') { if (typeof callback !== 'undefined') {

View File

@ -60,11 +60,16 @@ mse.mscript.toGUI = function () {
for (let i = 0; i < mse.mscript.data.arr.length; i++) { for (let i = 0; i < mse.mscript.data.arr.length; i++) {
c = mse.mscript.data.arr[i]; c = mse.mscript.data.arr[i];
mcopy.state.sequence.arr[i] = c; mcopy.state.sequence.arr[i] = c;
//if (c === 'CF' || c === 'CB') { console.dir(mse.mscript.data);
mcopy.state.sequence.light[i] = light.color.join(','); if (c === 'CF' || c === 'CB') {
//} else { if (typeof mse.mscript.data.light[i] !== 'undefined' && mse.mscript.data.light[i] !== '') {
//mcopy.state.sequence.light[i] = ''; mcopy.state.sequence.light[i] = mse.mscript.data.light[i];
//} } else {
mcopy.state.sequence.light[i] = light.color.join(',');
}
} else {
mcopy.state.sequence.light[i] = '';
}
gui.grid.state(i); gui.grid.state(i);
} }
}; };
@ -95,6 +100,7 @@ mse.mscript.toSequence = function () {
mse.mscript.compile = function (cb) { mse.mscript.compile = function (cb) {
'use strict'; 'use strict';
const data = mse.mscript.editor.getValue(); const data = mse.mscript.editor.getValue();
let mscript = new Mscript();
let output; let output;
mse.mscript.raw = data; mse.mscript.raw = data;
mscript.interpret(data, (output) => { mscript.interpret(data, (output) => {
@ -114,11 +120,11 @@ mse.mscript.prepare = function () {
obj = { obj = {
cmd : mse.mscript.data.arr[i] cmd : mse.mscript.data.arr[i]
}; };
/*if (mse.mscript.data.light[i] !== '') { if (typeof mse.mscript.data.light[i] !== 'undefined' && mse.mscript.data.light[i] !== '') {
obj.light = mse.mscript.data.light[i]; obj.light = mse.mscript.data.light[i];
} else { } else {
obj.light = light.color.join(','); obj.light = light.color.join(',');
}*/ }
arr.push(obj); arr.push(obj);
} }
return arr; return arr;

3980
app/package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -6,7 +6,8 @@
"scripts": { "scripts": {
"start": "./node_modules/.bin/electron main.js", "start": "./node_modules/.bin/electron main.js",
"dev": "./node_modules/.bin/gulp && ./node_modules/.bin/electron main.js -d", "dev": "./node_modules/.bin/gulp && ./node_modules/.bin/electron main.js -d",
"install": "./node_modules/.bin/electron-rebuild" "install": "./node_modules/.bin/electron-rebuild",
"test": "./node_modules/.bin/qunit test/index.js"
}, },
"repository": { "repository": {
"type": "git", "type": "git",
@ -25,7 +26,7 @@
}, },
"homepage": "https://github.com/sixteenmillimeter/mcopy#readme", "homepage": "https://github.com/sixteenmillimeter/mcopy#readme",
"devDependencies": { "devDependencies": {
"electron-installer-debian": "^0.7.1", "electron-installer-debian": "^0.8.1",
"electron-installer-dmg": "^0.2.1", "electron-installer-dmg": "^0.2.1",
"electron-packager": "^10.1.1", "electron-packager": "^10.1.1",
"electron-rebuild": "^1.4.0", "electron-rebuild": "^1.4.0",
@ -34,11 +35,12 @@
"gulp-concat": "^2.6.1", "gulp-concat": "^2.6.1",
"gulp-less": "^3.4.0", "gulp-less": "^3.4.0",
"jsdoc-to-markdown": "^4.0.1", "jsdoc-to-markdown": "^4.0.1",
"qunit": "^2.5.1" "qunit": "^2.6.1"
}, },
"dependencies": { "dependencies": {
"async": "^2.6.0", "async": "^2.6.0",
"electron": "^1.8.2-beta.4", "electron": "^1.8.2-beta.4",
"fs-extra": "^6.0.1",
"humanize-duration": "^3.12.1", "humanize-duration": "^3.12.1",
"moment": "^2.17.1", "moment": "^2.17.1",
"node-notifier": "^5.1.2", "node-notifier": "^5.1.2",

View File

@ -20,7 +20,7 @@ const cmd = require('./lib/ui/cmd.js');
const log = require('./lib/ui/log.js'); const log = require('./lib/ui/log.js');
const devices = require('./lib/ui/devices.js'); const devices = require('./lib/ui/devices.js');
const mse = require('./lib/ui/mscript.js'); const mse = require('./lib/ui/mscript.js');
const mscript = require('./lib/mscript'); const Mscript = require('./lib/mscript');

View File

@ -1,4 +1,4 @@
var fs = require('fs'), /*var fs = require('fs'),
mcopy = {}; mcopy = {};
mcopy.cfg = JSON.parse(fs.readFileSync('./cfg.json', 'utf8')); mcopy.cfg = JSON.parse(fs.readFileSync('./cfg.json', 'utf8'));
@ -14,7 +14,7 @@ mcopy.arduino.colorTest = function (color, cb) {
mcopy.arduino.init(function (success) { mcopy.arduino.init(function (success) {
mcopy.arduino.connect(function () { mcopy.arduino.connect(function () {
/*
mcopy.arduino.colorTest('255,140,70', function () { mcopy.arduino.colorTest('255,140,70', function () {
mcopy.arduino.colorTest('5,0,0', function () { mcopy.arduino.colorTest('5,0,0', function () {
mcopy.arduino.colorTest('255,255,255', function () { mcopy.arduino.colorTest('255,255,255', function () {
@ -26,6 +26,6 @@ mcopy.arduino.init(function (success) {
});//3 });//3
});//2 });//2
});//1 });//1
*/
}); });
}); });*/

3
app/test/index.js Normal file
View File

@ -0,0 +1,3 @@
'use strict'
const mscript_test = require('./mscript_test.js');

View File

@ -0,0 +1,38 @@
'use strict';
//the purpose of this script is to test the performance of the
//mscript rewrite against the original
const Mscript = require('../lib/mscript');
const mscript = new Mscript();
const mscriptOld = require('../lib/mscript/index.old.js');
mscript.interpret(`F 72 0,0,0 10,20,30
CF
END
PF 10
`, (output) => {
console.dir(output)
});
process.exit()
mscriptOld.state_clear();
console.time('mscript old str_to_arr');
for (let i = 0; i < 100000; i++) {
mscriptOld.str_to_arr('BF 2222', 'BF');
}
console.timeEnd('mscript old str_to_arr')
mscript.clear()
console.time('mscript str_to_arr');
for (let i = 0; i < 100000; i++) {
mscript.str_to_arr('BF 2222', 'BF');
}
console.timeEnd('mscript str_to_arr');

151
app/test/mscript_test.js Normal file
View File

@ -0,0 +1,151 @@
'use strict';
const Mscript = require('../lib/mscript');
const mscript = new Mscript();
QUnit.test(`Basic functions`, (assert) => {
const script1 = 'CF\nPF\nCB\nPB\nBF\nBB';
const script2 = `CF 3\nPF 3`
assert.expect( 2 );
mscript.interpret(script1, (obj) => {
let pass = false;
if (obj.success === true
&& obj.cam === 0
&& obj.proj === 0
&& obj.arr.length === 6) {
pass = true;
}
assert.ok(pass, `Simple script1 compiles`)
});
mscript.interpret(script2, (obj) => {
let pass = false;
if (obj.success === true
&& obj.cam === 3
&& obj.proj === 3
&& obj.arr.length === 6) {
pass = true;
}
assert.ok(pass, `Simple script2 compiles`)
});
});
QUnit.test(`Commands with integers`, (assert) => {
const script = 'CF 5\nPF 5\nCB 5\nPB 5\nBF 3\nBB 3';
assert.expect( 1 );
mscript.interpret(script, (obj) => {
let pass = false;
if (obj.success === true
&& obj.cam === 0
&& obj.proj === 0
&& obj.arr.length === 26) {
pass = true;
}
assert.ok(pass, `Script with integers cancels out count, but generates list of commands`)
});
})
QUnit.test('State', (assert) => {
const script = 'CF 1000\nCB 1000\nSET PROJ 200\nPB 200';
assert.expect(1);
mscript.interpret(script, (obj) => {
let pass = false;
if (obj.success === true
&& obj.cam === 0
&& obj.proj === 0) {
pass = true;
}
assert.ok(pass, `Basic state test`);
});
});
QUnit.test('Loop', (assert) => {
const script1 = 'LOOP 10\nCF 3\nPF 1\nEND LOOP';
assert.expect(3);
mscript.interpret(script1, (obj) => {
let pass = false;
if (obj.success === true
&& obj.cam === 30
&& obj.proj === 10
&& obj.arr.length === 40) {
pass = true;
}
assert.ok(pass, 'Basic loop');
});
const script2 = 'LOOP 4\nLOOP 4\nPF\nBF\nEND LOOP\nEND LOOP';
mscript.interpret(script2, (obj) => {
let pass = false;
if (obj.success === true
&& obj.cam === 16
&& obj.proj === 16
&& obj.arr.length === 32) {
pass = true;
}
assert.ok(pass, 'Recursive loop');
});
//LOOP W/ CAM and PROJ
const script3 = 'LOOP 2\nCAM 4\nPROJ 4\nEND';
mscript.interpret(script3, (obj) => {
let pass = false;
if (obj.success === true
&& obj.cam === 8
&& obj.proj === 8
&& obj.arr.length === 16
&& obj.light.length === 16
&& obj.light[0] === '0,0,0') {
pass = true;
}
assert.ok(pass, 'Basic cam/proj loop');
});
});
QUnit.test('Light', (assert) => {
//Lighting tests
const script1 = 'L 255,255,255\nCF\nPF';
assert.expect(3);
mscript.interpret(script1, (obj) => {
let pass = false;
if (obj.success === true
&& obj.cam === 1
&& obj.proj === 1
&& obj.arr.length === 2
&& obj.light.length === 2
&& obj.light[0] === '255,255,255'
&& obj.light[1] === '') {
pass = true;
}
assert.ok(pass, 'Basic light');
});
const script2 = 'L 255,255,255\nCF\nPF\nBF';
mscript.interpret(script2, (obj) => {
let pass = false;
if (obj.success === true
&& obj.cam === 2
&& obj.proj === 1
&& obj.arr.length === 3
&& obj.light.length === 3
&& obj.light[0] === '255,255,255'
&& obj.light[1] === ''
&& obj.light[2] === '0,0,0') {
pass = true;
}
assert.ok(pass, 'Basic black');
});
const script3 = 'LOOP 2\nL 1,1,1\nCF\nL 2,2,2\nCF\nEND';
mscript.interpret(script3, (obj) => {
let pass = false;
if (obj.success === true
&& obj.cam === 4
&& obj.proj === 0
&& obj.arr.length === 4
&& obj.light.length === 4
&& obj.light[0] === '1,1,1'
&& obj.light[3] === '2,2,2') {
pass = true;
}
assert.ok(pass, 'Basic light');
});
});

View File

@ -1,3 +0,0 @@
var mscript = require('../lib/mscript.js');
mscript.tests();