1 2 3 4///// CONSTANTS ///// 5const SIGNALS = {'0':'NEUTRAL','1':'A','2':'B','3':'C','4':'D','40':'E','48':'F','56':'G','10':'H','11':'I','52':'J','33':'K','41':'L','49':'M','57':'N','26':'O','34':'P','42':'Q','50':'R','58':'S','35':'T','43':'U','60':'V','53':'W','61':'X','51':'Y','55':'Z','15':'SPACE','44':'NUMBERS','59':'CANCEL'} 6const NUMBERS = {'1':'1','2':'2','3':'3','4':'4','40':'5','48':'6','56':'7','10':'8','11':'9','52':'LETTERS','33':'0','15':'SPACE','59':'CANCEL'} 7 8const SIGNALS_ORDERED = ['A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z','SPACE','NUMBERS','CANCEL'] 9 10const SIGNALS_ICONS = {'1':'A','2':'B','3':'C','4':'D','40':'E','48':'F','56':'G','10':'H','11':'I','52':'J','33':'K','41':'L','49':'M','57':'N','26':'O','34':'P','42':'Q','50':'R','58':'S','35':'T','43':'U','60':'V','53':'W','61':'X','51':'Y','55':'Z','15':'_','44':'#','59':'â« '} 11const NUMBERS_ICONS = {'1':'1','2':'2','3':'3','4':'4','40':'5','48':'6','56':'7','10':'8','11':'9','52':'ð¤','33':'0','15':'_','59':'â« '} 12 13const ALL_STATES = [DebugState, LoadingState, IntroMenuState, MainMenuState, GameAMenuState, GameState] 14 15Object.freeze(SIGNALS); 16Object.freeze(NUMBERS); 17Object.freeze(SIGNALS_ORDERED); 18Object.freeze(SIGNALS_ICONS); 19Object.freeze(NUMBERS_ICONS); 20Object.freeze(ALL_STATES); 21 22const TIME_THRESHOLD = 1200; // Milliseconds 23const DELTA_MAX = 160 24const LOCAL_DEBUG = false; 25const DEBUG_TEXT = "Q - Flip Camera & Guides\nW - Toggle Word Mode\nE - Toggle Flag Type\nR - Toggle Asyncronous Mode\nT - Return to Main Menu" 26 27var RED; 28var GREEN; 29var BLUE; 30var YELLOW; 31var MAGENTA; 32var CYAN; 33var BLACK; 34var WHITE; 35 36var LGRAY; 37var LRED; 38var LBLUE; 39 40var DGRAY; 41 42var Canvas; 43 44var streamRefreshMillis; 45 46var debugFrame = 0; 47 48var mainRegion= 49{ 50 size: undefined, 51 origin: undefined, 52 innerSize: undefined, 53 innerOrigin: undefined, 54 55 center: undefined, 56 57 idealSize: 720, 58 scale: undefined, 59} 60 61var margin; 62 63// TODO: MAKE GAME-DEPENDENT ONLY 64var lowerRegion= 65{ 66 size: undefined, 67 origin: undefined, 68} 69var overflowRegion= 70{ 71 size: undefined, 72 origin: undefined, 73} 74 75// var leftRegion= 76// { 77 // size: undefined, 78 // origin: undefined, 79// } 80// var rightRegion= 81// { 82 // size: undefined, 83 // origin: undefined, 84// } 85 86 87 88var cutoffAspect = 89{ 90 max: 2.3, 91 min: 0, 92} 93 94// var mainRegion.size; 95// var mainRegion.origin; 96 97// var mainRegion.innerSize; 98// var mainRegion.innerOrigin; 99 100// var mainRegion.center; 101 102var inModelPipeline = false; 103var flip = true; 104 105var drawStage = 'pre'; 106 107var state = LoadingState; 108 109var paused; 110var tabPaused; 111 112// p5.disableFriendlyErrors = !LOCAL_DEBUG 113p5.disableFriendlyErrors = true; 114 115window.onbeforeunload = function (e) 116{ 117 Model.disposeAll(); 118}; 119 120var introDone = false; 121var preloadDone = false; 122 123var ready = false; 124 125function animationEnd(event) 126{ 127 if(preloadDone) fadeLoader(); 128 introDone = true; 129} 130 131function fadeLoader() 132{ 133 // loadingDiv.onwebkitanimationend = endLoader; 134 // loadingDiv.onanimationend = endLoader; 135 // loadingDiv.onmozanimationend = endLoader; 136 // loadingDiv.onmsanimationend = endLoader; 137 138 loadingDiv.style.display = 'none'; 139 ready = true; 140 // loadingDiv.style.animation = "fade 1s ease-in-out reverse"; 141 // loadingDiv.style.webkitAnimation = "fade 1s ease-in-out reverse"; 142 // loadingDiv.style.mozAnimation = "fade 1s ease-in-out reverse"; 143 // loadingDiv.style.msAnimation = "fade 1s ease-in-out reverse"; 144 145 // Canvas.elt.style.animation = "fade 1s ease-in-out"; 146 // Canvas.elt.style.webkitAnimation = "fade 1s ease-in-out"; 147 // Canvas.elt.style.mozAnimation = "fade 1s ease-in-out"; 148 // Canvas.elt.style.msAnimation = "fade 1s ease-in-out"; 149 150 // Canvas.style("animation", "fade 1s ease-in-out"); 151 // Canvas.style("webkitAnimation", "fade 1s ease-in-out"); 152 // Canvas.style("mozAnimation", "fade 1s ease-in-out"); 153 // Canvas.style("msAnimation", "fade 1s ease-in-out"); 154 155 //ready = 0; 156 157 158} 159 160// function endLoader() 161// { 162 // loadingDiv.style.display = 'none'; 163 // ready = 1; 164// } 165 166var loadingDiv = document.getElementById('loading_circ'); 167loadingDiv.onwebkitanimationend = animationEnd; 168loadingDiv.onanimationend = animationEnd; 169loadingDiv.onmozanimationend = animationEnd; 170loadingDiv.onmsanimationend = animationEnd; 171 172///// P5 FUNCTIONS ///// 173function preload() 174{ 175 //introEnd = millis()+1000; 176 WebcamView.preload(); 177 Game.preload(); 178 GuideCards.preload(); 179 180 ALL_STATES.forEach((s)=> 181 { 182 if(s.preload) s.preload(); 183 }); 184} 185 186var linkSpan; 187var ppolSpan;// = document.getElementById('ppol'); 188var gitSpan 189 190function setup() 191{ 192 document.oncontextmenu = function() { return false; } 193 194 if(introDone) fadeLoader(); 195 preloadDone = true; 196 197 Canvas = createCanvas(windowWidth,windowHeight, P2D); 198 199 // let s = createSpan('<a href="https://www.iubenda.com/privacy-policy/91430819" class="iubend
199a-white iubenda-embed" title="Privacy Policy ">Privacy Policy</a><script type="text/javascript">(function (w,d) {var loader = function () {var s = d.createElement("script"), tag = d.getElementsByTagName("script")[0]; s.src="https://cdn.iubenda.com/iubenda.js"; tag.parentNode.insertBefore(s,tag);}; if(w.addEventListener){w.addEventListener("load", loader, false);}else if(w.attachEvent){w.attachEvent("onload", loader);}else{w.onload = loader;}})(window, document);</script>'); 200 // s.id("ppol"); 201 202 linkSpan = createSpan('Developed for <a href="https://www.signals.org.uk/">Signals</a> by Ben Tilbury'); 203 linkSpan.id("reflink") 204 linkSpan.hide(); 205 206 ppolSpan = createSpan('<a href="https://www.iubenda.com/privacy-policy/91430819">Privacy Policy</a>'); 207 ppolSpan.id("ppol") 208 ppolSpan.hide(); 209 210 gitSpan = createSpan('<a href="https://github.com/signalsmedia/signalsmedia.github.io">Source Code</a>'); 211 gitSpan.id("git") 212 gitSpan.hide(); 213 214 // if(!LOCAL_DEBUG) noCursor(); 215 216 textFont("Dosis", 64); 217 textStyle(BOLD) 218 strokeJoin(ROUND); 219 220 RED = color(255,0,0); 221 GREEN = color(0,255,0); 222 BLUE = color(0,0,255); 223 YELLOW = color(255,255,0); 224 MAGENTA = color(255,0,255); 225 CYAN = color(0,255,255); 226 BLACK = color(0,0,0); 227 WHITE = color(255,255,255); 228 LGRAY = color(160,160,160); 229 DGRAY = color(100,100,100); 230 231 LRED = color(255,60,60); 232 LBLUE = color(60,60,255); 233 234 windowResized(); 235 236 WebcamView.init(); 237 Model.init(); 238 Flag.init(); 239 UI.init(); 240 241 if(state.onEnter) state.onEnter(); 242} 243 244// var freq = 600; 245// var numPoints = 200; 246// var theta = 0.0; 247// var speed = 0.005; 248// var amp = 0.4; 249// var T = 0.004 250// var D = 0.01 251 252var mouseWait = 0; 253var mouseVisible = true; 254 255function draw() 256{ 257 let m = millis(); 258 259 if(!ready) return; 260 261 //// UPDATE //// 262 deltaTime = min(deltaTime,DELTA_MAX); 263 if(!state.ignoreModel) Model.update(); 264 if(state.update) state.update(); 265 266 //// DRAW //// 267 clear(); 268 // Background // 269 drawStage = 'pre'; 270 if(state.preDraw) state.preDraw(); 271 // Flippabled // 272 drawStage = 'flip'; 273 push(); 274 if(flip) 275 { 276 translate(width/2,0); 277 scale(-1,1); 278 translate(-width/2,0); 279 } 280 if(!state.ignoreWebcam) WebcamView.draw(); 281 if(state.flipDraw) state.flipDraw(); 282 if(!state.ignoreFlags && !paused) Flag.draw(); 283 pop(); 284 // Foreground // 285 drawStage = 'post'; 286 if(state.postDraw) state.postDraw(); 287 288 //drawStage = 'flag'; 289 //if(!state.ignoreFlags) Flag.draw(); 290 291 drawStage = 'overlay'; 292 if(paused) UI.showOptions(); 293 else if(UI.helpVisible()) UI.showHelp(); 294 295 //Model.debug(); 296 297 if ((mouseX != pmouseX) || (mouseY != pmouseY)) 298 { 299 if (!mouseVisible) 300 { 301 //cursor(); 302 document.body.style.cursor = 'auto'; 303 Canvas.style("cursor","auto") 304 mouseVisible = true; 305 } 306 307 if (mouseWait < m + 2000) mouseWait = m + 2000; 308 } 309 else 310 { 311 if (mouseVisible && m > mouseWait) 312 { 313 //noCursor(); 314 document.body.style.cursor = 'none'; 315 Canvas.style("cursor","none") 316 mouseVisible = false; 317 } 318 } 319 320 // if(ready>=0 && ready < 1) 321 // { 322 // ready += deltaTime*0.001 323 324 // Canvas.canvas.style.opacity = Math.min(1,ready); 325 // Canvas.canvas.style.webkitOpacity = Math.min(1,ready); 326 // } 327 // // // theta += speed; 328 // let step = windowWidth/numPoints 329 // let dx = (TWO_PI/freq) * step; 330 // let s = lowerRegion.size.y*amp; 331 // fill(BLUE); 332 // noStroke(); 333 // let x = theta; 334 // beginShape(); 335 // vertex(0,windowHeight) 336 // for(let i = 0; i<numPoints; i++) 337 // { 338 // curveVertex(i*step+mouseX,lowerRegion.origin.y+Math.sin(x)*s+mouseY); 339 // x+=dx; 340 // } 341 // // //to avoid Runge phenememon 342 // vertex(windowWidth,lowerRegion.origin.y+Math.sin(x)*s) 343 // vertex(windowWidth+20,lowerRegion.origin.y+Math.sin(x)*s) 344 // vertex(windowWidth,windowHeight) 345 // endShape(CLOSE) 346 347 348 // let step = windowWidth / Q; 349 // let s = lowerRegion.size.y; 350 // fill(BLUE); 351 // noStroke(); 352 // beginShape(); 353 // vertex(windowWidth,lowerRegion.origin.y+noise(millis()*T)*s) 354 // vertex(windowWidth,windowHeight) 355 // vertex(0,windowHeight) 356 // vertex(0,lowerRegion.origin.y+noise(Q*D+millis()*T)*s); 357 // for(let i = 0; i<Q-1; i++) 358 // { 359 // curveVertex(i*step,lowerRegion.origin.y+noise(i*D+millis()*T)*s); 360 // } 361 // // //+noise(i,millis()*0.0005) 362 // endShape(CLOSE) 363 364 // fill(CYAN);
365 // noStroke(); 366 // beginShape(); 367 // vertex(windowWidth,lowerRegion.origin.y+noise(millis()*T+0.5)*s+s/3); 368 // vertex(windowWidth,windowHeight) 369 // vertex(0,windowHeight) 370 // vertex(0,lowerRegion.origin.y+noise(Q*D+millis()*T+0.5)*s+s/3); 371 // for(let i = 0; i<Q-1; i++) 372 // { 373 // curveVertex(i*step,lowerRegion.origin.y+noise(i*D+millis()*T+0.5)*s+s/3); 374 // } 375 // endShape(CLOSE) 376 377 // strokeWeight(16); 378 // stroke(RED); 379 // line(lowerRegion.origin.x,lowerRegion.origin.y,windowWidth,lowerRegion.origin.y); 380 // stroke(BLUE) 381 // line(overflowRegion.origin.x,overflowRegion.origin.y,windowWidth,overflowRegion.origin.y) 382} 383// var T = 0.0004; 384// var D = 0.4 385// var Q = 100; 386 387var DEBUG_DRAW_REGIONS = false; 388 389function keyPressed() 390{ 391 /// DEBUG /// 392 if(key=='1' && state!=DebugState) 393 { 394 nextState(DebugState, state); 395 return; 396 } 397 else if(key=='2') DEBUG_DRAW_REGIONS = !DEBUG_DRAW_REGIONS; 398 ///////////// 399 if(state.onKeyPressed) state.onKeyPressed(); 400} 401 402function pause(yesText, yesAction, noText, noAction) 403{ 404 paused = true; 405 UI.setOptions({text:yesText, action:yesAction},{text:noText, action:noAction}, 'PAUSED'); 406} 407 408 409 410function nextState(newState, params) 411{ 412 if(state.onExit) state.onExit(); 413 state = newState; 414 415 // Model.resetTimes(); 416 417 // Initialize if first time entering. 418 if(!state.initialized && state.init) state.init(); 419 420 // Update dimensions if required, needs to be done after first time initialize but before onEnter 421 if(state.updateDimensionsPending && state.updateDimensions) state.updateDimensions(); 422 423 if(state.onEnter) state.onEnter(params); 424 425 state.updateDimensionsPending = false; 426 state.initialized = true; 427 428 Flag.rightFlag.confirmValue = 0; 429 Flag.leftFlag.confirmValue = 0; 430} 431 432function windowResized() 433{ 434 resizeCanvas(windowWidth,windowHeight) 435 436 if(state.overrideRegion) state.overrideMainRegion(); 437 else 438 { 439 mainRegion.size = createVector(min(windowWidth/2,(windowHeight/2.6)*cutoffAspect.max),min(windowWidth/2,(windowHeight/2.6)*cutoffAspect.max)); 440 //mainRegion.origin = createVector(windowWidth/2 - mainRegion.size.x/2, 0); 441 442 443 mainRegion.origin = createVector(windowWidth/2 - mainRegion.size.x/2, (windowHeight-mainRegion.size.y)/3); 444 445 mainRegion.innerSize = createVector(2*mainRegion.size.x/3,2*mainRegion.size.y/3); 446 mainRegion.innerOrigin = createVector(mainRegion.origin.x+mainRegion.innerSize.x/4,mainRegion.origin.y+mainRegion.innerSize.y/4); 447 mainRegion.center = createVector(mainRegion.origin.x+mainRegion.size.x/2,mainReg
447ion.origin.y+mainRegion.size.y/2); 448 mainRegion.scale = mainRegion.size.x / mainRegion.idealSize 449 450 lowerRegion.origin = createVector(0,windowHeight); 451 lowerRegion.size = createVector(windowWidth,0); 452 } 453 454 margin = 32*mainRegion.scale;//createVector(windowWidth/32,windowHeight/32); 455 456 // lowerRegion.origin = createVector(0,max(mainRegion.size.y,(windowHeight*2/3+mainRegion.size.y)/2)); 457 // lowerRegion.size = createVector(windowWidth,min(mainRegion.size.y/4,windowHeight-lowerRegion.origin.y)); 458 459 // overflowRegion.origin = createVector(0,lowerRegion.origin.y+lowerRegion.size.y); 460 // overflowRegion.size = createVector(windowWidth,windowHeight-overflowRegion.origin.y); 461 462 463 464 overflowRegion.origin = createVector(0,lowerRegion.origin.y+lowerRegion.size.y); 465 overflowRegion.size = createVector(windowWidth,windowHeight-overflowRegion.origin.y); 466 467 /// DEBUG /// 468 // leftRegion = { 469 // origin: createVector(margin,margin), 470 // size: createVector(mainRegion.origin.x-margin*2,lowerRegion.origin.y-margin*2) 471 // } 472 // rightRegion = { 473 // origin: createVector(mainRegion.origin.x+mainRegion.size.x+margin,margin), 474 // size: createVector(windowWidth-(mainRegion.origin.x+mainRegion.size.x+margin*2),lowerRegion.origin.y-margin*2) 475 // } 476 ///////////// 477 478 Flag.updateDimensions(); 479 UI.updateDimensions(); 480 481 ALL_STATES.forEach((s)=>s.updateDimensionsPending=true); 482 if(state.updateDimensions) state.updateDimensions(); 483 state.updateDimensionsPending = false; 484 485 textSize(windowWidth*0.01); 486 let h = textWidth("Developed for Signals by Ben Tilbury"); 487 linkSpan.position(windowWidth/2-h/2-windowWidth*0.005,windowHeight-windowWidth*0.02) 488 linkSpan.show() 489 490 textSize(windowWidth*0.01); 491 h = textWidth("Privacy Policy"); 492 ppolSpan.position(windowWidth-h-windowWidth*0.015,windowHeight-windowWidth*0.02); 493 ppolSpan.show(); 494 495 gitSpan.position(windowWidth*0.01,windowHeight-windowWidth*0.02); 496 gitSpan.show(); 497} 498 499function angleToIndex(angle) { return (round(angle*8/(PI*2))+6) % 8 } 500 501function anglesFromLetter(letter) 502{ 503 let num = Object.keys(SIGNALS).find(key => SIGNALS[key] === letter); 504 num = parseInt(num); 505 let l = floor(num/8) 506 let r = num - l*8 507 508 r = indexToAngle(r) 509 l = indexToAngle(l) 510 511 return [r, l]; 512} 513 514function indexToAngle(index, mode) 515{ 516 return ((index)/8)*PI*2 + PI/2; 517} 518 519function vectorsFromLetter(letter) 520{ 521 const [r,l] = anglesFromLetter(letter); 522 return [p5.Vector.fromAngle(r), p5.Vector.fromAngle(l)] 523} 524 525function randomTriangular(lower,upper,mode) 526{ 527 let U = Math.random()
528 if(U<(mode-lower)/(upper-lower)) return lower+Math.sqrt(U*(upper-lower)*(mode-lower)); 529 else return upper-Math.sqrt((1-U)*(upper-lower)*(upper-mode)); 530} 531 532function inputDebug() 533{ 534 // Flip 535 if(key.toUpperCase() === 'Q') 536 { 537 flip = !flip; 538 //document.getElementById("guideA").src = flip ? "assets/bacfaceA.png" : "assets/forfaceA.png" 539 //document.getElementById("guideB").src = flip ? "assets/bacfaceB.png" : "assets/forfaceB.png" 540 } 541 542 // Toggle Word Mode 543 if(key.toUpperCase() === 'W' && state!=GameState) 544 { 545 state.wordMode = !state.wordMode 546 state.sentence = ""; 547 } 548 549 // Toggle Two Tone Flags 550 if(key.toUpperCase() === 'E') 551 { 552 Flag.twoTone = !Flag.twoTone; 553 } 554 555 // Toggle Aync Mode 556 if(key.toUpperCase() === 'R') 557 { 558 Model.toggleAsync(); 559 Flag.resetAdapto(); 560 } 561 562 if(key.toUpperCase() === 'T') 563 { 564 nextState(MainMenuState) 565 } 566} 567 568// function shuffle(array) 569// { 570 // var m = array.length, t, i; 571 572 // while (m) { 573 574 // i = Math.floor(Math.random() * m--); 575 576 // t = array[m]; 577 // array[m] = array[i]; 578 // array[i] = t; 579 // } 580 581 // return array; 582// } 583 584///// DOCUMENT FUNCTIONS ///// 585document.addEventListener('visibilitychange', function() 586{ 587 if(document.hidden && !paused) 588 { 589 tabPaused = true; 590 } 591 else if(!document.hidden && !paused) 592 { 593 tabPaused = false; 594 } 595}); 596 597 598// window.onbeforeunload = function (e) 599// { 600 // Model.disposeAll(); 601// };
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.