|
// these are DOM elements |
|
var main_canvas; |
|
var pos1_slider; |
|
var tilt1_slider; |
|
var pos2_slider; |
|
var tilt2_slider; |
|
var pos3_slider; |
|
var tilt3_slider; |
|
var sel_char; |
|
var sel_mode; |
|
|
|
// constant for initialization |
|
var canvasWidth = 960; |
|
var canvasHeight = 500; |
|
|
|
// this is the variable that holds all character objects |
|
var letterParams = null; |
|
var letterParamsDebug = { |
|
"A": { |
|
"box1": { |
|
"position": -174, |
|
"tilt": -47 |
|
}, |
|
"box2": { |
|
"position": -104, |
|
"tilt": -4 |
|
}, |
|
"box3": { |
|
"position": -121, |
|
"tilt": 58 |
|
} |
|
}, |
|
"B": { |
|
"box1": { |
|
"position": -191, |
|
"tilt": -90 |
|
}, |
|
"box2": { |
|
"position": -54, |
|
"tilt": -45 |
|
}, |
|
"box3": { |
|
"position": -12, |
|
"tilt": 6 |
|
} |
|
}, |
|
"C": { |
|
"box1": { |
|
"position": -163, |
|
"tilt": -84 |
|
}, |
|
"box2": { |
|
"position": -191, |
|
"tilt": 163 |
|
}, |
|
"box3": { |
|
"position": 0, |
|
"tilt": -27 |
|
} |
|
}, |
|
} |
|
|
|
// the sliders will write to this location |
|
var debugLetter = "9"; |
|
|
|
// Handy string of all letters available |
|
var letters = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"; |
|
|
|
// DrawMode can be "solo" or "alphabet" |
|
var initialDrawMode = "exhibit"; |
|
var curDrawMode; |
|
|
|
// these variables are used for animation |
|
var soloCurLetter = "1"; |
|
var soloPrevObj = null; |
|
var soloIsAnimating = false; |
|
var soloNumAnimationFrames = 60; |
|
var soloCurAnimationFrame = 0; |
|
|
|
var chosenLettersDebug = ["C", "C", "C", "C", "C", "C", "C", "C"]; |
|
var chosenLetters = ["C", "O", "N", "F", "E", "T", "T", "I"]; |
|
var chosenPrevObjs = [null, null, null, null, null, null, null, null]; |
|
var chosenIsAnimating = [false, false, false, false, false, false, false, false]; |
|
var chosenNumAnimationFrames = 30; |
|
var chosenCurAnimationFrame = [0, 0, 0, 0, 0, 0, 0, 0]; |
|
var curChosenLetter = 0; |
|
|
|
var lastKeyPressedTime; |
|
var secondsUntilSwapMode = 15; |
|
var lastWordSwappedTime; |
|
var isSwappingWords = true; |
|
var secondsPerWord = 8; |
|
var curSwapWord = 0; |
|
var swapWordsDebug = [ |
|
"CCCCCCCC", |
|
"AAAAAAAA", |
|
"BBBBBBBB" |
|
] |
|
var swapWords = [ |
|
"CONFETTI", |
|
"ACTUALLY", |
|
"EXPECTED", |
|
"PROPERTY", |
|
"ADDITION", |
|
"FOLLOWED", |
|
"PROVIDED", |
|
"ALTHOUGH", |
|
"HAPPENED", |
|
"QUESTION", |
|
"AMERICAN", |
|
"INCREASE", |
|
"RECEIVED", |
|
"ANYTHING", |
|
"INDUSTRY", |
|
"RELIGION", |
|
"BUILDING", |
|
"INTEREST", |
|
"REMEMBER", |
|
"BUSINESS", |
|
"INVOLVED", |
|
"REQUIRED", |
|
"CHILDREN", |
|
"NATIONAL", |
|
"SERVICES", |
|
"COMPLETE", |
|
"ORGANIZE", |
|
"SOUTHERN", |
|
"CONSIDER", |
|
"PERSONAL", |
|
"STANDARD", |
|
"CONTINUE", |
|
"PLANNING", |
|
"STRENGTH", |
|
"ALPHABET", |
|
"POSITION", |
|
"STUDENTS", |
|
"DECISION", |
|
"POSSIBLE", |
|
"SUDDENLY", |
|
"DIRECTLY", |
|
"PRESSURE", |
|
"THINKING", |
|
"DISTRICT", |
|
"PROBABLY", |
|
"TOGETHER", |
|
"ECONOMIC", |
|
"PROBLEMS", |
|
"TRAINING", |
|
"EVIDENCE", |
|
"PROGRAMS" |
|
] |
|
|
|
function preload() { |
|
// sometimes when debugging, letterParams is initialized locally |
|
if(letterParams == null) { |
|
letterParams = loadJSON('letters.json'); |
|
} |
|
} |
|
|
|
function make_interface() { |
|
// create two sliders |
|
pos1_slider = createSlider(-200, 200, 0); |
|
tilt1_slider = createSlider(-180, 180, 0); |
|
pos2_slider = createSlider(-200, 200, 0); |
|
tilt2_slider = createSlider(-180, 180, 0); |
|
pos3_slider = createSlider(-200, 200, 0); |
|
tilt3_slider = createSlider(-180, 180, 0); |
|
|
|
sel_char = createSelect(); |
|
for (var i = 0, len = letters.length; i < len; i++) { |
|
sel_char.option(letters[i]); |
|
} |
|
sel_char.changed(letterChangedEvent); |
|
|
|
sel_mode = createSelect(); |
|
sel_mode.option("alphabet"); |
|
sel_mode.option("solo"); |
|
sel_mode.option("exhibit"); |
|
sel_mode.changed(modeChangedEvent); |
|
sel_mode.value(initialDrawMode); |
|
|
|
button = createButton('show data'); |
|
button.mousePressed(buttonPressedEvent); |
|
|
|
// var button2 = createButton('random data'); |
|
// button2.mousePressed(randomData); |
|
pos1_slider.parent('slider1Container'); |
|
tilt1_slider.parent('slider2Container'); |
|
pos2_slider.parent('slider3Container'); |
|
tilt2_slider.parent('slider4Container'); |
|
pos3_slider.parent('slider5Container'); |
|
tilt3_slider.parent('slider6Container'); |
|
|
|
sel_char.parent('selectorContainer'); |
|
sel_mode.parent('modeContainer'); |
|
button.parent('buttonContainer'); |
|
// button2.parent(buttonContainer); |
|
|
|
dataObjectToSliders(letterParams[debugLetter]) |
|
} |
|
|
|
function setup () { |
|
// create the drawing canvas, save the canvas element |
|
main_canvas = createCanvas(canvasWidth, canvasHeight); |
|
|
|
// rotation in degrees (more slider friendly) |
|
angleMode(DEGREES); |
|
curDrawMode = initialDrawMode; |
|
|
|
var now = millis(); |
|
lastKeyPressedTime = now; |
|
lastWordSwappedTime = now; |
|
|
|
// position each element on the page |
|
main_canvas.parent('canvasContainer'); |
|
|
|
if(initialDrawMode != "exhibit") { |
|
make_interface(); |
|
} |
|
} |
|
|
|
// Generate a random set of letters. |
|
// This was useful to generate placeholders. |
|
// They are output to the html. |
|
function randomData() { |
|
var o = {}; |
|
for (var i = 0, len = letters.length; i < len; i++) { |
|
var obj = {} |
|
obj["box1"] = {}; |
|
obj["box1"]["position"] = Math.round(random(-20, 20)); |
|
obj["box1"]["tilt"] = Math.round(random(-30, 30)); |
|
obj["box2"] = {}; |
|
obj["box2"]["position"] = Math.round(random(-20, 20)); |
|
obj["box2"]["tilt"] = Math.round(random(-30, 30)); |
|
obj["box3"] = {}; |
|
obj["box3"]["position"] = Math.round(random(-20, 20)); |
|
obj["box3"]["tilt"] = Math.round(random(-30, 30)); |
|
o[letters[i]] = obj; |
|
} |
|
var text = select('#output'); |
|
var json = JSON.stringify(o, null, 2); |
|
text.html(json) |
|
} |
|
|
|
// Take all values from the slider and generate a data object |
|
// that represents one character in the alphabet. |
|
function sliderToDataObject() { |
|
var obj = {}; |
|
obj["box1"] = {}; |
|
obj["box1"]["position"] = pos1_slider.value(); |
|
obj["box1"]["tilt"] = tilt1_slider.value(); |
|
obj["box2"] = {}; |
|
obj["box2"]["position"] = pos2_slider.value(); |
|
obj["box2"]["tilt"] = tilt2_slider.value(); |
|
obj["box3"] = {}; |
|
obj["box3"]["position"] = pos3_slider.value(); |
|
obj["box3"]["tilt"] = tilt3_slider.value(); |
|
return obj; |
|
} |
|
|
|
// Given a data object representing a character, adjust |
|
// the sliders appropiately. |
|
function dataObjectToSliders(obj) { |
|
pos1_slider.value(obj["box1"]["position"]); |
|
tilt1_slider.value(obj["box1"]["tilt"]); |
|
pos2_slider.value(obj["box2"]["position"]); |
|
tilt2_slider.value(obj["box2"]["tilt"]); |
|
pos3_slider.value(obj["box3"]["position"]); |
|
tilt3_slider.value(obj["box3"]["tilt"]); |
|
} |
|
|
|
// Funcation called when DOM letter selector is changed |
|
function letterChangedEvent() { |
|
var item = sel_char.value(); |
|
dataObjectToSliders(letterParams[item]); |
|
} |
|
|
|
// Funcation called when DOM mode selector is changed |
|
function modeChangedEvent() { |
|
curDrawMode = sel_mode.value(); |
|
} |
|
|
|
// Function called when "show data" button is pressed. |
|
// Presents a single JSON object in the HTML. |
|
function buttonPressedEvent() { |
|
var obj = letterParams[debugLetter] |
|
var json = JSON.stringify(obj, null, 2); |
|
var text = select('#output'); |
|
text.html(json) |
|
} |
|
|
|
// global front and back colors |
|
var colorFront = [207, 222, 227]; |
|
var colorBack = [29, 42, 46]; |
|
|
|
// draws one of the three rectangles of a character |
|
function drawPart(y_offset, pos, tilt) { |
|
push(); |
|
translate(pos, y_offset); |
|
rotate(tilt); |
|
|
|
var scale = 10; |
|
|
|
fill(colorFront); |
|
rect(-20*scale, -3*scale, 20*scale, 3*scale); |
|
pop(); |
|
} |
|
|
|
// draws a single character given an object, position, and scale |
|
function drawFromDataObject(x, y, s, obj) { |
|
push(); |
|
translate(x, y); |
|
scale(s, s); |
|
drawPart(-50, obj["box1"]["position"], obj["box1"]["tilt"]); |
|
drawPart( 0, obj["box2"]["position"], obj["box2"]["tilt"]); |
|
drawPart( 50, obj["box3"]["position"], obj["box3"]["tilt"]); |
|
pop(); |
|
} |
|
|
|
function computeCurrentSoloChar() { |
|
// now figure out what object to draw |
|
var obj; |
|
if (soloIsAnimating) { |
|
nextObj = letterParams[soloCurLetter]; |
|
// interpolation logic here |
|
obj = {}; |
|
obj["box1"] = {}; |
|
obj["box1"]["position"] = map(soloCurAnimationFrame, 0, soloNumAnimationFrames, soloPrevObj["box1"]["position"], nextObj["box1"]["position"]) |
|
obj["box1"]["tilt"] = map(soloCurAnimationFrame, 0, soloNumAnimationFrames, soloPrevObj["box1"]["tilt"], nextObj["box1"]["tilt"]) |
|
obj["box2"] = {}; |
|
obj["box2"]["position"] = map(soloCurAnimationFrame, 0, soloNumAnimationFrames, soloPrevObj["box2"]["position"], nextObj["box2"]["position"]) |
|
obj["box2"]["tilt"] = map(soloCurAnimationFrame, 0, soloNumAnimationFrames, soloPrevObj["box2"]["tilt"], nextObj["box2"]["tilt"]) |
|
obj["box3"] = {}; |
|
obj["box3"]["position"] = map(soloCurAnimationFrame, 0, soloNumAnimationFrames, soloPrevObj["box3"]["position"], nextObj["box3"]["position"]) |
|
obj["box3"]["tilt"] = map(soloCurAnimationFrame, 0, soloNumAnimationFrames, soloPrevObj["box3"]["tilt"], nextObj["box3"]["tilt"]) |
|
} |
|
else { |
|
obj = letterParams[soloCurLetter]; |
|
} |
|
return obj; |
|
} |
|
|
|
function computeCurrentChosenChar(n) { |
|
// now figure out what object to draw |
|
var obj; |
|
if (chosenIsAnimating[n]) { |
|
if(chosenCurAnimationFrame[n] < 0) { |
|
obj = chosenPrevObjs[n]; |
|
} |
|
else { |
|
nextObj = letterParams[chosenLetters[n]]; |
|
// interpolation logic here |
|
obj = {}; |
|
obj["box1"] = {}; |
|
obj["box1"]["position"] = map(chosenCurAnimationFrame[n], 0, chosenNumAnimationFrames, chosenPrevObjs[n]["box1"]["position"], nextObj["box1"]["position"]) |
|
obj["box1"]["tilt"] = map(chosenCurAnimationFrame[n], 0, chosenNumAnimationFrames, chosenPrevObjs[n]["box1"]["tilt"], nextObj["box1"]["tilt"]) |
|
obj["box2"] = {}; |
|
obj["box2"]["position"] = map(chosenCurAnimationFrame[n], 0, chosenNumAnimationFrames, chosenPrevObjs[n]["box2"]["position"], nextObj["box2"]["position"]) |
|
obj["box2"]["tilt"] = map(chosenCurAnimationFrame[n], 0, chosenNumAnimationFrames, chosenPrevObjs[n]["box2"]["tilt"], nextObj["box2"]["tilt"]) |
|
obj["box3"] = {}; |
|
obj["box3"]["position"] = map(chosenCurAnimationFrame[n], 0, chosenNumAnimationFrames, chosenPrevObjs[n]["box3"]["position"], nextObj["box3"]["position"]) |
|
obj["box3"]["tilt"] = map(chosenCurAnimationFrame[n], 0, chosenNumAnimationFrames, chosenPrevObjs[n]["box3"]["tilt"], nextObj["box3"]["tilt"]) |
|
} |
|
} |
|
else { |
|
obj = letterParams[chosenLetters[n]]; |
|
} |
|
return obj; |
|
} |
|
|
|
// var lastKeyPressedTime; |
|
// var secondsUntilSwapMode = 30; |
|
// var lastWordSwappedTime; |
|
// var isSwappingWords = true; |
|
// var secondsPerWord = 5; |
|
// var curSwapWord = 0; |
|
// var swapWords = [ |
|
|
|
function draw () { |
|
// update debug letter from sliders |
|
if(curDrawMode != "exhibit") { |
|
letterParams[debugLetter] = sliderToDataObject(); |
|
} |
|
|
|
now = millis(); |
|
// check to see if we should go into swapping mode |
|
if(!isSwappingWords && lastKeyPressedTime + 1000 * secondsUntilSwapMode < now) { |
|
isSwappingWords = true; |
|
} |
|
|
|
if(isSwappingWords) { |
|
if(lastWordSwappedTime + 1000 * secondsPerWord < now) { |
|
lastWordSwappedTime = now; |
|
curSwapWord = (curSwapWord + 1) % swapWords.length; |
|
for(var i=0; i<8; i++) { |
|
var c = swapWords[curSwapWord][i]; |
|
swapExhibitLetter(i, c, 6*i); |
|
} |
|
} |
|
} |
|
|
|
background(colorBack); |
|
fill(colorFront); |
|
stroke(95, 52, 8); |
|
|
|
// shorthand variables to allow margin |
|
var o = 40 |
|
var w2 = width - 2 * o |
|
var h2 = height - 2 * o |
|
if (curDrawMode == "alphabet") { |
|
var cur_index = 0; |
|
var hw = (w2 / 9.0) / 2.0; |
|
var hh = (h2 / 4.0) / 2.0; |
|
for(var j=0; j<4; j++) { |
|
for(var i=0; i<9; i++) { |
|
var cur_letter = letters[cur_index]; |
|
var obj = letterParams[cur_letter]; |
|
drawFromDataObject(o + hw + i * w2/9.0, o + hh + j * h2/4.0, 0.20, obj) |
|
cur_index = cur_index + 1; |
|
} |
|
} |
|
} |
|
else if (curDrawMode == "solo") { |
|
// see if animation should be turned off |
|
if(soloIsAnimating && soloCurAnimationFrame >= soloNumAnimationFrames) { |
|
soloIsAnimating = false; |
|
} |
|
// if we are animating, increment the number of animation frames |
|
if(soloIsAnimating) { |
|
soloCurAnimationFrame = soloCurAnimationFrame + 1; |
|
} |
|
var obj = computeCurrentSoloChar(); |
|
drawFromDataObject(o + w2/2.0, o + h2/2.0, 1.0, obj) |
|
} |
|
else if (curDrawMode == "exhibit") { |
|
for(var i=0; i<8; i++) { |
|
// see if animation should be turned off |
|
if(chosenIsAnimating[i] && chosenCurAnimationFrame[i] >= chosenNumAnimationFrames) { |
|
chosenIsAnimating[i] = false; |
|
} |
|
// if we are animating, increment the number of animation frames |
|
if(chosenIsAnimating[i]) { |
|
chosenCurAnimationFrame[i] = chosenCurAnimationFrame[i] + 1; |
|
} |
|
var obj = computeCurrentChosenChar(i); |
|
drawFromDataObject(o + w2/10.0 + i*w2/8.0, o + h2/2.0, 0.25, obj) |
|
} |
|
} |
|
} |
|
|
|
function swapExhibitLetter(n, c, frameDelay) { |
|
chosenPrevObjs[n] = computeCurrentChosenChar(n); |
|
chosenLetters[n] = c; |
|
chosenIsAnimating[n] = true; |
|
chosenCurAnimationFrame[n] = 0 - frameDelay; |
|
} |
|
|
|
function keyTyped() { |
|
if (key == '!') { |
|
saveBlocksImages(); |
|
} |
|
else if (key == '@') { |
|
saveBlocksImages(true); |
|
} |
|
else { |
|
lastKeyPressedTime = millis(); |
|
if(isSwappingWords) { |
|
isSwappingWords = false; |
|
} |
|
upper_key = key.toUpperCase(); |
|
if (upper_key in letterParams) { |
|
if(curDrawMode == "solo") { |
|
soloPrevObj = computeCurrentSoloChar(); |
|
soloCurLetter = upper_key; |
|
soloIsAnimating = true; |
|
soloCurAnimationFrame = 0; |
|
} |
|
else if(curDrawMode == "alphabet") { |
|
sel_char.value(upper_key); |
|
dataObjectToSliders(letterParams[upper_key]); |
|
} |
|
else if(curDrawMode == "exhibit") { |
|
swapExhibitLetter(curChosenLetter, upper_key, 0); |
|
curChosenLetter = (curChosenLetter + 1) % 8; |
|
} |
|
} |
|
} |
|
} |