|
|
@ -25,149 +25,186 @@ |
|
|
|
|
|
|
|
|
|
|
|
/* Takes root element to attach to, and an audio context element for |
|
|
|
/* Takes root element to attach to, and an audio context element for |
|
|
|
getting the current time with reasonable accuracy */ |
|
|
|
getting the current time with reasonable accuracy */ |
|
|
|
function HuesCanvas(root, audioContext, core) { |
|
|
|
class HuesCanvas { |
|
|
|
this.audio = audioContext; |
|
|
|
constructor(root, audioContext, core) { |
|
|
|
core.addEventListener("newimage", this.setImage.bind(this)); |
|
|
|
this.audio = audioContext; |
|
|
|
core.addEventListener("newcolour", this.setColour.bind(this)); |
|
|
|
core.addEventListener("newimage", this.setImage.bind(this)); |
|
|
|
core.addEventListener("beat", this.beat.bind(this)); |
|
|
|
core.addEventListener("newcolour", this.setColour.bind(this)); |
|
|
|
core.addEventListener("invert", this.setInvert.bind(this)); |
|
|
|
core.addEventListener("beat", this.beat.bind(this)); |
|
|
|
core.addEventListener("settingsupdated", this.settingsUpdated.bind(this)); |
|
|
|
core.addEventListener("invert", this.setInvert.bind(this)); |
|
|
|
core.addEventListener("frame", this.animationLoop.bind(this)); |
|
|
|
core.addEventListener("settingsupdated", this.settingsUpdated.bind(this)); |
|
|
|
this.core = core; |
|
|
|
core.addEventListener("frame", this.animationLoop.bind(this)); |
|
|
|
|
|
|
|
this.core = core; |
|
|
|
this.needsRedraw = false; |
|
|
|
|
|
|
|
this.colour = 0xFFFFFF; |
|
|
|
|
|
|
|
this.image = null; |
|
|
|
|
|
|
|
this.smartAlign = true; // avoid string comparisons every frame
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
this.animTimeout = null; |
|
|
|
|
|
|
|
this.animFrame = null; |
|
|
|
|
|
|
|
this.lastBeat = 0; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// set later
|
|
|
|
|
|
|
|
this.blurDecay = null; |
|
|
|
|
|
|
|
this.blurAmount = null; |
|
|
|
|
|
|
|
this.blurIterations = null; |
|
|
|
|
|
|
|
this.blurDelta = null; |
|
|
|
|
|
|
|
this.blurAlpha = null; |
|
|
|
|
|
|
|
// dynamic
|
|
|
|
|
|
|
|
this.blurStart = 0; |
|
|
|
|
|
|
|
this.blurDistance = 0; |
|
|
|
|
|
|
|
this.xBlur = false; |
|
|
|
|
|
|
|
this.yBlur = false; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// trippy mode
|
|
|
|
|
|
|
|
this.trippyStart = [0, 0]; // x, y
|
|
|
|
|
|
|
|
this.trippyRadii = [0, 0]; // x, y
|
|
|
|
|
|
|
|
// force trippy mode
|
|
|
|
|
|
|
|
this.trippyOn = false; |
|
|
|
|
|
|
|
this.trippyRadius = 0; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
this.blackout = false; |
|
|
|
|
|
|
|
this.blackoutColour = "#000"; // for the whiteout case we must store this
|
|
|
|
|
|
|
|
this.blackoutTimeout = null; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
this.invert = false; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
this.colourFade = false; |
|
|
|
|
|
|
|
this.colourFadeStart=0; |
|
|
|
|
|
|
|
this.colourFadeLength=0; |
|
|
|
|
|
|
|
this.oldColour=0xFFFFFF; |
|
|
|
|
|
|
|
this.newColour=0xFFFFFF; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
this.blendMode = "hard-light"; |
|
|
|
|
|
|
|
// Chosen because they look decent
|
|
|
|
|
|
|
|
this.setBlurAmount("medium"); |
|
|
|
|
|
|
|
this.setBlurQuality("high"); |
|
|
|
|
|
|
|
this.setBlurDecay("fast"); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
this.canvas = document.createElement('canvas'); |
|
|
|
|
|
|
|
this.context = this.canvas.getContext("2d"); |
|
|
|
|
|
|
|
this.canvas.width = 1280; |
|
|
|
|
|
|
|
this.canvas.height = 720; |
|
|
|
|
|
|
|
this.canvas.className = "hues-canvas"; |
|
|
|
|
|
|
|
root.appendChild(this.canvas); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
this.offCanvas = document.createElement('canvas'); |
|
|
|
|
|
|
|
this.offContext = this.offCanvas.getContext('2d'); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
window.addEventListener('resize', this.resize.bind(this)); |
|
|
|
|
|
|
|
this.resize(); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
HuesCanvas.prototype.setInvert = function(invert) { |
|
|
|
this.needsRedraw = false; |
|
|
|
this.invert = invert; |
|
|
|
this.colour = 0xFFFFFF; |
|
|
|
this.needsRedraw = true; |
|
|
|
this.image = null; |
|
|
|
}; |
|
|
|
this.smartAlign = true; // avoid string comparisons every frame
|
|
|
|
|
|
|
|
|
|
|
|
HuesCanvas.prototype.settingsUpdated = function() { |
|
|
|
this.animTimeout = null; |
|
|
|
this.setSmartAlign(localStorage["smartAlign"]); |
|
|
|
this.animFrame = null; |
|
|
|
this.setBlurAmount(localStorage["blurAmount"]); |
|
|
|
this.lastBeat = 0; |
|
|
|
this.setBlurDecay(localStorage["blurDecay"]); |
|
|
|
|
|
|
|
this.setBlurQuality(localStorage["blurQuality"]); |
|
|
|
// set later
|
|
|
|
this.trippyOn = localStorage["trippyMode"] == "on"; |
|
|
|
this.blurDecay = null; |
|
|
|
}; |
|
|
|
this.blurAmount = null; |
|
|
|
|
|
|
|
this.blurIterations = null; |
|
|
|
HuesCanvas.prototype.resize = function() { |
|
|
|
this.blurDelta = null; |
|
|
|
// height is max 720px, we expand width to suit
|
|
|
|
this.blurAlpha = null; |
|
|
|
let height = this.core.root.clientHeight; |
|
|
|
// dynamic
|
|
|
|
let ratio = this.core.root.clientWidth / height; |
|
|
|
this.blurStart = 0; |
|
|
|
this.canvas.height = Math.min(height, 720); |
|
|
|
this.blurDistance = 0; |
|
|
|
this.canvas.width = Math.ceil(this.canvas.height * ratio); |
|
|
|
this.xBlur = false; |
|
|
|
this.offCanvas.height = this.canvas.height; |
|
|
|
this.yBlur = false; |
|
|
|
this.offCanvas.width = this.canvas.width; |
|
|
|
|
|
|
|
this.trippyRadius = Math.max(this.canvas.width, this.canvas.height) / 2; |
|
|
|
// trippy mode
|
|
|
|
this.needsRedraw = true; |
|
|
|
this.trippyStart = [0, 0]; // x, y
|
|
|
|
}; |
|
|
|
this.trippyRadii = [0, 0]; // x, y
|
|
|
|
|
|
|
|
// force trippy mode
|
|
|
|
HuesCanvas.prototype.redraw = function() { |
|
|
|
this.trippyOn = false; |
|
|
|
let offset; // for centering/right/left align
|
|
|
|
this.trippyRadius = 0; |
|
|
|
let bOpacity; |
|
|
|
|
|
|
|
let width = this.canvas.width; |
|
|
|
this.blackout = false; |
|
|
|
let height = this.canvas.height; |
|
|
|
this.blackoutColour = "#000"; // for the whiteout case we must store this
|
|
|
|
|
|
|
|
this.blackoutTimeout = null; |
|
|
|
let cTime = this.audio.currentTime; |
|
|
|
|
|
|
|
// white BG for the hard light filter
|
|
|
|
this.invert = false; |
|
|
|
this.context.globalAlpha = 1; |
|
|
|
|
|
|
|
this.context.globalCompositeOperation = "source-over"; |
|
|
|
this.colourFade = false; |
|
|
|
if(this.blackout) { |
|
|
|
this.colourFadeStart=0; |
|
|
|
// original is 3 frames at 30fps, this is close
|
|
|
|
this.colourFadeLength=0; |
|
|
|
bOpacity = (cTime - this.blackoutStart)*10; |
|
|
|
this.oldColour=0xFFFFFF; |
|
|
|
if(bOpacity > 1) { // optimise the draw
|
|
|
|
this.newColour=0xFFFFFF; |
|
|
|
this.context.fillStyle = this.blackoutColour; |
|
|
|
|
|
|
|
|
|
|
|
this.blendMode = "hard-light"; |
|
|
|
|
|
|
|
// Chosen because they look decent
|
|
|
|
|
|
|
|
this.setBlurAmount("medium"); |
|
|
|
|
|
|
|
this.setBlurQuality("high"); |
|
|
|
|
|
|
|
this.setBlurDecay("fast"); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
this.canvas = document.createElement('canvas'); |
|
|
|
|
|
|
|
this.context = this.canvas.getContext("2d"); |
|
|
|
|
|
|
|
this.canvas.width = 1280; |
|
|
|
|
|
|
|
this.canvas.height = 720; |
|
|
|
|
|
|
|
this.canvas.className = "hues-canvas"; |
|
|
|
|
|
|
|
root.appendChild(this.canvas); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
this.offCanvas = document.createElement('canvas'); |
|
|
|
|
|
|
|
this.offContext = this.offCanvas.getContext('2d'); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
window.addEventListener('resize', this.resize.bind(this)); |
|
|
|
|
|
|
|
this.resize(); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
setInvert(invert) { |
|
|
|
|
|
|
|
this.invert = invert; |
|
|
|
|
|
|
|
this.needsRedraw = true; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
settingsUpdated() { |
|
|
|
|
|
|
|
this.setSmartAlign(localStorage["smartAlign"]); |
|
|
|
|
|
|
|
this.setBlurAmount(localStorage["blurAmount"]); |
|
|
|
|
|
|
|
this.setBlurDecay(localStorage["blurDecay"]); |
|
|
|
|
|
|
|
this.setBlurQuality(localStorage["blurQuality"]); |
|
|
|
|
|
|
|
this.trippyOn = localStorage["trippyMode"] == "on"; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
resize() { |
|
|
|
|
|
|
|
// height is max 720px, we expand width to suit
|
|
|
|
|
|
|
|
let height = this.core.root.clientHeight; |
|
|
|
|
|
|
|
let ratio = this.core.root.clientWidth / height; |
|
|
|
|
|
|
|
this.canvas.height = Math.min(height, 720); |
|
|
|
|
|
|
|
this.canvas.width = Math.ceil(this.canvas.height * ratio); |
|
|
|
|
|
|
|
this.offCanvas.height = this.canvas.height; |
|
|
|
|
|
|
|
this.offCanvas.width = this.canvas.width; |
|
|
|
|
|
|
|
this.trippyRadius = Math.max(this.canvas.width, this.canvas.height) / 2; |
|
|
|
|
|
|
|
this.needsRedraw = true; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
redraw() { |
|
|
|
|
|
|
|
let offset; // for centering/right/left align
|
|
|
|
|
|
|
|
let bOpacity; |
|
|
|
|
|
|
|
let width = this.canvas.width; |
|
|
|
|
|
|
|
let height = this.canvas.height; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
let cTime = this.audio.currentTime; |
|
|
|
|
|
|
|
// white BG for the hard light filter
|
|
|
|
|
|
|
|
this.context.globalAlpha = 1; |
|
|
|
|
|
|
|
this.context.globalCompositeOperation = "source-over"; |
|
|
|
|
|
|
|
if(this.blackout) { |
|
|
|
|
|
|
|
// original is 3 frames at 30fps, this is close
|
|
|
|
|
|
|
|
bOpacity = (cTime - this.blackoutStart)*10; |
|
|
|
|
|
|
|
if(bOpacity > 1) { // optimise the draw
|
|
|
|
|
|
|
|
this.context.fillStyle = this.blackoutColour; |
|
|
|
|
|
|
|
this.context.fillRect(0,0,width,height); |
|
|
|
|
|
|
|
this.needsRedraw = false; |
|
|
|
|
|
|
|
this.drawInvert(); |
|
|
|
|
|
|
|
return; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} else { |
|
|
|
|
|
|
|
this.context.fillStyle = "#FFF"; |
|
|
|
this.context.fillRect(0,0,width,height); |
|
|
|
this.context.fillRect(0,0,width,height); |
|
|
|
this.needsRedraw = false; |
|
|
|
|
|
|
|
this.drawInvert(); |
|
|
|
|
|
|
|
return; |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
} else { |
|
|
|
|
|
|
|
this.context.fillStyle = "#FFF"; |
|
|
|
|
|
|
|
this.context.fillRect(0,0,width,height); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if(this.image && (this.image.bitmap || this.image.bitmaps)) { |
|
|
|
if(this.image && (this.image.bitmap || this.image.bitmaps)) { |
|
|
|
let bitmap = this.image.animated ? |
|
|
|
let bitmap = this.image.animated ? |
|
|
|
this.image.bitmaps[this.animFrame] : this.image.bitmap; |
|
|
|
this.image.bitmaps[this.animFrame] : this.image.bitmap; |
|
|
|
let drawHeight = bitmap.height * (height / bitmap.height); |
|
|
|
let drawHeight = bitmap.height * (height / bitmap.height); |
|
|
|
let drawWidth = (bitmap.width / bitmap.height) * drawHeight; |
|
|
|
let drawWidth = (bitmap.width / bitmap.height) * drawHeight; |
|
|
|
if(this.smartAlign) { |
|
|
|
if(this.smartAlign) { |
|
|
|
switch(this.image.align) { |
|
|
|
switch(this.image.align) { |
|
|
|
case "left": |
|
|
|
case "left": |
|
|
|
offset = 0; |
|
|
|
offset = 0; |
|
|
|
break; |
|
|
|
break; |
|
|
|
case "right": |
|
|
|
case "right": |
|
|
|
offset = width - drawWidth; |
|
|
|
offset = width - drawWidth; |
|
|
|
break; |
|
|
|
break; |
|
|
|
default: |
|
|
|
default: |
|
|
|
offset = width/2 - drawWidth/2; |
|
|
|
offset = width/2 - drawWidth/2; |
|
|
|
break; |
|
|
|
break; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} else { |
|
|
|
|
|
|
|
offset = width/2 - drawWidth/2; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
if(this.xBlur || this.yBlur) { |
|
|
|
|
|
|
|
this.drawBlur(bitmap, offset, drawWidth, drawHeight); |
|
|
|
|
|
|
|
}else { |
|
|
|
|
|
|
|
this.context.globalAlpha = 1; |
|
|
|
|
|
|
|
this.context.drawImage(bitmap, offset, 0, drawWidth, drawHeight); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if(this.trippyStart[0] || this.trippyStart[1]) { |
|
|
|
|
|
|
|
this.drawTrippy(width, height); |
|
|
|
} else { |
|
|
|
} else { |
|
|
|
offset = width/2 - drawWidth/2; |
|
|
|
this.offContext.fillStyle = this.intToHex(this.colour); |
|
|
|
|
|
|
|
this.offContext.fillRect(0,0,width,height); |
|
|
|
} |
|
|
|
} |
|
|
|
if(this.xBlur || this.yBlur) { |
|
|
|
this.context.globalAlpha = 0.7; |
|
|
|
this.context.globalAlpha = this.blurAlpha; |
|
|
|
this.context.globalCompositeOperation = this.blendMode; |
|
|
|
|
|
|
|
this.context.drawImage(this.offCanvas, 0, 0); |
|
|
|
|
|
|
|
if(this.blackout) { |
|
|
|
|
|
|
|
this.context.globalAlpha = bOpacity; |
|
|
|
|
|
|
|
this.context.fillStyle = this.blackoutColour; |
|
|
|
|
|
|
|
this.context.fillRect(0,0,width,height); |
|
|
|
|
|
|
|
this.needsRedraw = true; |
|
|
|
|
|
|
|
} else { |
|
|
|
|
|
|
|
this.needsRedraw = false; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
this.drawInvert(); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
drawInvert() { |
|
|
|
|
|
|
|
if(this.invert) { |
|
|
|
|
|
|
|
this.context.globalAlpha = 1; |
|
|
|
|
|
|
|
this.context.globalCompositeOperation = "difference"; |
|
|
|
|
|
|
|
this.context.fillStyle = "#FFF"; |
|
|
|
|
|
|
|
this.context.fillRect(0,0,this.canvas.width,this.canvas.height); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
drawBlur(bitmap, offset, drawWidth, drawHeight) { |
|
|
|
|
|
|
|
this.context.globalAlpha = this.blurAlpha; |
|
|
|
if(this.xBlur) { |
|
|
|
if(this.xBlur) { |
|
|
|
if(this.blurIterations < 0) { |
|
|
|
if(this.blurIterations < 0) { |
|
|
|
this.context.globalAlpha = 1; |
|
|
|
this.context.globalAlpha = 1; |
|
|
@ -188,13 +225,11 @@ HuesCanvas.prototype.redraw = function() { |
|
|
|
this.context.drawImage(bitmap, offset, Math.floor(this.blurDistance * i), drawWidth, drawHeight); |
|
|
|
this.context.drawImage(bitmap, offset, Math.floor(this.blurDistance * i), drawWidth, drawHeight); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} else { |
|
|
|
|
|
|
|
this.context.globalAlpha = 1; |
|
|
|
|
|
|
|
this.context.drawImage(bitmap, offset, 0, drawWidth, drawHeight); |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
if(this.trippyStart[0] || this.trippyStart[1]) { |
|
|
|
// draws the correct trippy colour circles onto the offscreen canvas
|
|
|
|
|
|
|
|
drawTrippy(width, height) { |
|
|
|
// x blur moves inwards from the corners, y comes out
|
|
|
|
// x blur moves inwards from the corners, y comes out
|
|
|
|
// So the base colour is inverted for y, normal for x
|
|
|
|
// So the base colour is inverted for y, normal for x
|
|
|
|
// Thus if the y start is more recent, we invert
|
|
|
|
// Thus if the y start is more recent, we invert
|
|
|
@ -222,289 +257,265 @@ HuesCanvas.prototype.redraw = function() { |
|
|
|
this.offContext.closePath(); |
|
|
|
this.offContext.closePath(); |
|
|
|
invert = !invert; |
|
|
|
invert = !invert; |
|
|
|
} |
|
|
|
} |
|
|
|
} else { |
|
|
|
|
|
|
|
this.offContext.fillStyle = this.intToHex(this.colour); |
|
|
|
|
|
|
|
this.offContext.fillRect(0,0,width,height); |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
this.context.globalAlpha = 0.7; |
|
|
|
|
|
|
|
this.context.globalCompositeOperation = this.blendMode; |
|
|
|
|
|
|
|
this.context.drawImage(this.offCanvas, 0, 0); |
|
|
|
|
|
|
|
if(this.blackout) { |
|
|
|
|
|
|
|
this.context.globalAlpha = bOpacity; |
|
|
|
|
|
|
|
this.context.fillStyle = this.blackoutColour; |
|
|
|
|
|
|
|
this.context.fillRect(0,0,width,height); |
|
|
|
|
|
|
|
this.needsRedraw = true; |
|
|
|
|
|
|
|
} else { |
|
|
|
|
|
|
|
this.needsRedraw = false; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
this.drawInvert(); |
|
|
|
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
HuesCanvas.prototype.drawInvert = function() { |
|
|
|
/* Second fastest method from |
|
|
|
if(this.invert) { |
|
|
|
http://stackoverflow.com/questions/10073699/pad-a-number-with-leading-zeros-in-javascript
|
|
|
|
this.context.globalAlpha = 1; |
|
|
|
It stil does millions of ops per second, and isn't ugly like the integer if/else */ |
|
|
|
this.context.globalCompositeOperation = "difference"; |
|
|
|
intToHex(num) { |
|
|
|
this.context.fillStyle = "#FFF"; |
|
|
|
return '#' + ("00000"+num.toString(16)).slice(-6); |
|
|
|
this.context.fillRect(0,0,this.canvas.width,this.canvas.height); |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
animationLoop() { |
|
|
|
/* Second fastest method from |
|
|
|
if (this.colourFade) { |
|
|
|
http://stackoverflow.com/questions/10073699/pad-a-number-with-leading-zeros-in-javascript
|
|
|
|
let delta = this.audio.currentTime - this.colourFadeStart; |
|
|
|
It stil does millions of ops per second, and isn't ugly like the integer if/else */ |
|
|
|
let fadeVal = delta / this.colourFadeLength; |
|
|
|
HuesCanvas.prototype.intToHex = function(num) { |
|
|
|
if (fadeVal >= 1) { |
|
|
|
return '#' + ("00000"+num.toString(16)).slice(-6); |
|
|
|
this.stopFade(); |
|
|
|
}; |
|
|
|
this.colour = this.newColour; |
|
|
|
|
|
|
|
} else { |
|
|
|
HuesCanvas.prototype.animationLoop = function() { |
|
|
|
this.mixColours(fadeVal); |
|
|
|
if (this.colourFade) { |
|
|
|
} |
|
|
|
let delta = this.audio.currentTime - this.colourFadeStart; |
|
|
|
this.needsRedraw = true; |
|
|
|
let fadeVal = delta / this.colourFadeLength; |
|
|
|
|
|
|
|
if (fadeVal >= 1) { |
|
|
|
|
|
|
|
this.stopFade(); |
|
|
|
|
|
|
|
this.colour = this.newColour; |
|
|
|
|
|
|
|
} else { |
|
|
|
|
|
|
|
this.mixColours(fadeVal); |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
this.needsRedraw = true; |
|
|
|
if(this.blackoutTimeout && this.audio.currentTime > this.blackoutTimeout) { |
|
|
|
} |
|
|
|
this.clearBlackout(); |
|
|
|
if(this.blackoutTimeout && this.audio.currentTime > this.blackoutTimeout) { |
|
|
|
} |
|
|
|
this.clearBlackout(); |
|
|
|
if(this.image && this.image.animated){ |
|
|
|
} |
|
|
|
if(this.image.beatsPerAnim && this.core.currentSong && this.core.currentSong.charsPerBeat) { |
|
|
|
if(this.image && this.image.animated){ |
|
|
|
let a = this.animFrame; |
|
|
|
if(this.image.beatsPerAnim && this.core.currentSong && this.core.currentSong.charsPerBeat) { |
|
|
|
this.syncAnim(); |
|
|
|
let a = this.animFrame; |
|
|
|
if(this.animFrame != a) { |
|
|
|
this.syncAnim(); |
|
|
|
this.needsRedraw = true; |
|
|
|
if(this.animFrame != a) { |
|
|
|
// If you change to a non-synced song, this needs to be reset
|
|
|
|
|
|
|
|
this.animTimeout = this.audio.currentTime; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} else if(this.animTimeout < this.audio.currentTime) { |
|
|
|
|
|
|
|
this.animFrame++; |
|
|
|
|
|
|
|
this.animFrame %= this.image.frameDurations.length; |
|
|
|
|
|
|
|
// Don't rebase to current time otherwise we may lag
|
|
|
|
|
|
|
|
this.animTimeout += this.image.frameDurations[this.animFrame]/1000; |
|
|
|
this.needsRedraw = true; |
|
|
|
this.needsRedraw = true; |
|
|
|
// If you change to a non-synced song, this needs to be reset
|
|
|
|
|
|
|
|
this.animTimeout = this.audio.currentTime; |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
} else if(this.animTimeout < this.audio.currentTime) { |
|
|
|
} |
|
|
|
this.animFrame++; |
|
|
|
if(this.blurStart) { |
|
|
|
this.animFrame %= this.image.frameDurations.length; |
|
|
|
// flash offsets blur gen by a frame
|
|
|
|
// Don't rebase to current time otherwise we may lag
|
|
|
|
let delta = this.audio.currentTime - this.blurStart + (1/30); |
|
|
|
this.animTimeout += this.image.frameDurations[this.animFrame]/1000; |
|
|
|
this.blurDistance = this.blurAmount * Math.exp(-this.blurDecay * delta); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Update UI
|
|
|
|
|
|
|
|
let dist = this.blurDistance / this.blurAmount; |
|
|
|
|
|
|
|
if(this.xBlur) |
|
|
|
|
|
|
|
this.core.blurUpdated(dist, 0); |
|
|
|
|
|
|
|
else |
|
|
|
|
|
|
|
this.core.blurUpdated(0, dist); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
if(this.trippyStart[0] || this.trippyStart[1]) { |
|
|
|
|
|
|
|
for(let i = 0; i < 2; i++) { |
|
|
|
|
|
|
|
this.trippyRadii[i] = Math.floor((this.audio.currentTime - this.trippyStart[i]) * this.trippyRadius) * 2; |
|
|
|
|
|
|
|
if(this.trippyRadii[i] > this.trippyRadius) { |
|
|
|
|
|
|
|
this.trippyStart[i] = 0; |
|
|
|
|
|
|
|
this.trippyRadii[i] = 0; |
|
|
|
|
|
|
|
continue; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
// x comes from outside the window
|
|
|
|
|
|
|
|
if(i % 2 === 0) { |
|
|
|
|
|
|
|
this.trippyRadii[i] = this.trippyRadius - this.trippyRadii[i]; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
this.needsRedraw = true; |
|
|
|
this.needsRedraw = true; |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
if(this.blurStart) { |
|
|
|
|
|
|
|
// flash offsets blur gen by a frame
|
|
|
|
|
|
|
|
let delta = this.audio.currentTime - this.blurStart + (1/30); |
|
|
|
|
|
|
|
this.blurDistance = this.blurAmount * Math.exp(-this.blurDecay * delta); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Update UI
|
|
|
|
if(this.blurStart && this.blurDistance < 1) { |
|
|
|
let dist = this.blurDistance / this.blurAmount; |
|
|
|
this.core.blurUpdated(0, 0); |
|
|
|
if(this.xBlur) |
|
|
|
this.blurDistance = 0; |
|
|
|
this.core.blurUpdated(dist, 0); |
|
|
|
this.blurStart = 0; |
|
|
|
else |
|
|
|
this.xBlur = this.yBlur = false; |
|
|
|
this.core.blurUpdated(0, dist); |
|
|
|
this.redraw(); |
|
|
|
|
|
|
|
} else if(this.blurStart) { |
|
|
|
|
|
|
|
this.redraw(); |
|
|
|
|
|
|
|
} else if(this.needsRedraw){ |
|
|
|
|
|
|
|
this.redraw(); |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
if(this.trippyStart[0] || this.trippyStart[1]) { |
|
|
|
|
|
|
|
for(let i = 0; i < 2; i++) { |
|
|
|
setImage(image) { |
|
|
|
this.trippyRadii[i] = Math.floor((this.audio.currentTime - this.trippyStart[i]) * this.trippyRadius) * 2; |
|
|
|
if(this.image == image) { |
|
|
|
if(this.trippyRadii[i] > this.trippyRadius) { |
|
|
|
return; |
|
|
|
this.trippyStart[i] = 0; |
|
|
|
|
|
|
|
this.trippyRadii[i] = 0; |
|
|
|
|
|
|
|
continue; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
// x comes from outside the window
|
|
|
|
|
|
|
|
if(i % 2 === 0) { |
|
|
|
|
|
|
|
this.trippyRadii[i] = this.trippyRadius - this.trippyRadii[i]; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
this.needsRedraw = true; |
|
|
|
this.needsRedraw = true; |
|
|
|
|
|
|
|
this.image = image; |
|
|
|
|
|
|
|
// Null images don't need anything interesting done to them
|
|
|
|
|
|
|
|
if(!image || (!image.bitmap && !image.bitmaps)) { |
|
|
|
|
|
|
|
return; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
if(image.animated) { |
|
|
|
|
|
|
|
this.animBeat = null; |
|
|
|
|
|
|
|
this.animFrame = 0; |
|
|
|
|
|
|
|
this.animTimeout = this.audio.currentTime + image.frameDurations[0]/1000; |
|
|
|
|
|
|
|
if(image.beatsPerAnim && this.core.currentSong && this.core.currentSong.charsPerBeat) { |
|
|
|
|
|
|
|
this.syncAnim(); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
if(this.blurStart && this.blurDistance < 1) { |
|
|
|
beat() { |
|
|
|
this.core.blurUpdated(0, 0); |
|
|
|
this.lastBeat = this.audio.currentTime; |
|
|
|
this.blurDistance = 0; |
|
|
|
} |
|
|
|
this.blurStart = 0; |
|
|
|
|
|
|
|
this.xBlur = this.yBlur = false; |
|
|
|
syncAnim() { |
|
|
|
this.redraw(); |
|
|
|
let song = this.core.currentSong; |
|
|
|
} else if(this.blurStart) { |
|
|
|
if(!song) { // fallback to default
|
|
|
|
this.redraw(); |
|
|
|
return; |
|
|
|
} else if(this.needsRedraw){ |
|
|
|
} |
|
|
|
this.redraw(); |
|
|
|
let index = this.core.beatIndex; |
|
|
|
|
|
|
|
// When animation has more frames than song has beats, or part thereof
|
|
|
|
|
|
|
|
if(this.lastBeat && this.core.getBeatLength()) { |
|
|
|
|
|
|
|
let interp = (this.audio.currentTime - this.lastBeat) / this.core.getBeatLength(); |
|
|
|
|
|
|
|
index += Math.min(interp, 1); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
// This loops A-OK because the core's beatIndex never rolls over for a new loop
|
|
|
|
|
|
|
|
let beatLoc = (index / song.charsPerBeat) % this.image.beatsPerAnim; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
let aLen = this.image.bitmaps.length; |
|
|
|
|
|
|
|
this.animFrame = Math.floor(aLen * (beatLoc / this.image.beatsPerAnim)); |
|
|
|
|
|
|
|
if(this.image.syncOffset) { |
|
|
|
|
|
|
|
this.animFrame += this.image.syncOffset; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
// Because negative mods are different in JS
|
|
|
|
|
|
|
|
this.animFrame = ((this.animFrame % aLen) + aLen) % aLen; |
|
|
|
} |
|
|
|
} |
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
HuesCanvas.prototype.setImage = function(image) { |
|
|
|
setColour(colour, isFade) { |
|
|
|
if(this.image == image) { |
|
|
|
if(colour.c == this.colour) { |
|
|
|
return; |
|
|
|
return; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
if(isFade) { |
|
|
|
|
|
|
|
this.newColour = colour.c; |
|
|
|
|
|
|
|
} else { |
|
|
|
|
|
|
|
this.stopFade(); |
|
|
|
|
|
|
|
this.colour = colour.c; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
this.needsRedraw = true; |
|
|
|
} |
|
|
|
} |
|
|
|
this.needsRedraw = true; |
|
|
|
|
|
|
|
this.image = image; |
|
|
|
doBlackout(whiteout) { |
|
|
|
// Null images don't need anything interesting done to them
|
|
|
|
if (typeof(whiteout)==='undefined') whiteout = false; |
|
|
|
if(!image || (!image.bitmap && !image.bitmaps)) { |
|
|
|
if(whiteout) { |
|
|
|
return; |
|
|
|
this.blackoutColour = "#FFF"; |
|
|
|
|
|
|
|
} else { |
|
|
|
|
|
|
|
this.blackoutColour = "#000"; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
this.blackoutTimeout = 0; // indefinite
|
|
|
|
|
|
|
|
// Don't restart the blackout animation if we're already blacked out
|
|
|
|
|
|
|
|
if(!this.blackout) { |
|
|
|
|
|
|
|
this.blackoutStart = this.audio.currentTime; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
this.blackout = true; |
|
|
|
|
|
|
|
this.needsRedraw = true; |
|
|
|
|
|
|
|
if(localStorage["blackoutUI"] == "on") { |
|
|
|
|
|
|
|
this.core.userInterface.hide(); |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
if(image.animated) { |
|
|
|
|
|
|
|
this.animBeat = null; |
|
|
|
// for song changes
|
|
|
|
this.animFrame = 0; |
|
|
|
clearBlackout() { |
|
|
|
this.animTimeout = this.audio.currentTime + image.frameDurations[0]/1000; |
|
|
|
this.blackout = false; |
|
|
|
if(image.beatsPerAnim && this.core.currentSong && this.core.currentSong.charsPerBeat) { |
|
|
|
this.blackoutTimeout = 0; |
|
|
|
this.syncAnim(); |
|
|
|
this.needsRedraw = true; |
|
|
|
|
|
|
|
if(localStorage["blackoutUI"] == "on") { |
|
|
|
|
|
|
|
this.core.userInterface.show(); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
HuesCanvas.prototype.beat = function() { |
|
|
|
doShortBlackout(beatTime) { |
|
|
|
this.lastBeat = this.audio.currentTime; |
|
|
|
this.doBlackout(); |
|
|
|
}; |
|
|
|
this.blackoutTimeout = this.audio.currentTime + beatTime / 1.7; |
|
|
|
|
|
|
|
// looks better if we go right to black
|
|
|
|
|
|
|
|
this.blackoutStart = 0; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
doColourFade(length) { |
|
|
|
|
|
|
|
this.colourFade = true; |
|
|
|
|
|
|
|
this.colourFadeLength = length; |
|
|
|
|
|
|
|
this.colourFadeStart = this.audio.currentTime; |
|
|
|
|
|
|
|
this.oldColour = this.colour; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
HuesCanvas.prototype.syncAnim = function() { |
|
|
|
stopFade() { |
|
|
|
let song = this.core.currentSong; |
|
|
|
this.colourFade = false; |
|
|
|
if(!song) { // fallback to default
|
|
|
|
this.colourFadeStart = 0; |
|
|
|
return; |
|
|
|
this.colourFadeLength = 0; |
|
|
|
} |
|
|
|
} |
|
|
|
let index = this.core.beatIndex; |
|
|
|
|
|
|
|
// When animation has more frames than song has beats, or part thereof
|
|
|
|
mixColours(percent) { |
|
|
|
if(this.lastBeat && this.core.getBeatLength()) { |
|
|
|
percent = Math.min(1, percent); |
|
|
|
let interp = (this.audio.currentTime - this.lastBeat) / this.core.getBeatLength(); |
|
|
|
let oldR = this.oldColour >> 16 & 0xFF; |
|
|
|
index += Math.min(interp, 1); |
|
|
|
let oldG = this.oldColour >> 8 & 0xFF; |
|
|
|
|
|
|
|
let oldB = this.oldColour & 0xFF; |
|
|
|
|
|
|
|
let newR = this.newColour >> 16 & 0xFF; |
|
|
|
|
|
|
|
let newG = this.newColour >> 8 & 0xFF; |
|
|
|
|
|
|
|
let newB = this.newColour & 0xFF; |
|
|
|
|
|
|
|
let mixR = oldR * (1 - percent) + newR * percent; |
|
|
|
|
|
|
|
let mixG = oldG * (1 - percent) + newG * percent; |
|
|
|
|
|
|
|
let mixB = oldB * (1 - percent) + newB * percent; |
|
|
|
|
|
|
|
this.colour = mixR << 16 | mixG << 8 | mixB; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
doXBlur() { |
|
|
|
|
|
|
|
this.blurStart = this.audio.currentTime; |
|
|
|
|
|
|
|
if(this.trippyOn) |
|
|
|
|
|
|
|
this.trippyStart[0] = this.blurStart; |
|
|
|
|
|
|
|
this.blurDistance = this.blurAmount; |
|
|
|
|
|
|
|
this.xBlur = true; |
|
|
|
|
|
|
|
this.yBlur = false; |
|
|
|
|
|
|
|
this.needsRedraw = true; |
|
|
|
} |
|
|
|
} |
|
|
|
// This loops A-OK because the core's beatIndex never rolls over for a new loop
|
|
|
|
|
|
|
|
let beatLoc = (index / song.charsPerBeat) % this.image.beatsPerAnim; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
let aLen = this.image.bitmaps.length; |
|
|
|
doYBlur() { |
|
|
|
this.animFrame = Math.floor(aLen * (beatLoc / this.image.beatsPerAnim)); |
|
|
|
this.blurStart = this.audio.currentTime; |
|
|
|
if(this.image.syncOffset) { |
|
|
|
if(this.trippyOn) |
|
|
|
this.animFrame += this.image.syncOffset; |
|
|
|
this.trippyStart[1] = this.blurStart; |
|
|
|
|
|
|
|
this.blurDistance = this.blurAmount; |
|
|
|
|
|
|
|
this.xBlur = false; |
|
|
|
|
|
|
|
this.yBlur = true; |
|
|
|
|
|
|
|
this.needsRedraw = true; |
|
|
|
} |
|
|
|
} |
|
|
|
// Because negative mods are different in JS
|
|
|
|
|
|
|
|
this.animFrame = ((this.animFrame % aLen) + aLen) % aLen; |
|
|
|
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
HuesCanvas.prototype.setColour = function(colour, isFade) { |
|
|
|
doTrippyX() { |
|
|
|
if(colour.c == this.colour) { |
|
|
|
let saveTrippy = this.trippyOn; |
|
|
|
return; |
|
|
|
// force trippy
|
|
|
|
|
|
|
|
this.trippyOn = true; |
|
|
|
|
|
|
|
this.doXBlur(); |
|
|
|
|
|
|
|
this.trippyOn = saveTrippy; |
|
|
|
} |
|
|
|
} |
|
|
|
if(isFade) { |
|
|
|
|
|
|
|
this.newColour = colour.c; |
|
|
|
doTrippyY() { |
|
|
|
} else { |
|
|
|
let saveTrippy = this.trippyOn; |
|
|
|
this.stopFade(); |
|
|
|
// force trippy
|
|
|
|
this.colour = colour.c; |
|
|
|
this.trippyOn = true; |
|
|
|
|
|
|
|
this.doYBlur(); |
|
|
|
|
|
|
|
this.trippyOn = saveTrippy; |
|
|
|
} |
|
|
|
} |
|
|
|
this.needsRedraw = true; |
|
|
|
|
|
|
|
}; |
|
|
|
setBlurDecay(decay) { |
|
|
|
|
|
|
|
this.blurDecay = {"slow" : 7.8, "medium" : 14.1, "fast" : 20.8, "faster!" : 28.7}[decay]; |
|
|
|
HuesCanvas.prototype.doBlackout = function(whiteout) { |
|
|
|
|
|
|
|
if (typeof(whiteout)==='undefined') whiteout = false; |
|
|
|
|
|
|
|
if(whiteout) { |
|
|
|
|
|
|
|
this.blackoutColour = "#FFF"; |
|
|
|
|
|
|
|
} else { |
|
|
|
|
|
|
|
this.blackoutColour = "#000"; |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
this.blackoutTimeout = 0; // indefinite
|
|
|
|
|
|
|
|
// Don't restart the blackout animation if we're already blacked out
|
|
|
|
setBlurQuality(quality) { |
|
|
|
if(!this.blackout) { |
|
|
|
this.blurIterations = {"low" : -1, "medium" : 11, "high" : 19, "extreme" : 35}[quality]; |
|
|
|
this.blackoutStart = this.audio.currentTime; |
|
|
|
this.blurDelta = 1 / (this.blurIterations/2); |
|
|
|
|
|
|
|
this.blurAlpha = 1 / (this.blurIterations/2); |
|
|
|
} |
|
|
|
} |
|
|
|
this.blackout = true; |
|
|
|
|
|
|
|
this.needsRedraw = true; |
|
|
|
setBlurAmount(amount) { |
|
|
|
if(localStorage["blackoutUI"] == "on") { |
|
|
|
this.blurAmount = {"low" : 48, "medium" : 96, "high" : 384}[amount]; |
|
|
|
this.core.userInterface.hide(); |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
setSmartAlign(align) { |
|
|
|
// for song changes
|
|
|
|
this.smartAlign = align == "on"; |
|
|
|
HuesCanvas.prototype.clearBlackout = function() { |
|
|
|
|
|
|
|
this.blackout = false; |
|
|
|
|
|
|
|
this.blackoutTimeout = 0; |
|
|
|
|
|
|
|
this.needsRedraw = true; |
|
|
|
|
|
|
|
if(localStorage["blackoutUI"] == "on") { |
|
|
|
|
|
|
|
this.core.userInterface.show(); |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
}; |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
HuesCanvas.prototype.doShortBlackout = function(beatTime) { |
|
|
|
|
|
|
|
this.doBlackout(); |
|
|
|
|
|
|
|
this.blackoutTimeout = this.audio.currentTime + beatTime / 1.7; |
|
|
|
|
|
|
|
// looks better if we go right to black
|
|
|
|
|
|
|
|
this.blackoutStart = 0; |
|
|
|
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
HuesCanvas.prototype.doColourFade = function(length) { |
|
|
|
|
|
|
|
this.colourFade = true; |
|
|
|
|
|
|
|
this.colourFadeLength = length; |
|
|
|
|
|
|
|
this.colourFadeStart = this.audio.currentTime; |
|
|
|
|
|
|
|
this.oldColour = this.colour; |
|
|
|
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
HuesCanvas.prototype.stopFade = function() { |
|
|
|
|
|
|
|
this.colourFade = false; |
|
|
|
|
|
|
|
this.colourFadeStart = 0; |
|
|
|
|
|
|
|
this.colourFadeLength = 0; |
|
|
|
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
HuesCanvas.prototype.mixColours = function(percent) { |
|
|
|
|
|
|
|
percent = Math.min(1, percent); |
|
|
|
|
|
|
|
let oldR = this.oldColour >> 16 & 0xFF; |
|
|
|
|
|
|
|
let oldG = this.oldColour >> 8 & 0xFF; |
|
|
|
|
|
|
|
let oldB = this.oldColour & 0xFF; |
|
|
|
|
|
|
|
let newR = this.newColour >> 16 & 0xFF; |
|
|
|
|
|
|
|
let newG = this.newColour >> 8 & 0xFF; |
|
|
|
|
|
|
|
let newB = this.newColour & 0xFF; |
|
|
|
|
|
|
|
let mixR = oldR * (1 - percent) + newR * percent; |
|
|
|
|
|
|
|
let mixG = oldG * (1 - percent) + newG * percent; |
|
|
|
|
|
|
|
let mixB = oldB * (1 - percent) + newB * percent; |
|
|
|
|
|
|
|
this.colour = mixR << 16 | mixG << 8 | mixB; |
|
|
|
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
HuesCanvas.prototype.doXBlur = function() { |
|
|
|
|
|
|
|
this.blurStart = this.audio.currentTime; |
|
|
|
|
|
|
|
if(this.trippyOn) |
|
|
|
|
|
|
|
this.trippyStart[0] = this.blurStart; |
|
|
|
|
|
|
|
this.blurDistance = this.blurAmount; |
|
|
|
|
|
|
|
this.xBlur = true; |
|
|
|
|
|
|
|
this.yBlur = false; |
|
|
|
|
|
|
|
this.needsRedraw = true; |
|
|
|
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
HuesCanvas.prototype.doYBlur = function() { |
|
|
|
|
|
|
|
this.blurStart = this.audio.currentTime; |
|
|
|
|
|
|
|
if(this.trippyOn) |
|
|
|
|
|
|
|
this.trippyStart[1] = this.blurStart; |
|
|
|
|
|
|
|
this.blurDistance = this.blurAmount; |
|
|
|
|
|
|
|
this.xBlur = false; |
|
|
|
|
|
|
|
this.yBlur = true; |
|
|
|
|
|
|
|
this.needsRedraw = true; |
|
|
|
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
HuesCanvas.prototype.doTrippyX = function() { |
|
|
|
|
|
|
|
let saveTrippy = this.trippyOn; |
|
|
|
|
|
|
|
// force trippy
|
|
|
|
|
|
|
|
this.trippyOn = true; |
|
|
|
|
|
|
|
this.doXBlur(); |
|
|
|
|
|
|
|
this.trippyOn = saveTrippy; |
|
|
|
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
HuesCanvas.prototype.doTrippyY = function() { |
|
|
|
|
|
|
|
let saveTrippy = this.trippyOn; |
|
|
|
|
|
|
|
// force trippy
|
|
|
|
|
|
|
|
this.trippyOn = true; |
|
|
|
|
|
|
|
this.doYBlur(); |
|
|
|
|
|
|
|
this.trippyOn = saveTrippy; |
|
|
|
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
HuesCanvas.prototype.setBlurDecay = function(decay) { |
|
|
|
|
|
|
|
this.blurDecay = {"slow" : 7.8, "medium" : 14.1, "fast" : 20.8, "faster!" : 28.7}[decay]; |
|
|
|
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
HuesCanvas.prototype.setBlurQuality = function(quality) { |
|
|
|
|
|
|
|
this.blurIterations = {"low" : -1, "medium" : 11, "high" : 19, "extreme" : 35}[quality]; |
|
|
|
|
|
|
|
this.blurDelta = 1 / (this.blurIterations/2); |
|
|
|
|
|
|
|
this.blurAlpha = 1 / (this.blurIterations/2); |
|
|
|
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
HuesCanvas.prototype.setBlurAmount = function(amount) { |
|
|
|
|
|
|
|
this.blurAmount = {"low" : 48, "medium" : 96, "high" : 384}[amount]; |
|
|
|
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
HuesCanvas.prototype.setSmartAlign = function(align) { |
|
|
|
|
|
|
|
this.smartAlign = align == "on"; |
|
|
|
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
window.HuesCanvas = HuesCanvas; |
|
|
|
window.HuesCanvas = HuesCanvas; |
|
|
|
|
|
|
|
|
|
|
|