REPLACE ALL TEXT IN THIS FILE
This README should eventually explain the different paramaterised faces.
. |
/* | |
* This program draws your arrangement of faces on the canvas. | |
*/ | |
const canvasWidth = 960; | |
const canvasHeight = 500; | |
let curRandomSeed = 0; | |
let lastSwapTime = 0; | |
const millisPerSwap = 3000; | |
function setup () { | |
// create the drawing canvas, save the canvas element | |
let main_canvas = createCanvas(canvasWidth, canvasHeight); | |
main_canvas.parent('canvasContainer'); | |
curRandomSeed = int(random(0, 1000)); | |
// rotation in degrees | |
angleMode(DEGREES); | |
} | |
function changeRandomSeed() { | |
curRandomSeed = curRandomSeed + 1; | |
lastSwapTime = millis(); | |
} | |
// global variables for colors | |
const bg_color1 = [225, 206, 187]; | |
function mouseClicked() { | |
changeRandomSeed(); | |
} | |
function draw () { | |
if(millis() > lastSwapTime + millisPerSwap) { | |
changeRandomSeed(); | |
} | |
// reset the random number generator each time draw is called | |
randomSeed(curRandomSeed); | |
// clear screen | |
background(bg_color1); | |
noStroke(); | |
// draw a 7x4 grid of faces | |
let w = canvasWidth / 7; | |
let h = canvasHeight / 4; | |
for(let i=0; i<4; i++) { | |
for(let j=0; j<7; j++) { | |
let y = h/2 + h*i; | |
let x = w/2 + w*j; | |
if (i == 0) { | |
// center face | |
let eye_value = 2; | |
let tilt_value = random(-15, 45); | |
let mouth_value = random(1, 3); | |
let is_cyclops = random(0, 100); | |
if(is_cyclops < 10) { | |
eye_value = 1; | |
tilt_value = random(-5, 5); | |
mouth_value = random(5, 10); | |
} | |
push(); | |
translate(x, y); | |
scale(w/25, h/25); | |
drawFace3(tilt_value, eye_value, mouth_value); | |
pop(); | |
} | |
else if (i > 0) { | |
// all other faces | |
push(); | |
translate(x, y); | |
scale(w/25, h/25); | |
if((i+j)%2 == 0) { | |
drawFace1(); | |
} | |
else { | |
thinness_value = random(0, 100); | |
drawFace2(thinness_value); | |
} | |
pop(); | |
} | |
} | |
} | |
} | |
function keyTyped() { | |
if (key == '!') { | |
saveBlocksImages(); | |
} | |
else if (key == '@') { | |
saveBlocksImages(true); | |
} | |
} |
<head> | |
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.4.0/p5.js"></script> | |
<script language="javascript" type="text/javascript" src="z_purview_helper.js"></script> | |
<script language="javascript" type="text/javascript" src="face_code.js"></script> | |
<script language="javascript" type="text/javascript" src="editor.js"></script> | |
<style> | |
body { padding: 0; margin: 0; } | |
.inner { position: absolute; } | |
#controls { | |
font: 300 12px "Helvetica Neue"; | |
padding: 5; | |
margin: 5; | |
background: #f0f0f0; | |
opacity: 0.0; | |
-webkit-transition: opacity 0.2s ease; | |
-moz-transition: opacity 0.2s ease; | |
-o-transition: opacity 0.2s ease; | |
-ms-transition: opacity 0.2s ease; | |
} | |
#controls:hover { opacity: 0.9; } | |
</style> | |
</head> | |
<body style="background-color:white"> | |
<div class="outer"> | |
<div class="inner"> | |
<div id="canvasContainer"></div> | |
<a href="index.html">arrangement</a> | |
(<a href="arrangement.js">arrangement code</a>, | |
<a href="face_code.js">face code</a>)<br> | |
<a href="editor.html">editor</a> | |
(<a href="editor.js">editor code</a>, | |
<a href="face_code.js">face code</a>)<br> | |
<a href="sketch.html">sketch</a> | |
</div> | |
<div class="inner" id="controls" height="500px"> | |
<table> | |
<tr> | |
<td>Setting 1</td> | |
<td id="slider1Container"></td> | |
</tr> | |
<tr> | |
<td>Setting 2</td> | |
<td id="slider2Container"></td> | |
</tr> | |
<tr> | |
<td>Setting 3</td> | |
<td id="slider3Container"></td> | |
</tr> | |
<tr> | |
<td>Setting 4</td> | |
<td id="slider4Container"></td> | |
</tr> | |
<tr> | |
<td>Setting 5</td> | |
<td id="slider5Container"></td> | |
</tr> | |
<tr> | |
<td>Setting 6</td> | |
<td id="slider6Container"></td> | |
</tr> | |
<tr> | |
<td>Setting 7</td> | |
<td id="slider7Container"></td> | |
</tr> | |
<tr> | |
<td>Setting 8</td> | |
<td id="slider8Container"></td> | |
</tr> | |
<tr> | |
<td>Setting 9</td> | |
<td id="slider9Container"></td> | |
</tr> | |
<tr> | |
<td>Setting 10</td> | |
<td id="slider10Container"></td> | |
</tr> | |
<tr> | |
<td>Show Target</td> | |
<td id="checkbox1Container"></td> | |
</tr> | |
<tr> | |
<td>Face</td> | |
<td id="selector1Container"></td> | |
</tr> | |
</table> | |
</div> | |
</div> | |
</table> | |
</body> |
/* | |
* This editor shows the possible faces that can be created | |
*/ | |
const canvasWidth = 960; | |
const canvasHeight = 500; | |
let slider1, slider2, slider3, slider4, slider5; | |
let slider6, slider7, slider8, slider9, slider10; | |
let faceSelector; | |
let faceGuideCheckbox; | |
function setup () { | |
// create the drawing canvas, save the canvas element | |
let main_canvas = createCanvas(canvasWidth, canvasHeight); | |
main_canvas.parent('canvasContainer'); | |
// create sliders | |
slider1 = createSlider(0, 100, 50); | |
slider2 = createSlider(0, 100, 50); | |
slider3 = createSlider(0, 100, 50); | |
slider4 = createSlider(0, 100, 50); | |
slider5 = createSlider(0, 100, 50); | |
slider6 = createSlider(0, 100, 50); | |
slider7 = createSlider(0, 100, 50); | |
slider8 = createSlider(0, 100, 50); | |
slider9 = createSlider(0, 100, 50); | |
slider10 = createSlider(0, 100, 50); | |
slider1.parent('slider1Container'); | |
slider2.parent('slider2Container'); | |
slider3.parent('slider3Container'); | |
slider4.parent('slider4Container'); | |
slider5.parent('slider5Container'); | |
slider6.parent('slider6Container'); | |
slider7.parent('slider7Container'); | |
slider8.parent('slider8Container'); | |
slider9.parent('slider9Container'); | |
slider10.parent('slider10Container'); | |
faceGuideCheckbox = createCheckbox('', false); | |
faceGuideCheckbox.parent('checkbox1Container'); | |
faceSelector = createSelect(); | |
faceSelector.option('1'); | |
faceSelector.option('2'); | |
faceSelector.option('3'); | |
faceSelector.value('1'); | |
faceSelector.parent('selector1Container'); | |
} | |
const bg_color = [225, 206, 187]; | |
function draw () { | |
strokeWeight(0.2); | |
let mode = faceSelector.value(); | |
background(bg_color); | |
let s1 = slider1.value(); | |
let s2 = slider2.value(); | |
let s3 = slider3.value(); | |
let s4 = slider4.value(); | |
let s5 = slider5.value(); | |
let s6 = slider6.value(); | |
let s7 = slider7.value(); | |
let s8 = slider8.value(); | |
let s9 = slider9.value(); | |
let s10 = slider10.value(); | |
let show_face_guide = faceGuideCheckbox.checked(); | |
// use same size / y_pos for all faces | |
let face_size = canvasWidth / 5; | |
let face_scale = face_size / 10; | |
let face_y = height / 2; | |
let face_x = width / 2; | |
push(); | |
translate(face_x, face_y); | |
scale(face_scale); | |
push(); | |
if (mode == '1') { | |
// draw 1st face | |
drawFace1(); | |
} | |
if (mode == '2') { | |
// draw 2nd face - let slider value 1 indicate thinness | |
drawFace2(s1); | |
} | |
if (mode == '3') { | |
// draw 3rd face using values mapped from 3 sliders | |
let tilt_value = map(s1, 0, 100, -90, 90); | |
let mouth_value = map(s2, 0, 100, 0.5, 10); | |
let eye_value = int(map(s3, 0, 100, 1, 3)); | |
drawFace3(tilt_value, eye_value, mouth_value); | |
} | |
pop(); | |
if(show_face_guide) { | |
strokeWeight(0.1); | |
rectMode(CORNER); | |
noFill() | |
stroke(0, 0, 255); | |
// ellipse(0, 0, 20, 20); | |
rect(-10, -10, 20, 20); | |
line( 0, -11, 0, -10); | |
line( 0, 10, 0, 11); | |
line(-11, 0,-10, 0); | |
line( 11, 0, 10, 0); | |
} | |
pop(); | |
} | |
function keyTyped() { | |
if (key == '!') { | |
saveBlocksImages(); | |
} | |
else if (key == '@') { | |
saveBlocksImages(true); | |
} | |
} |
/* | |
* This file should contain code that draws your faces. | |
* | |
* Each function takes parameters and draws a face that is within | |
* the bounding box (-10, -10) to (10, 10). | |
* | |
* These functions are used by your final arrangement of faces as well as the face editor. | |
*/ | |
function drawFace1() { | |
fill(60); | |
noStroke(); | |
// head | |
ellipse(0, 0, 20); | |
// eyes | |
fill(200); | |
ellipse(-3, -3, 3); | |
ellipse( 3, -3, 3); | |
} | |
/* | |
* thinness_value ranges from 0-100 and indicates how thin the face is | |
*/ | |
function drawFace2(thinness_value) { | |
// head | |
noStroke(); | |
fill(200, 150, 150); | |
let head_width = map(thinness_value, 0, 100, 8, 20); | |
rect(-head_width/2, -9, head_width, 18); | |
// rect(-5, -10, 10, 20); | |
// eyes | |
fill(240); | |
ellipse(-2, -4, 1); | |
ellipse( 2, -4, 1); | |
} | |
/* | |
* tilt_value is in degrees | |
* eye_value is an integer number of eyes: either 0, 1, 2, or 3 | |
* mouth_value is how open the mouth is and should generally range from 0.5 to 10 | |
*/ | |
function drawFace3(tilt_value, eye_value, mouth_value) { | |
const bg_color3 = [225, 206, 187]; | |
const fg_color3 = [151, 102, 52]; | |
// rotation in degrees | |
angleMode(DEGREES); | |
rotate(tilt_value); | |
noStroke(); | |
fill(fg_color3); | |
ellipse(0, 0, 30/2, 40/2); | |
// eyes | |
if (eye_value === 1 || eye_value == 3) { | |
fill(bg_color3); | |
ellipse( 0, -8/2, 5/2, 3/2); | |
fill(fg_color3); | |
ellipse(-1/2, -8/2, 2/2, 2/2); | |
} | |
if (eye_value >= 2) { | |
fill(bg_color3); | |
ellipse(-5/2, -8/2, 5/2, 3/2); | |
ellipse( 5/2, -8/2, 5/2, 3/2); | |
fill(fg_color3); | |
ellipse(-6/2, -8/2, 2/2, 2/2); | |
ellipse( 4/2, -8/2, 2/2, 2/2); | |
} | |
// mouth | |
fill(bg_color3); | |
ellipse(0/2, 7/2, 15/2, mouth_value); | |
} |
<head> | |
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.4.0/p5.js"></script> | |
<script language="javascript" type="text/javascript" src="z_purview_helper.js"></script> | |
<script language="javascript" type="text/javascript" src="face_code.js"></script> | |
<script language="javascript" type="text/javascript" src="arrangement.js"></script> | |
<style> | |
body { padding: 0; margin: 0; } | |
.inner { position: absolute; } | |
#controls { | |
font: 300 12px "Helvetica Neue"; | |
padding: 5; | |
margin: 5; | |
background: #f0f0f0; | |
opacity: 0.0; | |
-webkit-transition: opacity 0.2s ease; | |
-moz-transition: opacity 0.2s ease; | |
-o-transition: opacity 0.2s ease; | |
-ms-transition: opacity 0.2s ease; | |
} | |
#controls:hover { opacity: 0.9; } | |
</style> | |
</head> | |
<body style="background-color:white"> | |
<div class="outer"> | |
<div class="inner"> | |
<div id="canvasContainer"></div> | |
<a href="index.html">arrangement</a> | |
(<a href="arrangement.js">arrangement code</a>, | |
<a href="face_code.js">face code</a>)<br> | |
<a href="editor.html">editor</a> | |
(<a href="editor.js">editor code</a>, | |
<a href="face_code.js">face code</a>)<br> | |
<a href="sketch.html">sketch</a> | |
</div> | |
<div class="inner" id="controls" height="500px"> | |
<table> | |
<tr> | |
<td></td> | |
<td id="slider1Container"></td> | |
</tr> | |
<tr> | |
<td></td> | |
<td id="slider2Container"></td> | |
</tr> | |
<tr> | |
<td></td> | |
<td id="slider3Container"></td> | |
</tr> | |
<tr> | |
<td></td> | |
<td id="slider4Container"></td> | |
</tr> | |
<tr> | |
<td></td> | |
<td id="slider5Container"></td> | |
</tr> | |
<tr> | |
<td></td> | |
<td id="selector1Container"></td> | |
</tr> | |
</table> | |
</div> | |
</div> | |
</table> | |
</body> |
<head> | |
<style> body {padding: 0; margin: 0;} </style> | |
</head> | |
<body style="background-color:white"> | |
<img src="sketch.jpg" width="960" height="480"/> | |
<p> | |
<a href="index.html">arrangement</a> | |
(<a href="arrangement.js">arrangement code</a>, | |
<a href="face_code.js">face code</a>)<br> | |
<a href="editor.html">editor</a> | |
(<a href="editor.js">editor code</a>, | |
<a href="face_code.js">face code</a>)<br> | |
<a href="sketch.html">sketch</a> | |
</body> |
// note: this file is poorly named - it can generally be ignored. | |
// helper functions below for supporting blocks/purview | |
function saveBlocksImages(doZoom) { | |
if(doZoom == null) { | |
doZoom = false; | |
} | |
// generate 960x500 preview.jpg of entire canvas | |
// TODO: should this be recycled? | |
var offscreenCanvas = document.createElement('canvas'); | |
offscreenCanvas.width = 960; | |
offscreenCanvas.height = 500; | |
var context = offscreenCanvas.getContext('2d'); | |
// background is flat white | |
context.fillStyle="#FFFFFF"; | |
context.fillRect(0, 0, 960, 500); | |
context.drawImage(this.canvas, 0, 0, 960, 500); | |
// save to browser | |
var downloadMime = 'image/octet-stream'; | |
var imageData = offscreenCanvas.toDataURL('image/jpeg'); | |
imageData = imageData.replace('image/jpeg', downloadMime); | |
p5.prototype.downloadFile(imageData, 'preview.jpg', 'jpg'); | |
// generate 230x120 thumbnail.png centered on mouse | |
offscreenCanvas.width = 230; | |
offscreenCanvas.height = 120; | |
// background is flat white | |
context = offscreenCanvas.getContext('2d'); | |
context.fillStyle="#FFFFFF"; | |
context.fillRect(0, 0, 230, 120); | |
if(doZoom) { | |
// pixelDensity does the right thing on retina displays | |
var pd = this._pixelDensity; | |
var sx = pd * mouseX - pd * 230/2; | |
var sy = pd * mouseY - pd * 120/2; | |
var sw = pd * 230; | |
var sh = pd * 120; | |
// bounds checking - just displace if necessary | |
if (sx < 0) { | |
sx = 0; | |
} | |
if (sx > this.canvas.width - sw) { | |
sx = this.canvas.width - sw; | |
} | |
if (sy < 0) { | |
sy = 0; | |
} | |
if (sy > this.canvas.height - sh) { | |
sy = this.canvas.height - sh; | |
} | |
// save to browser | |
context.drawImage(this.canvas, sx, sy, sw, sh, 0, 0, 230, 120); | |
} | |
else { | |
// now scaledown | |
var full_width = this.canvas.width; | |
var full_height = this.canvas.height; | |
context.drawImage(this.canvas, 0, 0, full_width, full_height, 0, 0, 230, 120); | |
} | |
imageData = offscreenCanvas.toDataURL('image/png'); | |
imageData = imageData.replace('image/png', downloadMime); | |
// call this function after 1 second | |
setTimeout(function(){ | |
p5.prototype.downloadFile(imageData, 'thumbnail.png', 'png'); | |
}, 1000); | |
} |