Merge in 9 months of work on capper branch #71
|
@ -0,0 +1,243 @@
|
||||||
|
/** @module lib/mscript */
|
||||||
|
interface RGB extends Array<number> {
|
||||||
|
[index: number]: number;
|
||||||
|
}
|
||||||
|
/** class Mscript */
|
||||||
|
export declare class Mscript {
|
||||||
|
output: any;
|
||||||
|
lines: string[];
|
||||||
|
cam: number;
|
||||||
|
cam2: number;
|
||||||
|
proj: number;
|
||||||
|
proj2: number;
|
||||||
|
color: string;
|
||||||
|
loops: any[];
|
||||||
|
rec: number;
|
||||||
|
two: string;
|
||||||
|
three: string;
|
||||||
|
four: string;
|
||||||
|
arr: any[];
|
||||||
|
meta: string[];
|
||||||
|
target: number;
|
||||||
|
dist: number;
|
||||||
|
variables: any;
|
||||||
|
/**
|
||||||
|
* @constructor
|
||||||
|
* Create new Mscript interpreter
|
||||||
|
**/
|
||||||
|
constructor();
|
||||||
|
/**
|
||||||
|
* Clear the state of the script
|
||||||
|
*/
|
||||||
|
clear(): void;
|
||||||
|
/**
|
||||||
|
* 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 sequence.
|
||||||
|
*
|
||||||
|
* @param {string} text Mscript text to interpret
|
||||||
|
* @param {function} callback Function to call when string is interpreted
|
||||||
|
*
|
||||||
|
* @returns {object} if callback is not provided
|
||||||
|
*/
|
||||||
|
interpret(text: string, callback?: Function): any;
|
||||||
|
/**
|
||||||
|
* Interprets variables for complex sequence behavior.
|
||||||
|
* TODO: Fully implement, add test coverage
|
||||||
|
*
|
||||||
|
* @param {string} line Line containing a variable assignment
|
||||||
|
*
|
||||||
|
**/
|
||||||
|
variable(line: string): void;
|
||||||
|
/**
|
||||||
|
* Replace variable with value at time of interpretation
|
||||||
|
* TODO: Implement this please
|
||||||
|
*
|
||||||
|
* @param {string} line Line containing variable to be replaced with value
|
||||||
|
*
|
||||||
|
* @returns {string} New string to be interpreted
|
||||||
|
**/
|
||||||
|
variable_replace(line: string): string;
|
||||||
|
/**
|
||||||
|
* Interpret a basic two character command
|
||||||
|
*
|
||||||
|
* @param {string} line Line of script to interpret
|
||||||
|
* @param {string} short The short command to use
|
||||||
|
*/
|
||||||
|
basic_cmd(line: string, short: string): void;
|
||||||
|
/**
|
||||||
|
* Start a new loop
|
||||||
|
*
|
||||||
|
* @param {string} line Line to evaluate as either loop or fade
|
||||||
|
* @param {boolean} fade Flag as true if fade
|
||||||
|
*/
|
||||||
|
new_loop(line: string, fade?: boolean): void;
|
||||||
|
/**
|
||||||
|
* Close the most recent loop
|
||||||
|
*
|
||||||
|
* @param {string} line Line to interpret
|
||||||
|
*/
|
||||||
|
end_loop(line: string): void;
|
||||||
|
/**
|
||||||
|
* Move camera to explicitly-defined frame
|
||||||
|
*
|
||||||
|
* @param {string} line Line to interpret with camera move statement
|
||||||
|
*/
|
||||||
|
move_cam(line: string): void;
|
||||||
|
/**
|
||||||
|
* Move secondary camera to explicitly-defined frame
|
||||||
|
*
|
||||||
|
* @param {string} line Line to interpret with camera move statement
|
||||||
|
*/
|
||||||
|
move_cam2(line: string): void;
|
||||||
|
/**
|
||||||
|
* Move projector to explicitly-defined frame
|
||||||
|
*
|
||||||
|
* @param {string} line Line containing `move` statement to interpret
|
||||||
|
*/
|
||||||
|
move_proj(line: string): void;
|
||||||
|
/**
|
||||||
|
* Move projector to explicitly-defined frame
|
||||||
|
*
|
||||||
|
* @param {string} line Line containing `move` statement to interpret
|
||||||
|
*/
|
||||||
|
move_proj2(line: string): void;
|
||||||
|
/**
|
||||||
|
* Set the state of either the cam or projector
|
||||||
|
*
|
||||||
|
* @param line {string} String containing set statement
|
||||||
|
*/
|
||||||
|
set_state(line: string): void;
|
||||||
|
/**
|
||||||
|
* Return the last loop
|
||||||
|
*
|
||||||
|
* @returns {object}
|
||||||
|
*/
|
||||||
|
last_loop(): any;
|
||||||
|
/**
|
||||||
|
* Return the second-last loop
|
||||||
|
*
|
||||||
|
* @returns {object} Loop array
|
||||||
|
*/
|
||||||
|
parent_loop(): any;
|
||||||
|
/**
|
||||||
|
* Extract the loop count integer from a LOOP cmd
|
||||||
|
*
|
||||||
|
* @returns {integer} Loop count in string parsed into integer
|
||||||
|
*/
|
||||||
|
loop_count(str: string): number;
|
||||||
|
/**
|
||||||
|
* Execute a fade of frame length, from color to another color
|
||||||
|
*
|
||||||
|
* @param {string} line Line containing a fade initiator
|
||||||
|
*/
|
||||||
|
fade(line: string): void;
|
||||||
|
/**
|
||||||
|
* Extract the fade length integer from a FADE cmd
|
||||||
|
*
|
||||||
|
* @param {string} str Line containing the length of fade in frames
|
||||||
|
*/
|
||||||
|
fade_count(str: string): number;
|
||||||
|
/**
|
||||||
|
* Extract the start color from a string
|
||||||
|
*
|
||||||
|
* @param {string} str Line containing the start color value in a fade initiator
|
||||||
|
*
|
||||||
|
* @returns {array} Array containing RGB color values
|
||||||
|
*/
|
||||||
|
fade_start(str: string): RGB;
|
||||||
|
/**
|
||||||
|
* Extract the end color from a string
|
||||||
|
*
|
||||||
|
* @param {string} str Line containing the end color value in a fade initiator
|
||||||
|
*
|
||||||
|
* @returns {array} Array containing RGB color values
|
||||||
|
*/
|
||||||
|
fade_end(str: string): RGB;
|
||||||
|
/**
|
||||||
|
* Determine the state of a fade at a particular frame in the sequence, x
|
||||||
|
*
|
||||||
|
* @param {array} start Color the fade starts at
|
||||||
|
* @param {array} end Color the fade finishes at
|
||||||
|
* @param {integer} len Total length of the fade in frames
|
||||||
|
* @param {integer} x Position of the fade to get color value of
|
||||||
|
*
|
||||||
|
* @returns {array} Array containing RGB color values
|
||||||
|
*/
|
||||||
|
fade_rgb(start: RGB, end: RGB, len: number, x: number): string;
|
||||||
|
/**
|
||||||
|
* Parse string into array of RGB color values. 0-255 octet.
|
||||||
|
*
|
||||||
|
* @param {string} str String containing only color values as `#,#,#`
|
||||||
|
**/
|
||||||
|
rgb(str: string): RGB;
|
||||||
|
/**
|
||||||
|
* Cast RGB color values as string
|
||||||
|
*
|
||||||
|
* @param {array} arr Array to join into string
|
||||||
|
*
|
||||||
|
* @returns {string} String of RGB values
|
||||||
|
**/
|
||||||
|
rgb_str(arr: RGB): string;
|
||||||
|
/**
|
||||||
|
* Increase the state of a specific object, such as the camera/projector,
|
||||||
|
* by the value defined in val.
|
||||||
|
*
|
||||||
|
* @param {string} cmd String representing command to interpret and update state
|
||||||
|
*/
|
||||||
|
update(cmd: string, val?: number): void;
|
||||||
|
/**
|
||||||
|
* Split string on command, turn into array of commands
|
||||||
|
* as long as count variable. Default 1.
|
||||||
|
*
|
||||||
|
* @param {string} str String to split
|
||||||
|
* @param {string} cmd String representing command to split at
|
||||||
|
*
|
||||||
|
* @returns {array} Array containing commands
|
||||||
|
*/
|
||||||
|
str_to_arr(str: string, cmd: string): string[];
|
||||||
|
/**
|
||||||
|
* Split a string on a command to extract data for light array
|
||||||
|
*
|
||||||
|
* @param {string} str String containing light command
|
||||||
|
* @param {string} cmd String representing command
|
||||||
|
*
|
||||||
|
* @returns {array} An RGB array containing the color values
|
||||||
|
*/
|
||||||
|
light_to_arr(str: string, cmd: string): RGB;
|
||||||
|
/**
|
||||||
|
* Split a string to extract an rgb color value
|
||||||
|
*
|
||||||
|
* @param {string} Color string assign to color property
|
||||||
|
*/
|
||||||
|
light_state(str: string): void;
|
||||||
|
/**
|
||||||
|
* Interpret a pause command
|
||||||
|
*
|
||||||
|
* @param {string} line String containing pause command
|
||||||
|
**/
|
||||||
|
pause(line: string): void;
|
||||||
|
/**
|
||||||
|
* Interpret an alert command
|
||||||
|
*
|
||||||
|
* @param {string} line String containing pause command
|
||||||
|
**/
|
||||||
|
alert(line: string): void;
|
||||||
|
/**
|
||||||
|
* Throw an error with specific message
|
||||||
|
*
|
||||||
|
* @param {string} msg Error message to print
|
||||||
|
*/
|
||||||
|
fail(msg: string): void;
|
||||||
|
/**
|
||||||
|
* Determine if array contains matching elements of
|
||||||
|
* another array
|
||||||
|
*
|
||||||
|
* @param {Array} arr Original array to compare
|
||||||
|
* @param {Array} arr2 Array to compare elements from
|
||||||
|
*
|
||||||
|
* @returns {boolean} Whether arr contains elements in arr2
|
||||||
|
**/
|
||||||
|
contains(arr: string[], arr2: string[]): boolean;
|
||||||
|
}
|
||||||
|
export {};
|
|
@ -1,4 +1,6 @@
|
||||||
'use strict';
|
'use strict';
|
||||||
|
Object.defineProperty(exports, "__esModule", { value: true });
|
||||||
|
exports.Mscript = void 0;
|
||||||
const BLACK = '0,0,0';
|
const BLACK = '0,0,0';
|
||||||
const WHITE = '255,255,255';
|
const WHITE = '255,255,255';
|
||||||
const CMD = [
|
const CMD = [
|
||||||
|
@ -122,7 +124,7 @@ class Mscript {
|
||||||
*
|
*
|
||||||
* @returns {object} if callback is not provided
|
* @returns {object} if callback is not provided
|
||||||
*/
|
*/
|
||||||
interpret(text, callback) {
|
interpret(text, callback = null) {
|
||||||
this.clear();
|
this.clear();
|
||||||
if (typeof text === 'undefined') {
|
if (typeof text === 'undefined') {
|
||||||
return this.fail('No input');
|
return this.fail('No input');
|
||||||
|
@ -200,7 +202,7 @@ class Mscript {
|
||||||
if (this.contains(this.arr, PROJECTOR_SECONDARY)) {
|
if (this.contains(this.arr, PROJECTOR_SECONDARY)) {
|
||||||
this.output.proj2 = this.proj2;
|
this.output.proj2 = this.proj2;
|
||||||
}
|
}
|
||||||
if (typeof callback !== 'undefined') {
|
if (typeof callback !== 'undefined' && callback != null) {
|
||||||
//should only be invoked by running mscript.tests()
|
//should only be invoked by running mscript.tests()
|
||||||
callback(this.output);
|
callback(this.output);
|
||||||
}
|
}
|
||||||
|
@ -967,5 +969,6 @@ class Mscript {
|
||||||
return arr.some(r => arr2.includes(r));
|
return arr.some(r => arr2.includes(r));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
exports.Mscript = Mscript;
|
||||||
module.exports = Mscript;
|
module.exports = Mscript;
|
||||||
//# sourceMappingURL=index.js.map
|
//# sourceMappingURL=index.js.map
|
File diff suppressed because one or more lines are too long
|
@ -1,233 +1,280 @@
|
||||||
const mse = {};
|
'use strict';
|
||||||
|
Object.defineProperty(exports, "__esModule", { value: true });
|
||||||
|
/// <reference path ="jquery.d.ts"/>
|
||||||
|
const mscript_1 = require("mscript");
|
||||||
/******
|
/******
|
||||||
Mscript GUI
|
Mscript GUI
|
||||||
*******/
|
*******/
|
||||||
mse.mscript = {};
|
class MscriptGUI {
|
||||||
mse.mscript.editor = {};
|
constructor() {
|
||||||
mse.mscript.data = {};
|
this.editor = {};
|
||||||
mse.mscript.raw = '';
|
this.data = {};
|
||||||
mse.mscript.init = function () {
|
this.raw = '';
|
||||||
'use strict';
|
}
|
||||||
$('#editor').val('CF 1\nPF 1');
|
/**
|
||||||
mse.mscript.editor = CodeMirror.fromTextArea(document.getElementById('editor'), {
|
* Initializes the mscript GUI. Sets up CodeMirror instance,
|
||||||
lineNumbers: true,
|
* binds events and sets height of editor.
|
||||||
mode: 'python',
|
**/
|
||||||
matchBrackets: true,
|
init() {
|
||||||
theme: 'monokai'
|
const startingScript = `CF 1
|
||||||
});
|
PF 1`;
|
||||||
mse.mscript.editor.setSize(null, $(window).height() - $('footer').eq(0).height() - 30);
|
const editorHeight = $(window).height() - $('footer').eq(0).height() - 30;
|
||||||
mse.mscript.editor.on('change', function (e) {
|
const editorElem = document.getElementById('editor');
|
||||||
//
|
const editorConfig = {
|
||||||
});
|
lineNumbers: true,
|
||||||
$(document).on('resize', function (e) {
|
mode: 'python',
|
||||||
mse.mscript.editor.setSize(null, $(window).height() - $('footer').eq(0).height() - 30);
|
matchBrackets: true,
|
||||||
});
|
theme: 'monokai'
|
||||||
};
|
};
|
||||||
mse.mscript.open = function () {
|
$('#editor').val(startingScript);
|
||||||
'use strict';
|
this.editor = CodeMirror.fromTextArea(editorElem, editorConfig);
|
||||||
mse.mscript.editor.setSize(null, $(window).height() - $('footer').eq(0).height() - 30);
|
this.editor.setSize(null, editorHeight);
|
||||||
mse.mscript.editor.refresh();
|
this.editor.on('change', (e) => { });
|
||||||
};
|
$(document).on('resize', function (e) {
|
||||||
mse.mscript.fromSequence = function () {
|
this.editor.setSize(null, editorHeight);
|
||||||
//ehhhhh
|
}.bind(this));
|
||||||
'use strict';
|
}
|
||||||
let str;
|
/**
|
||||||
let tmp = [];
|
* Callback for when open event occurs.
|
||||||
let cont;
|
**/
|
||||||
let cmd;
|
open() {
|
||||||
//str = seq.grid.map(step => { return step.cmd }).join('\n'); //quick hack
|
//recalcuate in case resize has occurred needed
|
||||||
//console.dir(seq.grid);
|
const editorHeight = $(window).height() - $('footer').eq(0).height() - 30;
|
||||||
for (let step of seq.grid) {
|
this.editor.setSize(null, editorHeight);
|
||||||
if (!step || !step.cmd) continue;
|
this.editor.refresh();
|
||||||
cmd = step.cmd;
|
}
|
||||||
if (tmp.length > 0 && tmp[tmp.length - 1].cmd === cmd) {
|
/**
|
||||||
tmp[tmp.length - 1].num++;
|
* Create script from the sequencer's current state.
|
||||||
continue;
|
* Previous comment: ehhhh
|
||||||
}
|
* TODO: Make this smarter.
|
||||||
tmp.push({ cmd : cmd, num : 1 });
|
**/
|
||||||
}
|
fromSequence() {
|
||||||
tmp = tmp.map(line => {
|
let str;
|
||||||
return `${line.cmd} ${line.num}`
|
let tmp = [];
|
||||||
})
|
let cont;
|
||||||
//console.dir(tmp)
|
let cmd;
|
||||||
if (seq.gridLoops > 1) {
|
//str = seq.grid.map(step => { return step.cmd }).join('\n'); //quick hack
|
||||||
tmp.map(line => {
|
//console.dir(seq.grid);
|
||||||
return ` ${line}`;
|
for (let step of seq.grid) {
|
||||||
})
|
if (!step || !step.cmd) {
|
||||||
tmp.reverse();
|
continue;
|
||||||
tmp.push(`LOOP ${seq.gridLoops}`);
|
}
|
||||||
tmp.reverse();
|
cmd = step.cmd;
|
||||||
tmp.push('END');
|
if (tmp.length > 0 && tmp[tmp.length - 1].cmd === cmd) {
|
||||||
}
|
tmp[tmp.length - 1].num++;
|
||||||
|
continue;
|
||||||
str = tmp.join('\n');
|
}
|
||||||
|
tmp.push({ cmd, num: 1 });
|
||||||
nav.change('script');
|
}
|
||||||
cont = confirm(`Are you sure you want to over-write the current sequence?`);
|
tmp = tmp.map(line => {
|
||||||
if (cont) {
|
return `${line.cmd} ${line.num}`;
|
||||||
mse.mscript.editor.getDoc().setValue(str);
|
});
|
||||||
}
|
if (seq.gridLoops > 1) {
|
||||||
};
|
tmp.map(line => {
|
||||||
mse.mscript.toGUI = function () {
|
return ` ${line}`;
|
||||||
'use strict';
|
});
|
||||||
let c;
|
tmp.reverse();
|
||||||
let step;
|
tmp.push(`LOOP ${seq.gridLoops}`);
|
||||||
for (let x = 0; x < mse.mscript.data.arr.length; x++) {
|
tmp.reverse();
|
||||||
c = mse.mscript.data.arr[x];
|
tmp.push('END');
|
||||||
seq.set(x, c);
|
}
|
||||||
if (c === 'CF' || c === 'CB') {
|
str = tmp.join('\n');
|
||||||
if (typeof mse.mscript.data.meta[x] !== 'undefined' && mse.mscript.data.meta[x] !== '') {
|
nav.change('script');
|
||||||
seq.setLight(x, mse.mscript.data.meta[x]);
|
cont = confirm(`Are you sure you want to over-write the current sequence?`);
|
||||||
} else {
|
if (cont) {
|
||||||
seq.setLight(x, light.color);
|
this.editor.getDoc().setValue(str);
|
||||||
}
|
}
|
||||||
} else {
|
}
|
||||||
//unset light?
|
/**
|
||||||
}
|
* Take current compiled mscript state and send it to the sequencer
|
||||||
grid.state(x);
|
* GUI. TODO: Add confirm step if sequence is longer than X steps.
|
||||||
}
|
* TODO: Make this smarter (detect outer non-fade loop and assign to loop counter)
|
||||||
};
|
**/
|
||||||
mse.mscript.toSequence = function () {
|
toGUI() {
|
||||||
'use strict';
|
let c;
|
||||||
const data = mse.mscript.editor.getValue();
|
let step;
|
||||||
let cont;
|
for (let x = 0; x < this.data.arr.length; x++) {
|
||||||
if (data !== mse.mscript.raw) {
|
c = this.data.arr[x];
|
||||||
cont = confirm(`Current script has not been compiled. Compile first?`);
|
seq.set(x, c);
|
||||||
if (cont) {
|
if (c === 'CF' || c === 'CB') {
|
||||||
mse.mscript.compile()
|
if (typeof this.data.meta[x] !== 'undefined' && this.data.meta[x] !== '') {
|
||||||
}
|
seq.setLight(x, this.data.meta[x]);
|
||||||
}
|
}
|
||||||
mse.console.print(`Sending compiled script to GUI sequencer...`);
|
else {
|
||||||
seq.clear();
|
seq.setLight(x, light.color);
|
||||||
mse.mscript.toGUI();
|
}
|
||||||
grid.refresh();
|
}
|
||||||
seq.stats();
|
else {
|
||||||
return nav.change('sequencer');
|
//unset light?
|
||||||
|
}
|
||||||
|
grid.state(x);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Handles compilation of mscript and switches to sequencer
|
||||||
|
* GUI after confirmation questions.
|
||||||
|
**/
|
||||||
|
toSequence() {
|
||||||
|
const data = this.editor.getValue();
|
||||||
|
let cont = false;
|
||||||
|
if (data !== this.raw) {
|
||||||
|
cont = confirm(`Current script has not been compiled. Compile first?`);
|
||||||
|
if (cont) {
|
||||||
|
this.compile();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
mse.console.print(`Sending compiled script to GUI sequencer...`);
|
||||||
|
seq.clear();
|
||||||
|
this.toGUI();
|
||||||
|
grid.refresh();
|
||||||
|
seq.stats();
|
||||||
|
return nav.change('sequencer');
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Compiles text in editor using the Mscript library.
|
||||||
|
*
|
||||||
|
**/
|
||||||
|
compile() {
|
||||||
|
const data = this.editor.getValue();
|
||||||
|
const mscript = new mscript_1.Mscript();
|
||||||
|
const output = mscript.interpret(data);
|
||||||
|
const len = output.arr.length;
|
||||||
|
const cam2 = typeof output.cam2 !== 'undefined' ? `, CAM2 : ${output.cam2}` : '';
|
||||||
|
const proj2 = typeof output.proj2 !== 'undefined' ? `, PROJ2 : ${output.proj2}` : '';
|
||||||
|
const report = `Sequence contains ${len} step${(len === 1 ? '' : 's')}, CAM: ${output.cam}, PROJ: ${output.proj}${cam2}${proj2}`;
|
||||||
|
this.raw = data;
|
||||||
|
this.data = output;
|
||||||
|
//mse.console.print(JSON.stringify(output, null, '\t') + '\n')
|
||||||
|
mse.console.print(report);
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* This function re-writes the optional "meta" attribute
|
||||||
|
* of an mcopy command object to "light". TODO: change this.
|
||||||
|
* Do not re-write this object and improve the consumers
|
||||||
|
* of the compiled data.
|
||||||
|
**/
|
||||||
|
prepare() {
|
||||||
|
const arr = [];
|
||||||
|
let obj;
|
||||||
|
for (let i = 0; i < this.data.arr.length; i++) {
|
||||||
|
obj = {
|
||||||
|
cmd: this.data.arr[i]
|
||||||
|
};
|
||||||
|
if (typeof this.data.meta[i] !== 'undefined' && this.data.meta[i] !== '') {
|
||||||
|
obj.light = this.data.meta[i];
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
obj.light = light.color.join(',');
|
||||||
|
}
|
||||||
|
arr.push(obj);
|
||||||
|
}
|
||||||
|
return arr;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Method which compiles script if needs and then runs as a sequence.
|
||||||
|
**/
|
||||||
|
run() {
|
||||||
|
const data = this.editor.getValue();
|
||||||
|
let arr;
|
||||||
|
let cont = false;
|
||||||
|
if (data !== this.raw) {
|
||||||
|
cont = confirm(`Current script has not been compiled. Compile first?`);
|
||||||
|
if (cont) {
|
||||||
|
this.compile();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
arr = this.prepare();
|
||||||
|
mse.console.print(`Started running compiled sequence...`);
|
||||||
|
gui.overlay(true);
|
||||||
|
gui.spinner(true, `Running mscript sequence...`, true, true);
|
||||||
|
return seq.exec(arr, 1);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
mse.mscript.compile = function () {
|
|
||||||
'use strict';
|
|
||||||
const data = mse.mscript.editor.getValue();
|
|
||||||
const mscript = new Mscript();
|
|
||||||
let output = mscript.interpret(data);
|
|
||||||
let len = output.arr.length;
|
|
||||||
const cam2 = typeof output.cam2 !== 'undefined' ? `, CAM2 : ${output.cam2}` : '';
|
|
||||||
const proj2 = typeof output.proj2 !== 'undefined' ? `, PROJ2 : ${output.proj2}` : '';
|
|
||||||
|
|
||||||
mse.mscript.raw = data;
|
|
||||||
mse.mscript.data = output;
|
|
||||||
//mse.console.print(JSON.stringify(output, null, '\t') + '\n')
|
|
||||||
mse.console.print(`Sequence contains ${len} step${(len === 1 ? '' : 's')}, CAM: ${output.cam}, PROJ: ${output.proj}${cam2}${proj2}`);
|
|
||||||
};
|
|
||||||
|
|
||||||
mse.mscript.prepare = function () {
|
|
||||||
'use strict';
|
|
||||||
const arr = [];
|
|
||||||
let obj;
|
|
||||||
for (let i = 0; i < mse.mscript.data.arr.length; i++) {
|
|
||||||
obj = {
|
|
||||||
cmd : mse.mscript.data.arr[i]
|
|
||||||
};
|
|
||||||
if (typeof mse.mscript.data.meta[i] !== 'undefined' && mse.mscript.data.meta[i] !== '') {
|
|
||||||
obj.light = mse.mscript.data.meta[i];
|
|
||||||
} else {
|
|
||||||
obj.light = light.color.join(',');
|
|
||||||
}
|
|
||||||
arr.push(obj);
|
|
||||||
}
|
|
||||||
return arr;
|
|
||||||
};
|
|
||||||
|
|
||||||
mse.mscript.run = function () {
|
|
||||||
'use strict';
|
|
||||||
const data = mse.mscript.editor.getValue();
|
|
||||||
let arr;
|
|
||||||
let cont;
|
|
||||||
if (data !== mse.mscript.raw) {
|
|
||||||
cont = confirm(`Current script has not been compiled. Compile first?`);
|
|
||||||
if (cont) {
|
|
||||||
mse.mscript.compile();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
arr = mse.mscript.prepare();
|
|
||||||
mse.console.print(`Started running compiled sequence...`);
|
|
||||||
gui.overlay(true);
|
|
||||||
gui.spinner(true, `Running mscript sequence...`, true, true);
|
|
||||||
return seq.exec(arr, 1);
|
|
||||||
};
|
|
||||||
|
|
||||||
/*******
|
/*******
|
||||||
* gui console
|
* Mscript GUI Console
|
||||||
*******/
|
*******/
|
||||||
mse.console = {};
|
class MscriptConsole {
|
||||||
mse.console.elem = {};
|
/**
|
||||||
mse.console.init = function () {
|
* Initializes the console by creating the element
|
||||||
'use script';
|
* containing the output text and binding to
|
||||||
mse.console.elem = $('#console textarea');
|
* keyup event.
|
||||||
mse.console.elem.on('keyup', function (e) {
|
**/
|
||||||
var code = e.keyCode || e.which;
|
init() {
|
||||||
if (code === 13) {
|
this.elem = $('#console textarea');
|
||||||
mse.console.exec();
|
this.elem.on('keyup', function (e) {
|
||||||
e.preventDefault();
|
var code = e.keyCode || e.which;
|
||||||
return false;
|
if (code === 13) {
|
||||||
}
|
this.exec();
|
||||||
});
|
e.preventDefault();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}.bind(this));
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Parse the current state of the console and get the last
|
||||||
|
* line to add to the current state array.
|
||||||
|
**/
|
||||||
|
parse() {
|
||||||
|
const lines = (this.elem.val() + '').split('\n');
|
||||||
|
const line = lines[lines.length - 2].replace('>', '').trim();
|
||||||
|
this.lines.push(line);
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Executes the command in the last line of the console.
|
||||||
|
* TODO: implement the remaining commands. Currently only camera
|
||||||
|
* forward and backward will be executed.
|
||||||
|
**/
|
||||||
|
exec() {
|
||||||
|
let command;
|
||||||
|
this.parse();
|
||||||
|
command = this.lines[this.lines.length - 1].replace('>', '').trim();
|
||||||
|
log.info(command);
|
||||||
|
this.newLine();
|
||||||
|
if (mscript.cmd.indexOf(command) !== -1) {
|
||||||
|
if (command === 'CF') {
|
||||||
|
cmd.camera_forward(light.color);
|
||||||
|
}
|
||||||
|
else if (cmd === 'CB') {
|
||||||
|
cmd.camera_backward(light.color);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (command === 'compile') {
|
||||||
|
mse.mscript.compile();
|
||||||
|
}
|
||||||
|
else if (command === 'run') {
|
||||||
|
mse.mscript.run();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Adds a new line to the console after an event
|
||||||
|
* and re-establishes the height of the array. Animates
|
||||||
|
* the console to scroll down to last line.
|
||||||
|
**/
|
||||||
|
newLine() {
|
||||||
|
let current = (this.elem.val() + '');
|
||||||
|
let height;
|
||||||
|
current += '> ';
|
||||||
|
this.elem.val(current);
|
||||||
|
height = this.elem[0].scrollHeight;
|
||||||
|
this.elem.animate({
|
||||||
|
scrollTop: height
|
||||||
|
}, 'normal');
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Print string to the console and add new line
|
||||||
|
**/
|
||||||
|
print(str) {
|
||||||
|
let current = (this.elem.val() + '');
|
||||||
|
let height;
|
||||||
|
current += str;
|
||||||
|
mse.console.elem.val(current);
|
||||||
|
mse.console.elem.focus();
|
||||||
|
this.newLine();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const mse = {
|
||||||
|
mscript: new MscriptGUI(),
|
||||||
|
console: new MscriptConsole()
|
||||||
};
|
};
|
||||||
mse.console.lines = [];
|
module.exports = mse;
|
||||||
mse.console.parse = function () {
|
//# sourceMappingURL=mscript.js.map
|
||||||
'use strict';
|
|
||||||
const lines = mse.console.elem.val().split('\n');
|
|
||||||
const line = lines[lines.length - 2].replace('>', '').trim();
|
|
||||||
mse.console.lines.push(line);
|
|
||||||
};
|
|
||||||
|
|
||||||
mse.console.exec = function () {
|
|
||||||
'use strict';
|
|
||||||
let command;
|
|
||||||
mse.console.parse();
|
|
||||||
command = mse.console.lines[mse.console.lines.length - 1].replace('>', '').trim();
|
|
||||||
log.info(command);
|
|
||||||
mse.console.newLine();
|
|
||||||
if (mscript.cmd.indexOf(command) !== -1) {
|
|
||||||
if (command === 'CF') {
|
|
||||||
cmd.camera_forward(light.color);
|
|
||||||
} else if (cmd === 'CB') {
|
|
||||||
cmd.camera_backward(light.color);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (command === 'compile') {
|
|
||||||
mse.mscript.compile();
|
|
||||||
} else if (command === 'run') {
|
|
||||||
mse.mscript.run();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
mse.console.newLine = function () {
|
|
||||||
'use strict';
|
|
||||||
let current = mse.console.elem.val();
|
|
||||||
let height;
|
|
||||||
current += '> ';
|
|
||||||
mse.console.elem.val(current);
|
|
||||||
height = mse.console.elem[0].scrollHeight;
|
|
||||||
mse.console.elem.animate({
|
|
||||||
scrollTop : height
|
|
||||||
},'normal');
|
|
||||||
};
|
|
||||||
|
|
||||||
mse.console.print = function (str) {
|
|
||||||
'use strict'
|
|
||||||
let current = mse.console.elem.val();
|
|
||||||
let height;
|
|
||||||
current += str;
|
|
||||||
current += '\n> ';
|
|
||||||
mse.console.elem.val(current);
|
|
||||||
mse.console.elem.focus();
|
|
||||||
|
|
||||||
height = mse.console.elem[0].scrollHeight;
|
|
||||||
mse.console.elem.animate({
|
|
||||||
scrollTop : height
|
|
||||||
},'normal');
|
|
||||||
};
|
|
||||||
|
|
||||||
module.exports = mse;
|
|
File diff suppressed because one or more lines are too long
|
@ -51,6 +51,7 @@
|
||||||
"winston": "^3.7.2"
|
"winston": "^3.7.2"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
"@types/codemirror": "^5.60.5",
|
||||||
"@types/jquery": "^3.5.14",
|
"@types/jquery": "^3.5.14",
|
||||||
"chai": "^4.3.6",
|
"chai": "^4.3.6",
|
||||||
"electron": "^19.0.1",
|
"electron": "^19.0.1",
|
||||||
|
@ -1045,12 +1046,27 @@
|
||||||
"@types/responselike": "*"
|
"@types/responselike": "*"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/@types/codemirror": {
|
||||||
|
"version": "5.60.5",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/codemirror/-/codemirror-5.60.5.tgz",
|
||||||
|
"integrity": "sha512-TiECZmm8St5YxjFUp64LK0c8WU5bxMDt9YaAek1UqUb9swrSCoJhh92fWu1p3mTEqlHjhB5sY7OFBhWroJXZVg==",
|
||||||
|
"dev": true,
|
||||||
|
"dependencies": {
|
||||||
|
"@types/tern": "*"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/@types/color-name": {
|
"node_modules/@types/color-name": {
|
||||||
"version": "1.1.1",
|
"version": "1.1.1",
|
||||||
"resolved": "https://registry.npmjs.org/@types/color-name/-/color-name-1.1.1.tgz",
|
"resolved": "https://registry.npmjs.org/@types/color-name/-/color-name-1.1.1.tgz",
|
||||||
"integrity": "sha512-rr+OQyAjxze7GgWrSaJwydHStIhHq2lvY3BOC2Mj7KnzI7XK0Uw1TOOdI9lDoajEbSWLiYgoo4f1R51erQfhPQ==",
|
"integrity": "sha512-rr+OQyAjxze7GgWrSaJwydHStIhHq2lvY3BOC2Mj7KnzI7XK0Uw1TOOdI9lDoajEbSWLiYgoo4f1R51erQfhPQ==",
|
||||||
"devOptional": true
|
"devOptional": true
|
||||||
},
|
},
|
||||||
|
"node_modules/@types/estree": {
|
||||||
|
"version": "1.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.0.tgz",
|
||||||
|
"integrity": "sha512-WulqXMDUTYAXCjZnk6JtIHPigp55cVtDgDrO2gHRwhyJto21+1zbVCtOYB2L1F9w4qCQ0rOGWBnBe0FNTiEJIQ==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
"node_modules/@types/fs-extra": {
|
"node_modules/@types/fs-extra": {
|
||||||
"version": "9.0.1",
|
"version": "9.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/@types/fs-extra/-/fs-extra-9.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/@types/fs-extra/-/fs-extra-9.0.1.tgz",
|
||||||
|
@ -1120,6 +1136,15 @@
|
||||||
"integrity": "sha512-7EJYyKTL7tFR8+gDbB6Wwz/arpGa0Mywk1TJbNzKzHtzbwVmY4HR9WqS5VV7dsBUKQmPNr192jHr/VpBluj/hg==",
|
"integrity": "sha512-7EJYyKTL7tFR8+gDbB6Wwz/arpGa0Mywk1TJbNzKzHtzbwVmY4HR9WqS5VV7dsBUKQmPNr192jHr/VpBluj/hg==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"node_modules/@types/tern": {
|
||||||
|
"version": "0.23.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/tern/-/tern-0.23.4.tgz",
|
||||||
|
"integrity": "sha512-JAUw1iXGO1qaWwEOzxTKJZ/5JxVeON9kvGZ/osgZaJImBnyjyn0cjovPsf6FNLmyGY8Vw9DoXZCMlfMkMwHRWg==",
|
||||||
|
"dev": true,
|
||||||
|
"dependencies": {
|
||||||
|
"@types/estree": "*"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/@types/yauzl": {
|
"node_modules/@types/yauzl": {
|
||||||
"version": "2.9.1",
|
"version": "2.9.1",
|
||||||
"resolved": "https://registry.npmjs.org/@types/yauzl/-/yauzl-2.9.1.tgz",
|
"resolved": "https://registry.npmjs.org/@types/yauzl/-/yauzl-2.9.1.tgz",
|
||||||
|
@ -12125,12 +12150,27 @@
|
||||||
"@types/responselike": "*"
|
"@types/responselike": "*"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"@types/codemirror": {
|
||||||
|
"version": "5.60.5",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/codemirror/-/codemirror-5.60.5.tgz",
|
||||||
|
"integrity": "sha512-TiECZmm8St5YxjFUp64LK0c8WU5bxMDt9YaAek1UqUb9swrSCoJhh92fWu1p3mTEqlHjhB5sY7OFBhWroJXZVg==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"@types/tern": "*"
|
||||||
|
}
|
||||||
|
},
|
||||||
"@types/color-name": {
|
"@types/color-name": {
|
||||||
"version": "1.1.1",
|
"version": "1.1.1",
|
||||||
"resolved": "https://registry.npmjs.org/@types/color-name/-/color-name-1.1.1.tgz",
|
"resolved": "https://registry.npmjs.org/@types/color-name/-/color-name-1.1.1.tgz",
|
||||||
"integrity": "sha512-rr+OQyAjxze7GgWrSaJwydHStIhHq2lvY3BOC2Mj7KnzI7XK0Uw1TOOdI9lDoajEbSWLiYgoo4f1R51erQfhPQ==",
|
"integrity": "sha512-rr+OQyAjxze7GgWrSaJwydHStIhHq2lvY3BOC2Mj7KnzI7XK0Uw1TOOdI9lDoajEbSWLiYgoo4f1R51erQfhPQ==",
|
||||||
"devOptional": true
|
"devOptional": true
|
||||||
},
|
},
|
||||||
|
"@types/estree": {
|
||||||
|
"version": "1.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.0.tgz",
|
||||||
|
"integrity": "sha512-WulqXMDUTYAXCjZnk6JtIHPigp55cVtDgDrO2gHRwhyJto21+1zbVCtOYB2L1F9w4qCQ0rOGWBnBe0FNTiEJIQ==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
"@types/fs-extra": {
|
"@types/fs-extra": {
|
||||||
"version": "9.0.1",
|
"version": "9.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/@types/fs-extra/-/fs-extra-9.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/@types/fs-extra/-/fs-extra-9.0.1.tgz",
|
||||||
|
@ -12200,6 +12240,15 @@
|
||||||
"integrity": "sha512-7EJYyKTL7tFR8+gDbB6Wwz/arpGa0Mywk1TJbNzKzHtzbwVmY4HR9WqS5VV7dsBUKQmPNr192jHr/VpBluj/hg==",
|
"integrity": "sha512-7EJYyKTL7tFR8+gDbB6Wwz/arpGa0Mywk1TJbNzKzHtzbwVmY4HR9WqS5VV7dsBUKQmPNr192jHr/VpBluj/hg==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"@types/tern": {
|
||||||
|
"version": "0.23.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/tern/-/tern-0.23.4.tgz",
|
||||||
|
"integrity": "sha512-JAUw1iXGO1qaWwEOzxTKJZ/5JxVeON9kvGZ/osgZaJImBnyjyn0cjovPsf6FNLmyGY8Vw9DoXZCMlfMkMwHRWg==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"@types/estree": "*"
|
||||||
|
}
|
||||||
|
},
|
||||||
"@types/yauzl": {
|
"@types/yauzl": {
|
||||||
"version": "2.9.1",
|
"version": "2.9.1",
|
||||||
"resolved": "https://registry.npmjs.org/@types/yauzl/-/yauzl-2.9.1.tgz",
|
"resolved": "https://registry.npmjs.org/@types/yauzl/-/yauzl-2.9.1.tgz",
|
||||||
|
|
|
@ -35,6 +35,7 @@
|
||||||
},
|
},
|
||||||
"homepage": "https://github.com/sixteenmillimeter/mcopy#readme",
|
"homepage": "https://github.com/sixteenmillimeter/mcopy#readme",
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
"@types/codemirror": "^5.60.5",
|
||||||
"@types/jquery": "^3.5.14",
|
"@types/jquery": "^3.5.14",
|
||||||
"chai": "^4.3.6",
|
"chai": "^4.3.6",
|
||||||
"electron": "^19.0.1",
|
"electron": "^19.0.1",
|
||||||
|
|
|
@ -0,0 +1,320 @@
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
/// <reference path ="jquery.d.ts"/>
|
||||||
|
|
||||||
|
import { Mscript } from 'mscript';
|
||||||
|
|
||||||
|
declare var nav : any;
|
||||||
|
declare var gui : any;
|
||||||
|
declare var CodeMirror : any;
|
||||||
|
declare var mscript : any;
|
||||||
|
declare var cmd : any;
|
||||||
|
|
||||||
|
interface MSE {
|
||||||
|
mscript : MscriptGUI,
|
||||||
|
console : MscriptConsole
|
||||||
|
}
|
||||||
|
|
||||||
|
/******
|
||||||
|
Mscript GUI
|
||||||
|
*******/
|
||||||
|
|
||||||
|
class MscriptGUI {
|
||||||
|
public editor : any = {};
|
||||||
|
public data : any = {};
|
||||||
|
public raw : string = '';
|
||||||
|
|
||||||
|
constructor () {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initializes the mscript GUI. Sets up CodeMirror instance,
|
||||||
|
* binds events and sets height of editor.
|
||||||
|
**/
|
||||||
|
public init () {
|
||||||
|
const startingScript : string = `CF 1
|
||||||
|
PF 1`;
|
||||||
|
const editorHeight : number = $(window).height() - $('footer').eq(0).height() - 30;
|
||||||
|
const editorElem : HTMLTextAreaElement = document.getElementById('editor') as HTMLTextAreaElement;
|
||||||
|
const editorConfig : any = {
|
||||||
|
lineNumbers: true,
|
||||||
|
mode: 'python',
|
||||||
|
matchBrackets: true,
|
||||||
|
theme: 'monokai'
|
||||||
|
};
|
||||||
|
$('#editor').val(startingScript);
|
||||||
|
this.editor = CodeMirror.fromTextArea(editorElem, editorConfig);
|
||||||
|
this.editor.setSize(null, editorHeight);
|
||||||
|
this.editor.on('change', (e : Event) => { });
|
||||||
|
$(document).on('resize', function (e : Event) {
|
||||||
|
this.editor.setSize(null, editorHeight);
|
||||||
|
}.bind(this));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Callback for when open event occurs.
|
||||||
|
**/
|
||||||
|
public open () {
|
||||||
|
//recalcuate in case resize has occurred needed
|
||||||
|
const editorHeight : number = $(window).height() - $('footer').eq(0).height() - 30;
|
||||||
|
this.editor.setSize(null, editorHeight);
|
||||||
|
this.editor.refresh();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create script from the sequencer's current state.
|
||||||
|
* Previous comment: ehhhh
|
||||||
|
* TODO: Make this smarter.
|
||||||
|
**/
|
||||||
|
fromSequence () {
|
||||||
|
let str : string;
|
||||||
|
let tmp : any[] = [];
|
||||||
|
let cont : boolean;
|
||||||
|
let cmd : string;
|
||||||
|
|
||||||
|
//str = seq.grid.map(step => { return step.cmd }).join('\n'); //quick hack
|
||||||
|
//console.dir(seq.grid);
|
||||||
|
|
||||||
|
for (let step of seq.grid) {
|
||||||
|
if (!step || !step.cmd) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
cmd = step.cmd;
|
||||||
|
if (tmp.length > 0 && tmp[tmp.length - 1].cmd === cmd) {
|
||||||
|
tmp[tmp.length - 1].num++;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
tmp.push({ cmd, num : 1 });
|
||||||
|
}
|
||||||
|
|
||||||
|
tmp = tmp.map(line => {
|
||||||
|
return `${line.cmd} ${line.num}`
|
||||||
|
})
|
||||||
|
|
||||||
|
if (seq.gridLoops > 1) {
|
||||||
|
tmp.map(line => {
|
||||||
|
return ` ${line}`;
|
||||||
|
})
|
||||||
|
tmp.reverse();
|
||||||
|
tmp.push(`LOOP ${seq.gridLoops}`);
|
||||||
|
tmp.reverse();
|
||||||
|
tmp.push('END');
|
||||||
|
}
|
||||||
|
|
||||||
|
str = tmp.join('\n');
|
||||||
|
|
||||||
|
nav.change('script');
|
||||||
|
cont = confirm(`Are you sure you want to over-write the current sequence?`);
|
||||||
|
if (cont) {
|
||||||
|
this.editor.getDoc().setValue(str);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Take current compiled mscript state and send it to the sequencer
|
||||||
|
* GUI. TODO: Add confirm step if sequence is longer than X steps.
|
||||||
|
* TODO: Make this smarter (detect outer non-fade loop and assign to loop counter)
|
||||||
|
**/
|
||||||
|
toGUI () {
|
||||||
|
let c : string;
|
||||||
|
let step : string;
|
||||||
|
for (let x : number = 0; x < this.data.arr.length; x++) {
|
||||||
|
c = this.data.arr[x];
|
||||||
|
seq.set(x, c);
|
||||||
|
if (c === 'CF' || c === 'CB') {
|
||||||
|
if (typeof this.data.meta[x] !== 'undefined' && this.data.meta[x] !== '') {
|
||||||
|
seq.setLight(x, this.data.meta[x]);
|
||||||
|
} else {
|
||||||
|
seq.setLight(x, light.color);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
//unset light?
|
||||||
|
}
|
||||||
|
grid.state(x);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handles compilation of mscript and switches to sequencer
|
||||||
|
* GUI after confirmation questions.
|
||||||
|
**/
|
||||||
|
toSequence () {
|
||||||
|
const data : string = this.editor.getValue();
|
||||||
|
let cont : boolean = false;
|
||||||
|
if (data !== this.raw) {
|
||||||
|
cont = confirm(`Current script has not been compiled. Compile first?`);
|
||||||
|
if (cont) {
|
||||||
|
this.compile()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
mse.console.print(`Sending compiled script to GUI sequencer...`);
|
||||||
|
seq.clear();
|
||||||
|
this.toGUI();
|
||||||
|
grid.refresh();
|
||||||
|
seq.stats();
|
||||||
|
return nav.change('sequencer');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Compiles text in editor using the Mscript library.
|
||||||
|
*
|
||||||
|
**/
|
||||||
|
compile () {
|
||||||
|
const data : string = this.editor.getValue();
|
||||||
|
const mscript : Mscript = new Mscript();
|
||||||
|
const output : any = mscript.interpret(data);
|
||||||
|
const len : number = output.arr.length;
|
||||||
|
const cam2 : string = typeof output.cam2 !== 'undefined' ? `, CAM2 : ${output.cam2}` : '';
|
||||||
|
const proj2 : string = typeof output.proj2 !== 'undefined' ? `, PROJ2 : ${output.proj2}` : '';
|
||||||
|
const report : string = `Sequence contains ${len} step${(len === 1 ? '' : 's')}, CAM: ${output.cam}, PROJ: ${output.proj}${cam2}${proj2}`;
|
||||||
|
|
||||||
|
this.raw = data;
|
||||||
|
this.data = output;
|
||||||
|
//mse.console.print(JSON.stringify(output, null, '\t') + '\n')
|
||||||
|
mse.console.print(report);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This function re-writes the optional "meta" attribute
|
||||||
|
* of an mcopy command object to "light". TODO: change this.
|
||||||
|
* Do not re-write this object and improve the consumers
|
||||||
|
* of the compiled data.
|
||||||
|
**/
|
||||||
|
prepare () {
|
||||||
|
const arr : any[] = [];
|
||||||
|
let obj : any;
|
||||||
|
for (let i : number = 0; i < this.data.arr.length; i++) {
|
||||||
|
obj = {
|
||||||
|
cmd : this.data.arr[i]
|
||||||
|
};
|
||||||
|
if (typeof this.data.meta[i] !== 'undefined' && this.data.meta[i] !== '') {
|
||||||
|
obj.light = this.data.meta[i];
|
||||||
|
} else {
|
||||||
|
obj.light = light.color.join(',');
|
||||||
|
}
|
||||||
|
arr.push(obj);
|
||||||
|
}
|
||||||
|
return arr;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Method which compiles script if needs and then runs as a sequence.
|
||||||
|
**/
|
||||||
|
run () {
|
||||||
|
const data : string = this.editor.getValue();
|
||||||
|
let arr : any[];
|
||||||
|
let cont : boolean = false;
|
||||||
|
if (data !== this.raw) {
|
||||||
|
cont = confirm(`Current script has not been compiled. Compile first?`);
|
||||||
|
if (cont) {
|
||||||
|
this.compile();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
arr = this.prepare();
|
||||||
|
mse.console.print(`Started running compiled sequence...`);
|
||||||
|
gui.overlay(true);
|
||||||
|
gui.spinner(true, `Running mscript sequence...`, true, true);
|
||||||
|
return seq.exec(arr, 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*******
|
||||||
|
* Mscript GUI Console
|
||||||
|
*******/
|
||||||
|
|
||||||
|
class MscriptConsole {
|
||||||
|
public elem : JQuery;
|
||||||
|
private lines : string[];
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initializes the console by creating the element
|
||||||
|
* containing the output text and binding to
|
||||||
|
* keyup event.
|
||||||
|
**/
|
||||||
|
public init () {
|
||||||
|
this.elem = $('#console textarea');
|
||||||
|
this.elem.on('keyup', function (e : KeyboardEvent) {
|
||||||
|
var code : number = e.keyCode || e.which;
|
||||||
|
if (code === 13) {
|
||||||
|
this.exec();
|
||||||
|
e.preventDefault();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}.bind(this));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parse the current state of the console and get the last
|
||||||
|
* line to add to the current state array.
|
||||||
|
**/
|
||||||
|
parse () {
|
||||||
|
const lines : string[] = (this.elem.val() + '').split('\n');
|
||||||
|
const line : string = lines[lines.length - 2].replace('>', '').trim();
|
||||||
|
this.lines.push(line);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Executes the command in the last line of the console.
|
||||||
|
* TODO: implement the remaining commands. Currently only camera
|
||||||
|
* forward and backward will be executed.
|
||||||
|
**/
|
||||||
|
exec () {
|
||||||
|
let command : string;
|
||||||
|
this.parse();
|
||||||
|
command = this.lines[this.lines.length - 1].replace('>', '').trim();
|
||||||
|
log.info(command);
|
||||||
|
this.newLine();
|
||||||
|
if (mscript.cmd.indexOf(command) !== -1) {
|
||||||
|
if (command === 'CF') {
|
||||||
|
cmd.camera_forward(light.color);
|
||||||
|
} else if (cmd === 'CB') {
|
||||||
|
cmd.camera_backward(light.color);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (command === 'compile') {
|
||||||
|
mse.mscript.compile();
|
||||||
|
} else if (command === 'run') {
|
||||||
|
mse.mscript.run();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds a new line to the console after an event
|
||||||
|
* and re-establishes the height of the array. Animates
|
||||||
|
* the console to scroll down to last line.
|
||||||
|
**/
|
||||||
|
newLine () {
|
||||||
|
let current : string = (this.elem.val() + '');
|
||||||
|
let height : number;
|
||||||
|
current += '> ';
|
||||||
|
this.elem.val(current);
|
||||||
|
height = this.elem[0].scrollHeight;
|
||||||
|
this.elem.animate({
|
||||||
|
scrollTop : height
|
||||||
|
}, 'normal');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Print string to the console and add new line
|
||||||
|
**/
|
||||||
|
print (str : string) {
|
||||||
|
let current : string = (this.elem.val() + '');
|
||||||
|
let height : number;
|
||||||
|
current += str;
|
||||||
|
mse.console.elem.val(current);
|
||||||
|
mse.console.elem.focus();
|
||||||
|
|
||||||
|
this.newLine();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const mse : MSE = {
|
||||||
|
mscript : new MscriptGUI(),
|
||||||
|
console : new MscriptConsole()
|
||||||
|
};
|
||||||
|
|
||||||
|
module.exports = mse;
|
|
@ -11,7 +11,8 @@
|
||||||
"outDir": "./",
|
"outDir": "./",
|
||||||
"rootDir" : "./src/",
|
"rootDir" : "./src/",
|
||||||
"paths" : {
|
"paths" : {
|
||||||
"log" : ["./lib/log"]
|
"log" : ["./lib/log"],
|
||||||
|
"mscript" : ["./lib/mscript"]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"exclude" : [
|
"exclude" : [
|
||||||
|
|
|
@ -72,8 +72,8 @@ const ALTS : any = {
|
||||||
'PBPF' : [ ]
|
'PBPF' : [ ]
|
||||||
};
|
};
|
||||||
|
|
||||||
const PAUSE = 'PAUSE';
|
const PAUSE : string = 'PAUSE';
|
||||||
const ALERT = 'ALERT';
|
const ALERT : string = 'ALERT';
|
||||||
|
|
||||||
/** helper functions */
|
/** helper functions */
|
||||||
|
|
||||||
|
@ -86,20 +86,24 @@ const ALERT = 'ALERT';
|
||||||
**/
|
**/
|
||||||
function startsWith (str : string, target : string, position? : number) : boolean {
|
function startsWith (str : string, target : string, position? : number) : boolean {
|
||||||
const { length } = str;
|
const { length } = str;
|
||||||
|
|
||||||
position = position == null ? 0 : position;
|
position = position == null ? 0 : position;
|
||||||
|
|
||||||
if (position < 0) {
|
if (position < 0) {
|
||||||
position = 0;
|
position = 0;
|
||||||
} else if (position > length) {
|
} else if (position > length) {
|
||||||
position = length;
|
position = length;
|
||||||
}
|
}
|
||||||
|
|
||||||
target = `${target}`;
|
target = `${target}`;
|
||||||
|
|
||||||
return str.slice(position, position + target.length) == target;
|
return str.slice(position, position + target.length) == target;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** class Mscript */
|
/** class Mscript */
|
||||||
class Mscript {
|
export class Mscript {
|
||||||
output : any;
|
output : any;
|
||||||
lines : any[];
|
lines : string[];
|
||||||
cam : number;
|
cam : number;
|
||||||
cam2 : number;
|
cam2 : number;
|
||||||
proj : number;
|
proj : number;
|
||||||
|
@ -159,7 +163,7 @@ class Mscript {
|
||||||
*
|
*
|
||||||
* @returns {object} if callback is not provided
|
* @returns {object} if callback is not provided
|
||||||
*/
|
*/
|
||||||
interpret (text : string, callback : Function) {
|
interpret (text : string, callback : Function = null) {
|
||||||
this.clear()
|
this.clear()
|
||||||
|
|
||||||
if (typeof text === 'undefined') {
|
if (typeof text === 'undefined') {
|
||||||
|
@ -228,7 +232,7 @@ class Mscript {
|
||||||
this.output.proj2 = this.proj2;
|
this.output.proj2 = this.proj2;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (typeof callback !== 'undefined') {
|
if (typeof callback !== 'undefined' && callback != null) {
|
||||||
//should only be invoked by running mscript.tests()
|
//should only be invoked by running mscript.tests()
|
||||||
callback(this.output);
|
callback(this.output);
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -7,6 +7,7 @@
|
||||||
"moduleResolution": "node",
|
"moduleResolution": "node",
|
||||||
"sourceMap": true,
|
"sourceMap": true,
|
||||||
"removeComments" : false,
|
"removeComments" : false,
|
||||||
|
"declaration" : true,
|
||||||
"baseUrl" : "lib",
|
"baseUrl" : "lib",
|
||||||
"outDir": "./lib/",
|
"outDir": "./lib/",
|
||||||
"rootDir" : "./src/",
|
"rootDir" : "./src/",
|
||||||
|
|
Loading…
Reference in New Issue