|
// outlets: input index, output index, connection value |
|
outlets = 3; |
|
|
|
sketch.default2d(); |
|
|
|
// I/O count, should be an argument |
|
var num_ins = 4; |
|
var num_outs = 4; |
|
|
|
// mouse state (world coordinates) |
|
var wx = 0; |
|
var wy = 0; |
|
|
|
// colors |
|
var Color = Object.freeze({ |
|
"in_on" : [0.5, 1.0, 0.5, 1.0], |
|
"in_off" : [0.7, 0.8, 0.7, 1.0], |
|
"in_hover" : [0.8, 1.0, 0.8, 1.0], |
|
"out_on" : [1.0, 0.5, 0.5, 1.0], |
|
"out_off" : [0.8, 0.7, 0.7, 1.0], |
|
"out_hover" : [1.0, 0.8, 0.8, 1.0] |
|
}); |
|
|
|
var in_bounds = []; |
|
var out_bounds = []; |
|
|
|
var patched = []; |
|
|
|
var in_connected = []; |
|
var out_connected= []; |
|
var in_hover = []; |
|
var out_hover = []; |
|
|
|
|
|
for(i=0; i<num_ins; i++) { |
|
patched[i] = []; |
|
for(j=0; j<num_outs; j++) { |
|
patched[i][j] = false; |
|
} |
|
} |
|
|
|
// interaction state |
|
var ui_state = { |
|
"is_patching": false, |
|
"in_anchor": -1, |
|
"out_anchor": -1 |
|
}; |
|
|
|
function reset_ui_state() { |
|
ui_state.is_patching = false; |
|
ui_state.in_anchor = -1; |
|
ui_state.out_anchor = -1; |
|
} |
|
|
|
//--------------------------------- |
|
// event handlers |
|
function onresize(width, height) { |
|
set_node_bounds(); |
|
} |
|
|
|
function onidle(x, y) { |
|
var pos = sketch.screentoworld(x, y); |
|
wx = pos[0]; |
|
wy = pos[1]; |
|
for(i=0; i<num_ins; i++) { |
|
in_hover[i] = check_node_bounds(in_bounds[i], pos); |
|
} |
|
for(i=0; i<num_outs; i++) { |
|
out_hover[i] = check_node_bounds(out_bounds[i], pos); |
|
} |
|
redraw(); |
|
} |
|
|
|
function onclick(x, y) { |
|
var pos = sketch.screentoworld(x, y); |
|
for(i=0; i<num_ins; i++) { |
|
if (check_node_bounds(in_bounds[i], pos)) { |
|
do_input(i); |
|
} |
|
} |
|
for(i=0; i<num_outs; i++) { |
|
if(check_node_bounds(out_bounds[i], pos)) { |
|
do_output(i); |
|
} |
|
} |
|
} |
|
|
|
function onidleout() { |
|
reset_ui_state(); |
|
} |
|
|
|
//--------------------------------- |
|
//--- "controller logic" (ha) |
|
|
|
function do_input(i) { |
|
if(ui_state.is_patching) { |
|
if(ui_state.in_anchor != -1) { |
|
ui_state.in_anchor = i; |
|
} else { |
|
if(ui_state.out_anchor != -1) { |
|
ui_state.in_anchor = i; |
|
do_patch(); |
|
} else { |
|
// shouldn't get here |
|
} |
|
} |
|
} else { |
|
ui_state.is_patching = true; |
|
ui_state.in_anchor = i; |
|
ui_state.out_anchor = -1; |
|
} |
|
} |
|
|
|
function do_output(j) { |
|
if(ui_state.is_patching) { |
|
if(ui_state.out_anchor != -1) { |
|
ui_state.out_anchor = j; |
|
} else { |
|
if(ui_state.in_anchor != -1) { |
|
ui_state.out_anchor = j; |
|
do_patch(); |
|
} else { |
|
// shouldn't get here |
|
} |
|
} |
|
} else { |
|
ui_state.is_patching = true; |
|
ui_state.in_anchor = -1; |
|
ui_state.out_anchor = j; |
|
} |
|
|
|
} |
|
|
|
function do_patch() { |
|
var i = ui_state.in_anchor; |
|
var j = ui_state.out_anchor; |
|
var val; |
|
if (patched[i][j]) { |
|
patched[i][j] = false; |
|
val = 0; |
|
} |
|
else { |
|
patched[i][j] = true; |
|
val = 1; |
|
} |
|
reset_ui_state(); |
|
outlet(2, val); |
|
outlet(1, j); |
|
outlet(0, i); |
|
} |
|
|
|
//----------------- |
|
//--- helpers |
|
|
|
// calculate bounding boxes for I/O nodes (world coordinates) |
|
function set_node_bounds() { |
|
var in_w = (2.0 / num_ins); // leaving no space at all, lookin dumb |
|
var in_h = 0.2; |
|
for (i=0; i<num_ins; i++) { |
|
var l = (i * in_w) - 1.0; |
|
in_bounds[i] = {"left":l, "right":l+in_w, "top":1, "bottom":1-in_h}; |
|
post(in_bounds[i].left, in_bounds[i].right, in_bounds[i].top, in_bounds[i].bottom); |
|
in_connected[i] = false; |
|
in_hover[i] = false; |
|
} |
|
|
|
var out_w = (2.0 / num_ins); |
|
var out_h = 0.2; |
|
for (i=0; i<num_outs; i++) { |
|
var l = (i * out_w) - 1.0; |
|
out_bounds[i] = {"left":l, "right":l+out_w, "top":out_h - 1, "bottom":-1.0}; |
|
out_connected[i] = false; |
|
out_hover[i] = false; |
|
} |
|
} |
|
|
|
function check_node_bounds(b, pos) { |
|
var x = pos[0]; |
|
var y = pos[1]; |
|
return ((x >= b.left) && (x <= b.right) && (y <= b.top) && (y >= b.bottom)); |
|
} |
|
|
|
function get_in_coords(i) { |
|
var b = in_bounds[i]; |
|
return [b.left + (b.right - b.left) / 2, b.bottom]; |
|
} |
|
|
|
function get_out_coords(j) { |
|
var b = out_bounds[j]; |
|
return [b.left + (b.right - b.left) / 2, b.top]; |
|
} |
|
|
|
//------------------------ |
|
//--- drawing |
|
|
|
function redraw() { |
|
with(sketch) { |
|
glclearcolor([1.0, 1.0, 1.0, 1.0]); |
|
glclear(); |
|
|
|
// draw input nodes |
|
for(i=0; i<num_ins; i++) { |
|
var b = in_bounds[i]; |
|
// choose appropriate color based on input state |
|
if(in_hover[i]) { |
|
glcolor(Color.in_hover); |
|
} else { |
|
if(in_connected[i]) { |
|
glcolor(Color.in_on); |
|
} else { |
|
glcolor(Color.in_off); |
|
} |
|
} |
|
// draw filled quad |
|
quad(b.left, b.top, 0, b.right, b.top, 0, b.right, b.bottom, 0, b.left, b.bottom, 0); |
|
// draw black bounding box |
|
glcolor(0.0, 0.0, 0.0, 1.0); |
|
framequad(b.left, b.top, 0, b.right, b.top, 0, b.right, b.bottom, 0, b.left, b.bottom, 0); |
|
} |
|
|
|
// draw output nodes |
|
for(i=0; i<num_ins; i++) { |
|
var b = out_bounds[i]; |
|
// choose appropriate color based on input state |
|
if(out_hover[i]) { |
|
glcolor(Color.out_hover); |
|
} else { |
|
if(out_connected[i]) { |
|
glcolor(Color.out_on); |
|
} else { |
|
glcolor(Color.out_off); |
|
} |
|
} |
|
// draw filled quad |
|
quad(b.left, b.top, 0, b.right, b.top, 0, b.right, b.bottom, 0, b.left, b.bottom, 0); |
|
// draw black bounding box |
|
glcolor(0.0, 0.0, 0.0, 1.0); |
|
framequad(b.left, b.top, 0, b.right, b.top, 0, b.right, b.bottom, 0, b.left, b.bottom, 0); |
|
} |
|
|
|
// draw existing patch cables |
|
for(i=0; i<num_ins; i++) { |
|
for(j=0; j<num_outs; j++) { |
|
if(patched[i][j]) { |
|
var a = get_in_coords(i); |
|
var b = get_out_coords(j); |
|
moveto(a[0], a[1]); |
|
lineto(b[0], b[1]); |
|
} |
|
} |
|
} |
|
|
|
// draw current patch cable |
|
if(ui_state.is_patching) { |
|
var a, b; |
|
if(ui_state.in_anchor != -1) { |
|
a = get_in_coords(ui_state.in_anchor); |
|
b = [wx, wy]; |
|
} else { |
|
a = [wx, wy]; |
|
b = get_out_coords(ui_state.out_anchor); |
|
} |
|
moveto(a[0], a[1]); |
|
lineto(b[0], b[1]); |
|
} |
|
} |
|
refresh(); |
|
|
|
} |
|
|
|
set_node_bounds(); |
|
redraw(); |