Move to ES2015 classes. Makes HuesUI especially nice

master
William Toohey 9 years ago
parent f4f62d167b
commit 4145470d6a
  1. 4
      package.json
  2. 167
      src/js/HuesCanvas.js
  3. 230
      src/js/HuesCore.js
  4. 212
      src/js/HuesEditor.js
  5. 4
      src/js/HuesInfo.js
  6. 66
      src/js/HuesSettings.js
  7. 361
      src/js/HuesUI.js
  8. 36
      src/js/HuesWindow.js
  9. 146
      src/js/ResourceManager.js
  10. 117
      src/js/ResourcePack.js
  11. 92
      src/js/SoundManager.js

@ -20,7 +20,7 @@
}, },
"homepage": "https://github.com/mon/0x40-web#readme", "homepage": "https://github.com/mon/0x40-web#readme",
"devDependencies": { "devDependencies": {
"babel-preset-es2015": "^6.6.0", "babel-preset-es2015": "^6.9.0",
"del": "^2.2.0", "del": "^2.2.0",
"gulp": "^3.9.1", "gulp": "^3.9.1",
"gulp-autoprefixer": "^3.1.0", "gulp-autoprefixer": "^3.1.0",
@ -33,6 +33,6 @@
"gulp-plumber": "^1.1.0", "gulp-plumber": "^1.1.0",
"gulp-sourcemaps": "^1.6.0", "gulp-sourcemaps": "^1.6.0",
"gulp-uglify": "^1.5.3", "gulp-uglify": "^1.5.3",
"jshint": "^2.9.1" "jshint": "^2.9.2"
} }
} }

@ -25,7 +25,8 @@
/* 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 {
constructor(root, audioContext, core) {
this.audio = audioContext; this.audio = audioContext;
core.addEventListener("newimage", this.setImage.bind(this)); core.addEventListener("newimage", this.setImage.bind(this));
core.addEventListener("newcolour", this.setColour.bind(this)); core.addEventListener("newcolour", this.setColour.bind(this));
@ -95,20 +96,20 @@ function HuesCanvas(root, audioContext, core) {
this.resize(); this.resize();
} }
HuesCanvas.prototype.setInvert = function(invert) { setInvert(invert) {
this.invert = invert; this.invert = invert;
this.needsRedraw = true; this.needsRedraw = true;
}; }
HuesCanvas.prototype.settingsUpdated = function() { settingsUpdated() {
this.setSmartAlign(localStorage["smartAlign"]); this.setSmartAlign(localStorage["smartAlign"]);
this.setBlurAmount(localStorage["blurAmount"]); this.setBlurAmount(localStorage["blurAmount"]);
this.setBlurDecay(localStorage["blurDecay"]); this.setBlurDecay(localStorage["blurDecay"]);
this.setBlurQuality(localStorage["blurQuality"]); this.setBlurQuality(localStorage["blurQuality"]);
this.trippyOn = localStorage["trippyMode"] == "on"; this.trippyOn = localStorage["trippyMode"] == "on";
}; }
HuesCanvas.prototype.resize = function() { resize() {
// height is max 720px, we expand width to suit // height is max 720px, we expand width to suit
let height = this.core.root.clientHeight; let height = this.core.root.clientHeight;
let ratio = this.core.root.clientWidth / height; let ratio = this.core.root.clientWidth / height;
@ -118,9 +119,9 @@ HuesCanvas.prototype.resize = function() {
this.offCanvas.width = this.canvas.width; this.offCanvas.width = this.canvas.width;
this.trippyRadius = Math.max(this.canvas.width, this.canvas.height) / 2; this.trippyRadius = Math.max(this.canvas.width, this.canvas.height) / 2;
this.needsRedraw = true; this.needsRedraw = true;
}; }
HuesCanvas.prototype.redraw = function() { redraw() {
let offset; // for centering/right/left align let offset; // for centering/right/left align
let bOpacity; let bOpacity;
let width = this.canvas.width; let width = this.canvas.width;
@ -166,8 +167,44 @@ HuesCanvas.prototype.redraw = function() {
offset = width/2 - drawWidth/2; offset = width/2 - drawWidth/2;
} }
if(this.xBlur || this.yBlur) { if(this.xBlur || this.yBlur) {
this.context.globalAlpha = this.blurAlpha; 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 {
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();
} }
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,41 +257,16 @@ 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() {
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);
} }
};
/* Second fastest method from /* Second fastest method from
http://stackoverflow.com/questions/10073699/pad-a-number-with-leading-zeros-in-javascript http://stackoverflow.com/questions/10073699/pad-a-number-with-leading-zeros-in-javascript
It stil does millions of ops per second, and isn't ugly like the integer if/else */ It stil does millions of ops per second, and isn't ugly like the integer if/else */
HuesCanvas.prototype.intToHex = function(num) { intToHex(num) {
return '#' + ("00000"+num.toString(16)).slice(-6); return '#' + ("00000"+num.toString(16)).slice(-6);
}; }
HuesCanvas.prototype.animationLoop = function() { animationLoop() {
if (this.colourFade) { if (this.colourFade) {
let delta = this.audio.currentTime - this.colourFadeStart; let delta = this.audio.currentTime - this.colourFadeStart;
let fadeVal = delta / this.colourFadeLength; let fadeVal = delta / this.colourFadeLength;
@ -327,9 +337,9 @@ HuesCanvas.prototype.animationLoop = function() {
} else if(this.needsRedraw){ } else if(this.needsRedraw){
this.redraw(); this.redraw();
} }
}; }
HuesCanvas.prototype.setImage = function(image) { setImage(image) {
if(this.image == image) { if(this.image == image) {
return; return;
} }
@ -347,13 +357,13 @@ HuesCanvas.prototype.setImage = function(image) {
this.syncAnim(); this.syncAnim();
} }
} }
}; }
HuesCanvas.prototype.beat = function() { beat() {
this.lastBeat = this.audio.currentTime; this.lastBeat = this.audio.currentTime;
}; }
HuesCanvas.prototype.syncAnim = function() { syncAnim() {
let song = this.core.currentSong; let song = this.core.currentSong;
if(!song) { // fallback to default if(!song) { // fallback to default
return; return;
@ -374,9 +384,9 @@ HuesCanvas.prototype.syncAnim = function() {
} }
// Because negative mods are different in JS // Because negative mods are different in JS
this.animFrame = ((this.animFrame % aLen) + aLen) % aLen; this.animFrame = ((this.animFrame % aLen) + aLen) % aLen;
}; }
HuesCanvas.prototype.setColour = function(colour, isFade) { setColour(colour, isFade) {
if(colour.c == this.colour) { if(colour.c == this.colour) {
return; return;
} }
@ -387,9 +397,9 @@ HuesCanvas.prototype.setColour = function(colour, isFade) {
this.colour = colour.c; this.colour = colour.c;
} }
this.needsRedraw = true; this.needsRedraw = true;
}; }
HuesCanvas.prototype.doBlackout = function(whiteout) { doBlackout(whiteout) {
if (typeof(whiteout)==='undefined') whiteout = false; if (typeof(whiteout)==='undefined') whiteout = false;
if(whiteout) { if(whiteout) {
this.blackoutColour = "#FFF"; this.blackoutColour = "#FFF";
@ -406,39 +416,39 @@ HuesCanvas.prototype.doBlackout = function(whiteout) {
if(localStorage["blackoutUI"] == "on") { if(localStorage["blackoutUI"] == "on") {
this.core.userInterface.hide(); this.core.userInterface.hide();
} }
}; }
// for song changes // for song changes
HuesCanvas.prototype.clearBlackout = function() { clearBlackout() {
this.blackout = false; this.blackout = false;
this.blackoutTimeout = 0; this.blackoutTimeout = 0;
this.needsRedraw = true; this.needsRedraw = true;
if(localStorage["blackoutUI"] == "on") { if(localStorage["blackoutUI"] == "on") {
this.core.userInterface.show(); this.core.userInterface.show();
} }
}; }
HuesCanvas.prototype.doShortBlackout = function(beatTime) { doShortBlackout(beatTime) {
this.doBlackout(); this.doBlackout();
this.blackoutTimeout = this.audio.currentTime + beatTime / 1.7; this.blackoutTimeout = this.audio.currentTime + beatTime / 1.7;
// looks better if we go right to black // looks better if we go right to black
this.blackoutStart = 0; this.blackoutStart = 0;
}; }
HuesCanvas.prototype.doColourFade = function(length) { doColourFade(length) {
this.colourFade = true; this.colourFade = true;
this.colourFadeLength = length; this.colourFadeLength = length;
this.colourFadeStart = this.audio.currentTime; this.colourFadeStart = this.audio.currentTime;
this.oldColour = this.colour; this.oldColour = this.colour;
}; }
HuesCanvas.prototype.stopFade = function() { stopFade() {
this.colourFade = false; this.colourFade = false;
this.colourFadeStart = 0; this.colourFadeStart = 0;
this.colourFadeLength = 0; this.colourFadeLength = 0;
}; }
HuesCanvas.prototype.mixColours = function(percent) { mixColours(percent) {
percent = Math.min(1, percent); percent = Math.min(1, percent);
let oldR = this.oldColour >> 16 & 0xFF; let oldR = this.oldColour >> 16 & 0xFF;
let oldG = this.oldColour >> 8 & 0xFF; let oldG = this.oldColour >> 8 & 0xFF;
@ -450,9 +460,9 @@ HuesCanvas.prototype.mixColours = function(percent) {
let mixG = oldG * (1 - percent) + newG * percent; let mixG = oldG * (1 - percent) + newG * percent;
let mixB = oldB * (1 - percent) + newB * percent; let mixB = oldB * (1 - percent) + newB * percent;
this.colour = mixR << 16 | mixG << 8 | mixB; this.colour = mixR << 16 | mixG << 8 | mixB;
}; }
HuesCanvas.prototype.doXBlur = function() { doXBlur() {
this.blurStart = this.audio.currentTime; this.blurStart = this.audio.currentTime;
if(this.trippyOn) if(this.trippyOn)
this.trippyStart[0] = this.blurStart; this.trippyStart[0] = this.blurStart;
@ -460,9 +470,9 @@ HuesCanvas.prototype.doXBlur = function() {
this.xBlur = true; this.xBlur = true;
this.yBlur = false; this.yBlur = false;
this.needsRedraw = true; this.needsRedraw = true;
}; }
HuesCanvas.prototype.doYBlur = function() { doYBlur() {
this.blurStart = this.audio.currentTime; this.blurStart = this.audio.currentTime;
if(this.trippyOn) if(this.trippyOn)
this.trippyStart[1] = this.blurStart; this.trippyStart[1] = this.blurStart;
@ -470,41 +480,42 @@ HuesCanvas.prototype.doYBlur = function() {
this.xBlur = false; this.xBlur = false;
this.yBlur = true; this.yBlur = true;
this.needsRedraw = true; this.needsRedraw = true;
}; }
HuesCanvas.prototype.doTrippyX = function() { doTrippyX() {
let saveTrippy = this.trippyOn; let saveTrippy = this.trippyOn;
// force trippy // force trippy
this.trippyOn = true; this.trippyOn = true;
this.doXBlur(); this.doXBlur();
this.trippyOn = saveTrippy; this.trippyOn = saveTrippy;
}; }
HuesCanvas.prototype.doTrippyY = function() { doTrippyY() {
let saveTrippy = this.trippyOn; let saveTrippy = this.trippyOn;
// force trippy // force trippy
this.trippyOn = true; this.trippyOn = true;
this.doYBlur(); this.doYBlur();
this.trippyOn = saveTrippy; this.trippyOn = saveTrippy;
}; }
HuesCanvas.prototype.setBlurDecay = function(decay) { setBlurDecay(decay) {
this.blurDecay = {"slow" : 7.8, "medium" : 14.1, "fast" : 20.8, "faster!" : 28.7}[decay]; this.blurDecay = {"slow" : 7.8, "medium" : 14.1, "fast" : 20.8, "faster!" : 28.7}[decay];
}; }
HuesCanvas.prototype.setBlurQuality = function(quality) { setBlurQuality(quality) {
this.blurIterations = {"low" : -1, "medium" : 11, "high" : 19, "extreme" : 35}[quality]; this.blurIterations = {"low" : -1, "medium" : 11, "high" : 19, "extreme" : 35}[quality];
this.blurDelta = 1 / (this.blurIterations/2); this.blurDelta = 1 / (this.blurIterations/2);
this.blurAlpha = 1 / (this.blurIterations/2); this.blurAlpha = 1 / (this.blurIterations/2);
}; }
HuesCanvas.prototype.setBlurAmount = function(amount) { setBlurAmount(amount) {
this.blurAmount = {"low" : 48, "medium" : 96, "high" : 384}[amount]; this.blurAmount = {"low" : 48, "medium" : 96, "high" : 384}[amount];
}; }
HuesCanvas.prototype.setSmartAlign = function(align) { setSmartAlign(align) {
this.smartAlign = align == "on"; this.smartAlign = align == "on";
}; }
}
window.HuesCanvas = HuesCanvas; window.HuesCanvas = HuesCanvas;

@ -25,7 +25,8 @@
(function(window, document) { (function(window, document) {
"use strict"; "use strict";
function HuesCore(defaults) { class HuesCore {
constructor(defaults) {
this.eventListeners = { this.eventListeners = {
/* callback time(hundredths) /* callback time(hundredths)
* *
@ -113,7 +114,7 @@ function HuesCore(defaults) {
this.lastImageArray = []; this.lastImageArray = [];
this.colourIndex = 0x3f; this.colourIndex = 0x3f;
this.colours = this.oldColours; this.colours = HuesCore.oldColours;
this.isFullAuto = true; this.isFullAuto = true;
this.invert = false; this.invert = false;
@ -272,23 +273,23 @@ function HuesCore(defaults) {
} }
} }
HuesCore.prototype.callEventListeners = function(ev) { callEventListeners(ev) {
let args = Array.prototype.slice.call(arguments, 1); let args = Array.prototype.slice.call(arguments, 1);
this.eventListeners[ev].forEach(function(callback) { this.eventListeners[ev].forEach(function(callback) {
callback.apply(null, args); callback.apply(null, args);
}); });
}; }
HuesCore.prototype.addEventListener = function(ev, callback) { addEventListener(ev, callback) {
ev = ev.toLowerCase(); ev = ev.toLowerCase();
if (typeof(this.eventListeners[ev]) !== "undefined") { if (typeof(this.eventListeners[ev]) !== "undefined") {
this.eventListeners[ev].push(callback); this.eventListeners[ev].push(callback);
} else { } else {
throw Error("Unknown event: " + ev); throw Error("Unknown event: " + ev);
} }
}; }
HuesCore.prototype.removeEventListener = function(ev, callback) { removeEventListener(ev, callback) {
ev = ev.toLowerCase(); ev = ev.toLowerCase();
if (typeof(this.eventListeners[ev]) !== "undefined") { if (typeof(this.eventListeners[ev]) !== "undefined") {
this.eventListeners[ev] = this.eventListeners[ev].filter(function(a) { this.eventListeners[ev] = this.eventListeners[ev].filter(function(a) {
@ -297,9 +298,9 @@ HuesCore.prototype.removeEventListener = function(ev, callback) {
} else { } else {
throw Error("Unknown event: " + ev); throw Error("Unknown event: " + ev);
} }
}; }
HuesCore.prototype.makePreloader = function(root) { makePreloader(root) {
this.preloader = document.createElement("div"); this.preloader = document.createElement("div");
this.preloader.className = "hues-preloader"; this.preloader.className = "hues-preloader";
root.appendChild(this.preloader); root.appendChild(this.preloader);
@ -312,13 +313,13 @@ HuesCore.prototype.makePreloader = function(root) {
this.preloadSubMsg = document.createElement("div"); this.preloadSubMsg = document.createElement("div");
this.preloadSubMsg.className = "hues-preloader__subtext"; this.preloadSubMsg.className = "hues-preloader__subtext";
this.preloader.appendChild(this.preloadSubMsg); this.preloader.appendChild(this.preloadSubMsg);
}; }
HuesCore.prototype.resizeVisualiser = function() { resizeVisualiser() {
this.soundManager.initVisualiser(this.visualiser.width/2); this.soundManager.initVisualiser(this.visualiser.width/2);
}; }
HuesCore.prototype.updateVisualiser = function() { updateVisualiser() {
if(localStorage["visualiser"] != "on") { if(localStorage["visualiser"] != "on") {
return; return;
} }
@ -359,9 +360,9 @@ HuesCore.prototype.updateVisualiser = function() {
x += barWidth; x += barWidth;
} }
} }
}; }
HuesCore.prototype.animationLoop = function() { animationLoop() {
requestAnimationFrame(this.animationLoop.bind(this)); requestAnimationFrame(this.animationLoop.bind(this));
if(!this.soundManager.playing) { if(!this.soundManager.playing) {
this.callEventListeners("frame"); this.callEventListeners("frame");
@ -379,9 +380,9 @@ HuesCore.prototype.animationLoop = function() {
this.beater(beat); this.beater(beat);
} }
this.callEventListeners("frame"); this.callEventListeners("frame");
}; }
HuesCore.prototype.recalcBeatIndex = function(forcedNow) { recalcBeatIndex(forcedNow) {
let now = typeof forcedNow === "number" ? forcedNow : this.soundManager.currentTime(); let now = typeof forcedNow === "number" ? forcedNow : this.soundManager.currentTime();
// getBeatLength isn't updated with the right beatIndex yet // getBeatLength isn't updated with the right beatIndex yet
this.beatIndex = Math.floor(now / (now < 0 ? this.buildLength : this.loopLength)); this.beatIndex = Math.floor(now / (now < 0 ? this.buildLength : this.loopLength));
@ -409,9 +410,9 @@ HuesCore.prototype.recalcBeatIndex = function(forcedNow) {
// If there's an odd amount of inverts thus far, invert our display // If there's an odd amount of inverts thus far, invert our display
let invertCount = (mapSoFar.match(/i|I/g)||[]).length; let invertCount = (mapSoFar.match(/i|I/g)||[]).length;
this.setInvert(invertCount % 2); this.setInvert(invertCount % 2);
}; }
HuesCore.prototype.getBeatIndex = function() { getBeatIndex() {
if(!this.soundManager.playing) { if(!this.soundManager.playing) {
return 0; return 0;
} else if(this.beatIndex < 0) { } else if(this.beatIndex < 0) {
@ -419,32 +420,32 @@ HuesCore.prototype.getBeatIndex = function() {
} else { } else {
return this.beatIndex % this.currentSong.rhythm.length; return this.beatIndex % this.currentSong.rhythm.length;
} }
}; }
HuesCore.prototype.getSafeBeatIndex = function() { getSafeBeatIndex() {
let index = this.getBeatIndex(); let index = this.getBeatIndex();
if(index < 0) { if(index < 0) {
return 0; return 0;
} else { } else {
return index; return index;
} }
}; }
HuesCore.prototype.blurUpdated = function(x, y) { blurUpdated(x, y) {
this.callEventListeners("blurupdate", x, y); this.callEventListeners("blurupdate", x, y);
}; }
HuesCore.prototype.nextSong = function() { nextSong() {
let index = (this.songIndex + 1) % this.resourceManager.enabledSongs.length; let index = (this.songIndex + 1) % this.resourceManager.enabledSongs.length;
this.setSong(index); this.setSong(index);
}; }
HuesCore.prototype.previousSong = function() { previousSong() {
let index = ((this.songIndex - 1) + this.resourceManager.enabledSongs.length) % this.resourceManager.enabledSongs.length; let index = ((this.songIndex - 1) + this.resourceManager.enabledSongs.length) % this.resourceManager.enabledSongs.length;
this.setSong(index); this.setSong(index);
}; }
HuesCore.prototype.setSongByName = function(name) { setSongByName(name) {
let songs = this.resourceManager.enabledSongs; let songs = this.resourceManager.enabledSongs;
for(let i = 0; i < songs.length; i++) { for(let i = 0; i < songs.length; i++) {
if(songs[i].title == name) { if(songs[i].title == name) {
@ -452,18 +453,18 @@ HuesCore.prototype.setSongByName = function(name) {
} }
} }
return this.setSong(0); // fallback return this.setSong(0); // fallback
}; }
/* To set songs via reference instead of index - used in HuesEditor */ /* To set songs via reference instead of index - used in HuesEditor */
HuesCore.prototype.setSongOject = function(song) { setSongOject(song) {
for(let i = 0; i < this.resourceManager.enabledSongs.length; i++) { for(let i = 0; i < this.resourceManager.enabledSongs.length; i++) {
if(this.resourceManager.enabledSongs[i] === song) { if(this.resourceManager.enabledSongs[i] === song) {
return this.setSong(i); return this.setSong(i);
} }
} }
}; }
HuesCore.prototype.setSong = function(index, leaveArray) { setSong(index, leaveArray) {
if(this.currentSong == this.resourceManager.enabledSongs[index]) { if(this.currentSong == this.resourceManager.enabledSongs[index]) {
return; return;
} }
@ -503,9 +504,9 @@ HuesCore.prototype.setSong = function(index, leaveArray) {
this.fillBuildup(); this.fillBuildup();
this.callEventListeners("songstarted"); this.callEventListeners("songstarted");
}); });
}; }
HuesCore.prototype.updateBeatLength = function() { updateBeatLength() {
this.loopLength = this.soundManager.loopLength / this.currentSong.rhythm.length; this.loopLength = this.soundManager.loopLength / this.currentSong.rhythm.length;
if(this.currentSong.buildup) { if(this.currentSong.buildup) {
if (!this.currentSong.buildupRhythm) { if (!this.currentSong.buildupRhythm) {
@ -515,17 +516,17 @@ HuesCore.prototype.updateBeatLength = function() {
} else { } else {
this.buildLength = -1; this.buildLength = -1;
} }
}; }
HuesCore.prototype.getBeatLength = function() { getBeatLength() {
if(this.beatIndex < 0) { if(this.beatIndex < 0) {
return this.buildLength; return this.buildLength;
} else { } else {
return this.loopLength; return this.loopLength;
} }
}; }
HuesCore.prototype.fillBuildup = function() { fillBuildup() {
// update loop length for flash style filling // update loop length for flash style filling
this.updateBeatLength(); this.updateBeatLength();
if(this.currentSong.buildup) { if(this.currentSong.buildup) {
@ -549,9 +550,9 @@ HuesCore.prototype.fillBuildup = function() {
// If we're in the build or loop this will adjust // If we're in the build or loop this will adjust
// If we've lagged a bit, we'll miss the first beat. Rewind! // If we've lagged a bit, we'll miss the first beat. Rewind!
this.recalcBeatIndex(this.doBuildup ? -this.soundManager.buildLength : 0); this.recalcBeatIndex(this.doBuildup ? -this.soundManager.buildLength : 0);
}; }
HuesCore.prototype.randomSong = function() { randomSong() {
let songCount = this.resourceManager.enabledSongs.length; let songCount = this.resourceManager.enabledSongs.length;
let index=Math.floor((Math.random() * songCount)); let index=Math.floor((Math.random() * songCount));
if (songCount > 1 && (index == this.songIndex || this.lastSongArray.indexOf(index) != -1)) { if (songCount > 1 && (index == this.songIndex || this.lastSongArray.indexOf(index) != -1)) {
@ -564,19 +565,19 @@ HuesCore.prototype.randomSong = function() {
this.lastSongArray.shift(); this.lastSongArray.shift();
} }
} }
}; }
/* This is its own function because requestAnimationFrame is called very very /* This is its own function because requestAnimationFrame is called very very
rarely when the tab is backgrounded. As autoSong is often used to chill with rarely when the tab is backgrounded. As autoSong is often used to chill with
music, it's important to keep checking the loop so songs don't go for too music, it's important to keep checking the loop so songs don't go for too
long. */ long. */
HuesCore.prototype.loopCheck = function() { loopCheck() {
if(Math.floor(this.soundManager.currentTime() / this.soundManager.loopLength) > this.loopCount) { if(Math.floor(this.soundManager.currentTime() / this.soundManager.loopLength) > this.loopCount) {
this.onLoop(); this.onLoop();
} }
}; }
HuesCore.prototype.onLoop = function() { onLoop() {
this.loopCount++; this.loopCount++;
switch (localStorage["autoSong"]) { switch (localStorage["autoSong"]) {
case "loop": case "loop":
@ -592,9 +593,9 @@ HuesCore.prototype.onLoop = function() {
} }
break; break;
} }
}; }
HuesCore.prototype.doAutoSong = function() { doAutoSong() {
let func = null; let func = null;
if(localStorage["autoSongShuffle"] == "on") { if(localStorage["autoSongShuffle"] == "on") {
func = this.randomSong; func = this.randomSong;
@ -608,24 +609,24 @@ HuesCore.prototype.doAutoSong = function() {
} else { } else {
func.call(this); func.call(this);
} }
}; }
HuesCore.prototype.songDataUpdated = function() { songDataUpdated() {
if (this.currentSong) { if (this.currentSong) {
this.callEventListeners("newsong", this.currentSong); this.callEventListeners("newsong", this.currentSong);
this.callEventListeners("newimage", this.currentImage); this.callEventListeners("newimage", this.currentImage);
} }
}; }
HuesCore.prototype.resetAudio = function() { resetAudio() {
this.beatIndex = 0; this.beatIndex = 0;
this.songDataUpdated(); this.songDataUpdated();
if(localStorage["visualiser"] == "on") { if(localStorage["visualiser"] == "on") {
this.soundManager.initVisualiser(this.visualiser.width/2); this.soundManager.initVisualiser(this.visualiser.width/2);
} }
}; }
HuesCore.prototype.randomImage = function() { randomImage() {
if(localStorage["shuffleImages"] == "on") { if(localStorage["shuffleImages"] == "on") {
let len = this.resourceManager.enabledImages.length; let len = this.resourceManager.enabledImages.length;
let index = Math.floor(Math.random() * len); let index = Math.floor(Math.random() * len);
@ -643,9 +644,9 @@ HuesCore.prototype.randomImage = function() {
let img=(this.imageIndex + 1) % this.resourceManager.enabledImages.length; let img=(this.imageIndex + 1) % this.resourceManager.enabledImages.length;
this.setImage(img); this.setImage(img);
} }
}; }
HuesCore.prototype.setImage = function(index, leaveArray) { setImage(index, leaveArray) {
// If there are no images, this corrects NaN to 0 // If there are no images, this corrects NaN to 0
this.imageIndex = index ? index : 0; this.imageIndex = index ? index : 0;
let img=this.resourceManager.enabledImages[this.imageIndex]; let img=this.resourceManager.enabledImages[this.imageIndex];
@ -664,9 +665,9 @@ HuesCore.prototype.setImage = function(index, leaveArray) {
this.lastImageArray = []; this.lastImageArray = [];
} }
this.callEventListeners("newimage", this.currentImage); this.callEventListeners("newimage", this.currentImage);
}; }
HuesCore.prototype.setImageByName = function(name) { setImageByName(name) {
let images = this.resourceManager.enabledImages; let images = this.resourceManager.enabledImages;
for(let i = 0; i < images.length; i++) { for(let i = 0; i < images.length; i++) {
if(images[i].name == name || images[i].fullname == name) { if(images[i].name == name || images[i].fullname == name) {
@ -675,48 +676,48 @@ HuesCore.prototype.setImageByName = function(name) {
} }
} }
this.setImage(0); // fallback this.setImage(0); // fallback
}; }
HuesCore.prototype.nextImage = function() { nextImage() {
this.setIsFullAuto(false); this.setIsFullAuto(false);
let img=(this.imageIndex + 1) % this.resourceManager.enabledImages.length; let img=(this.imageIndex + 1) % this.resourceManager.enabledImages.length;
this.setImage(img); this.setImage(img);
}; }
HuesCore.prototype.previousImage = function() { previousImage() {
this.setIsFullAuto(false); this.setIsFullAuto(false);
let img=((this.imageIndex - 1) + this.resourceManager.enabledImages.length) % this.resourceManager.enabledImages.length; let img=((this.imageIndex - 1) + this.resourceManager.enabledImages.length) % this.resourceManager.enabledImages.length;
this.setImage(img); this.setImage(img);
}; }
HuesCore.prototype.randomColourIndex = function() { randomColourIndex() {
let index=Math.floor((Math.random() * this.colours.length)); let index=Math.floor((Math.random() * this.colours.length));
if (index == this.colourIndex) { if (index == this.colourIndex) {
return this.randomColourIndex(); return this.randomColourIndex();
} }
return index; return index;
}; }
HuesCore.prototype.randomColour = function(isFade) { randomColour(isFade) {
let index=this.randomColourIndex(); let index=this.randomColourIndex();
this.setColour(index, isFade); this.setColour(index, isFade);
}; }
HuesCore.prototype.setColour = function(index, isFade) { setColour(index, isFade) {
this.colourIndex = index; this.colourIndex = index;
let colour = this.colours[this.colourIndex]; let colour = this.colours[this.colourIndex];
this.callEventListeners("newcolour", colour, isFade); this.callEventListeners("newcolour", colour, isFade);
}; }
HuesCore.prototype.getBeat = function(index) { getBeat(index) {
if(index < 0) { if(index < 0) {
return this.currentSong.buildupRhythm[this.currentSong.buildupRhythm.length+index]; return this.currentSong.buildupRhythm[this.currentSong.buildupRhythm.length+index];
} else { } else {
return this.currentSong.rhythm[index % this.currentSong.rhythm.length]; return this.currentSong.rhythm[index % this.currentSong.rhythm.length];
} }
}; }
HuesCore.prototype.beater = function(beat) { beater(beat) {
this.callEventListeners("beat", this.getBeatString(), this.getBeatIndex()); this.callEventListeners("beat", this.getBeatString(), this.getBeatIndex());
switch(beat) { switch(beat) {
case 'X': case 'X':
@ -791,9 +792,9 @@ HuesCore.prototype.beater = function(beat) {
this.randomImage(); this.randomImage();
} }
} }
}; }
HuesCore.prototype.getBeatString = function(length) { getBeatString(length) {
length = length ? length : 256; length = length ? length : 256;
let beatString = ""; let beatString = "";
@ -811,33 +812,33 @@ HuesCore.prototype.getBeatString = function(length) {
} }
return beatString; return beatString;
}; }
HuesCore.prototype.setIsFullAuto = function(auto) { setIsFullAuto(auto) {
this.isFullAuto = auto; this.isFullAuto = auto;
if (this.userInterface) { if (this.userInterface) {
this.callEventListeners("newmode", this.isFullAuto); this.callEventListeners("newmode", this.isFullAuto);
} }
}; }
HuesCore.prototype.toggleFullAuto = function() { toggleFullAuto() {
this.setIsFullAuto(!this.isFullAuto); this.setIsFullAuto(!this.isFullAuto);
}; }
HuesCore.prototype.setInvert = function(invert) { setInvert(invert) {
this.invert = !!invert; this.invert = !!invert;
this.callEventListeners("invert", invert); this.callEventListeners("invert", invert);
}; }
HuesCore.prototype.toggleInvert = function() { toggleInvert() {
this.setInvert(!this.invert); this.setInvert(!this.invert);
}; }
HuesCore.prototype.respackLoaded = function() { respackLoaded() {
this.init(); this.init();
}; }
HuesCore.prototype.changeUI = function(index) { changeUI(index) {
if (index >= 0 && this.uiArray.length > index && this.userInterface != this.uiArray[index]) { if (index >= 0 && this.uiArray.length > index && this.userInterface != this.uiArray[index]) {
this.hideLists(); this.hideLists();
if(this.userInterface) { if(this.userInterface) {
@ -852,9 +853,9 @@ HuesCore.prototype.changeUI = function(index) {
this.callEventListeners("beat", this.getBeatString(), this.getBeatIndex()); this.callEventListeners("beat", this.getBeatString(), this.getBeatIndex());
this.callEventListeners("invert", this.invert); this.callEventListeners("invert", this.invert);
} }
}; }
HuesCore.prototype.settingsUpdated = function() { settingsUpdated() {
this.callEventListeners("settingsupdated"); this.callEventListeners("settingsupdated");
switch (localStorage["currentUI"]) { switch (localStorage["currentUI"]) {
case "retro": case "retro":
@ -878,13 +879,13 @@ HuesCore.prototype.settingsUpdated = function() {
} }
switch (localStorage["colourSet"]) { switch (localStorage["colourSet"]) {
case "normal": case "normal":
this.colours = this.oldColours; this.colours = HuesCore.oldColours;
break; break;
case "pastel": case "pastel":
this.colours = this.pastelColours; this.colours = HuesCore.pastelColours;
break; break;
case "v4.20": case "v4.20":
this.colours = this.weedColours; this.colours = HuesCore.weedColours;
break; break;
} }
switch (localStorage["blackoutUI"]) { switch (localStorage["blackoutUI"]) {
@ -913,39 +914,39 @@ HuesCore.prototype.settingsUpdated = function() {
this.loopCount = 0; this.loopCount = 0;
} }
this.autoSong = localStorage["autoSong"]; this.autoSong = localStorage["autoSong"];
}; }
HuesCore.prototype.enabledChanged = function() { enabledChanged() {
this.resourceManager.rebuildEnabled(); this.resourceManager.rebuildEnabled();
}; }
HuesCore.prototype.hideLists = function() { hideLists() {
this.resourceManager.hideLists(); this.resourceManager.hideLists();
}; }
HuesCore.prototype.toggleSongList = function() { toggleSongList() {
this.window.hide(); this.window.hide();
this.resourceManager.toggleSongList(); this.resourceManager.toggleSongList();
}; }
HuesCore.prototype.toggleImageList = function() { toggleImageList() {
this.window.hide(); this.window.hide();
this.resourceManager.toggleImageList(); this.resourceManager.toggleImageList();
}; }
HuesCore.prototype.openSongSource = function() { openSongSource() {
if (this.currentSong && this.currentSong.source) { if (this.currentSong && this.currentSong.source) {
window.open(this.currentSong.source,'_blank'); window.open(this.currentSong.source,'_blank');
} }
}; }
HuesCore.prototype.openImageSource = function() { openImageSource() {
if (this.currentImage && this.currentImage.source) { if (this.currentImage && this.currentImage.source) {
window.open(this.currentImage.source,'_blank'); window.open(this.currentImage.source,'_blank');
} }
}; }
HuesCore.prototype.keyHandler = function(key) { keyHandler(key) {
switch (key) { switch (key) {
case 37: // LEFT case 37: // LEFT
this.previousImage(); this.previousImage();
@ -1027,26 +1028,27 @@ HuesCore.prototype.keyHandler = function(key) {
return true; return true;
} }
return false; return false;
}; }
HuesCore.prototype.error = function(message) { error(message) {
console.log(message); console.log(message);
this.preloadSubMsg.textContent = message; this.preloadSubMsg.textContent = message;
this.preloadMsg.style.color = "#F00"; this.preloadMsg.style.color = "#F00";
}; }
HuesCore.prototype.warning = function(message) { warning(message) {
console.log(message); console.log(message);
this.preloadSubMsg.innerHTML = message; this.preloadSubMsg.innerHTML = message;
this.preloadMsg.style.color = "#F93"; this.preloadMsg.style.color = "#F93";
}; }
HuesCore.prototype.clearMessage = function() { clearMessage() {
this.preloadSubMsg.textContent = ""; this.preloadSubMsg.textContent = "";
this.preloadMsg.style.color = ""; this.preloadMsg.style.color = "";
}; }
}
HuesCore.prototype.oldColours = HuesCore.oldColours =
[{'c': 0x000000, 'n': 'black'}, [{'c': 0x000000, 'n': 'black'},
{'c': 0x550000, 'n': 'brick'}, {'c': 0x550000, 'n': 'brick'},
{'c': 0xAA0000, 'n': 'crimson'}, {'c': 0xAA0000, 'n': 'crimson'},
@ -1111,7 +1113,7 @@ HuesCore.prototype.oldColours =
{'c': 0x55FFFF, 'n': 'turquoise'}, {'c': 0x55FFFF, 'n': 'turquoise'},
{'c': 0xAAFFFF, 'n': 'powder'}, {'c': 0xAAFFFF, 'n': 'powder'},
{'c': 0xFFFFFF, 'n': 'white'}]; {'c': 0xFFFFFF, 'n': 'white'}];
HuesCore.prototype.pastelColours = HuesCore.pastelColours =
[{'c': 0xCD4A4A, 'n': 'Mahogany'}, [{'c': 0xCD4A4A, 'n': 'Mahogany'},
{'c': 0xFAE7B5, 'n': 'Banana Mania'}, {'c': 0xFAE7B5, 'n': 'Banana Mania'},
{'c': 0x9F8170, 'n': 'Beaver'}, {'c': 0x9F8170, 'n': 'Beaver'},
@ -1176,7 +1178,7 @@ HuesCore.prototype.pastelColours =
{'c': 0xFCE883, 'n': 'Yellow'}, {'c': 0xFCE883, 'n': 'Yellow'},
{'c': 0xC5E384, 'n': 'Yellow Green'}, {'c': 0xC5E384, 'n': 'Yellow Green'},
{'c': 0xFFB653, 'n': 'Yellow Orange'}]; {'c': 0xFFB653, 'n': 'Yellow Orange'}];
HuesCore.prototype.weedColours = HuesCore.weedColours =
[{'c': 0x00FF00, 'n': 'Green'}, [{'c': 0x00FF00, 'n': 'Green'},
{'c': 0x5A6351, 'n': 'Lizard'}, {'c': 0x5A6351, 'n': 'Lizard'},
{'c': 0x636F57, 'n': 'Cactus'}, {'c': 0x636F57, 'n': 'Cactus'},

@ -25,7 +25,8 @@
let WAVE_PIXELS_PER_SECOND = 100; let WAVE_PIXELS_PER_SECOND = 100;
let WAVE_HEIGHT_PIXELS = 20; let WAVE_HEIGHT_PIXELS = 20;
function HuesEditor(core, huesWin) { class HuesEditor {
constructor(core, huesWin) {
this.buildEditSize = 80; // pixels, including header this.buildEditSize = 80; // pixels, including header
this.buildEdit = null; this.buildEdit = null;
this.loopEdit = null; this.loopEdit = null;
@ -62,7 +63,7 @@ function HuesEditor(core, huesWin) {
} }
} }
HuesEditor.prototype.initUI = function() { initUI() {
this.root = document.createElement("div"); this.root = document.createElement("div");
this.root.className = "editor"; this.root.className = "editor";
let titleButtons = document.createElement("div"); let titleButtons = document.createElement("div");
@ -123,9 +124,9 @@ HuesEditor.prototype.initUI = function() {
// tabselected passes the name of the selected tab, we force noHilightCalc to false // tabselected passes the name of the selected tab, we force noHilightCalc to false
this.core.window.addEventListener("tabselected", this.resize.bind(this, false)); this.core.window.addEventListener("tabselected", this.resize.bind(this, false));
this.resize(); this.resize();
}; }
HuesEditor.prototype.resize = function(noHilightCalc) { resize(noHilightCalc) {
this.root.style.height = (window.innerHeight - 200) + "px"; this.root.style.height = (window.innerHeight - 200) + "px";
let boxHeight = this.editArea.offsetHeight; let boxHeight = this.editArea.offsetHeight;
let bHeadHeight = this.buildEdit._header.offsetHeight; let bHeadHeight = this.buildEdit._header.offsetHeight;
@ -171,13 +172,13 @@ HuesEditor.prototype.resize = function(noHilightCalc) {
this.waveCanvas.width = this.waveCanvas.clientWidth; this.waveCanvas.width = this.waveCanvas.clientWidth;
} }
}; }
HuesEditor.prototype.getOther = function(editor) { getOther(editor) {
return editor == this.loopEdit ? this.buildEdit : this.loopEdit; return editor == this.loopEdit ? this.buildEdit : this.loopEdit;
}; }
HuesEditor.prototype.onNewSong = function(song) { onNewSong(song) {
if(this.linked) { if(this.linked) {
if(song == this.song) { if(song == this.song) {
// Because you can "edit current" before it loads // Because you can "edit current" before it loads
@ -196,9 +197,9 @@ HuesEditor.prototype.onNewSong = function(song) {
} else if(song == this.song) { // went to another song then came back } else if(song == this.song) { // went to another song then came back
this.linked = true; this.linked = true;
} }
}; }
HuesEditor.prototype.onBeat = function(map, index) { onBeat(map, index) {
if(!this.song || this.core.currentSong != this.song) { if(!this.song || this.core.currentSong != this.song) {
return; return;
} }
@ -219,9 +220,9 @@ HuesEditor.prototype.onBeat = function(map, index) {
// Not computing width/height here due to Chrome bug // Not computing width/height here due to Chrome bug
editor._hilight.style.left = Math.floor(offsetX * this.hilightWidth) + "px"; editor._hilight.style.left = Math.floor(offsetX * this.hilightWidth) + "px";
editor._hilight.style.top = Math.floor(offsetY * this.hilightHeight) + "px"; editor._hilight.style.top = Math.floor(offsetY * this.hilightHeight) + "px";
}; }
HuesEditor.prototype.reflow = function(editor, map) { reflow(editor, map) {
if(!map) { // NOTHING TO SEE HERE if(!map) { // NOTHING TO SEE HERE
editor._beatmap.textContent = ""; editor._beatmap.textContent = "";
editor._hilight.textContent = "[none]"; editor._hilight.textContent = "[none]";
@ -238,9 +239,9 @@ HuesEditor.prototype.reflow = function(editor, map) {
// if it's too long to wrap, scroll in the x direction // if it's too long to wrap, scroll in the x direction
let regex = new RegExp("(.{" + this.wrapAt + "})", "g"); let regex = new RegExp("(.{" + this.wrapAt + "})", "g");
editor._beatmap.innerHTML = map.replace(regex, "$1<br />"); editor._beatmap.innerHTML = map.replace(regex, "$1<br />");
}; }
HuesEditor.prototype.updateInfo = function() { updateInfo() {
// Avoid a bunch of nested elses // Avoid a bunch of nested elses
this.seekStart.classList.add("hues-button--disabled"); this.seekStart.classList.add("hues-button--disabled");
this.seekLoop.classList.add("hues-button--disabled"); this.seekLoop.classList.add("hues-button--disabled");
@ -283,9 +284,9 @@ HuesEditor.prototype.updateInfo = function() {
this.loopLen.textContent = loopLen.toFixed(2); this.loopLen.textContent = loopLen.toFixed(2);
this.buildLen.textContent = buildLen.toFixed(2); this.buildLen.textContent = buildLen.toFixed(2);
this.beatLen.textContent = beatLen.toFixed(2); this.beatLen.textContent = beatLen.toFixed(2);
}; }
HuesEditor.prototype.loadAudio = function(editor) { loadAudio(editor) {
if(editor._fileInput.files.length < 1) { if(editor._fileInput.files.length < 1) {
return; return;
} }
@ -341,9 +342,9 @@ HuesEditor.prototype.loadAudio = function(editor) {
console.log(error); console.log(error);
this.alert("Couldn't load song! Is it a LAME encoded MP3?"); this.alert("Couldn't load song! Is it a LAME encoded MP3?");
}); });
}; }
HuesEditor.prototype.removeAudio = function(editor) { removeAudio(editor) {
if(!this.song) { if(!this.song) {
return; return;
} }
@ -364,9 +365,9 @@ HuesEditor.prototype.removeAudio = function(editor) {
} }
this.updateInfo(); this.updateInfo();
this.updateHalveDoubleButtons(editor); this.updateHalveDoubleButtons(editor);
}; }
HuesEditor.prototype.blobToArrayBuffer = function(blob) { blobToArrayBuffer(blob) {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
let fr = new FileReader(); let fr = new FileReader();
fr.onload = () => { fr.onload = () => {
@ -377,9 +378,9 @@ HuesEditor.prototype.blobToArrayBuffer = function(blob) {
}; };
fr.readAsArrayBuffer(blob); fr.readAsArrayBuffer(blob);
}); });
}; }
HuesEditor.prototype.newSong = function(song) { newSong(song) {
if(!song) { if(!song) {
song = {"name":"Name", song = {"name":"Name",
"title":"Title", "title":"Title",
@ -433,9 +434,9 @@ HuesEditor.prototype.newSong = function(song) {
this.linked = true; this.linked = true;
this.updateInfo(); this.updateInfo();
this.updateWaveform(); this.updateWaveform();
}; }
HuesEditor.prototype.updateIndependentBuild = function() { updateIndependentBuild() {
// Force independent build if only 1 source is present // Force independent build if only 1 source is present
// Effectively buildup XOR loop - does only 1 exist? // Effectively buildup XOR loop - does only 1 exist?
@ -444,9 +445,9 @@ HuesEditor.prototype.updateIndependentBuild = function() {
if(hasBuild != hasLoop) { if(hasBuild != hasLoop) {
this.setIndependentBuild(true); this.setIndependentBuild(true);
} }
}; }
HuesEditor.prototype.setIndependentBuild = function(indep) { setIndependentBuild(indep) {
this.song.independentBuild = indep; this.song.independentBuild = indep;
if(!indep) { if(!indep) {
// If both are locked, we lock the result, otherwise unlock both // If both are locked, we lock the result, otherwise unlock both
@ -463,23 +464,23 @@ HuesEditor.prototype.setIndependentBuild = function(indep) {
} }
} }
this.updateInfo(); this.updateInfo();
}; }
HuesEditor.prototype.batchUndo = function() { batchUndo() {
if(!this.batchUndoArray) if(!this.batchUndoArray)
this.batchUndoArray = []; this.batchUndoArray = [];
}; }
HuesEditor.prototype.commitUndo = function() { commitUndo() {
if(this.batchUndoArray) { if(this.batchUndoArray) {
this.undoBuffer.push(this.batchUndoArray); this.undoBuffer.push(this.batchUndoArray);
this.trimUndo(); this.trimUndo();
this.batchUndoArray = null; this.batchUndoArray = null;
this.updateUndoUI(); this.updateUndoUI();
} }
}; }
HuesEditor.prototype.pushUndo = function(name, editor, oldText, newText) { pushUndo(name, editor, oldText, newText) {
if(oldText == newText) { if(oldText == newText) {
return; return;
} }
@ -497,23 +498,23 @@ HuesEditor.prototype.pushUndo = function(name, editor, oldText, newText) {
this.trimUndo(); this.trimUndo();
} }
this.updateUndoUI(); this.updateUndoUI();
}; }
HuesEditor.prototype.trimUndo = function() { trimUndo() {
while(this.undoBuffer.length > 50) { while(this.undoBuffer.length > 50) {
this.undoBuffer.shift(); this.undoBuffer.shift();
} }
}; }
HuesEditor.prototype.undo = function() { undo() {
this.undoRedo(this.undoBuffer, this.redoBuffer); this.undoRedo(this.undoBuffer, this.redoBuffer);
}; }
HuesEditor.prototype.redo = function() { redo() {
this.undoRedo(this.redoBuffer, this.undoBuffer); this.undoRedo(this.redoBuffer, this.undoBuffer);
}; }
HuesEditor.prototype.undoRedo = function(from, to) { undoRedo(from, to) {
if(from.length === 0 || !this.song) { if(from.length === 0 || !this.song) {
return; return;
} }
@ -542,15 +543,15 @@ HuesEditor.prototype.undoRedo = function(from, to) {
this.updateInfo(); this.updateInfo();
this.core.updateBeatLength(); this.core.updateBeatLength();
this.core.recalcBeatIndex(); this.core.recalcBeatIndex();
}; }
HuesEditor.prototype.clearUndoRedo = function() { clearUndoRedo() {
this.undoBuffer = []; this.undoBuffer = [];
this.redoBuffer = []; this.redoBuffer = [];
this.updateUndoUI(); this.updateUndoUI();
}; }
HuesEditor.prototype.updateUndoUI = function() { updateUndoUI() {
this.undoBtn.className = "hues-button hues-button--disabled"; this.undoBtn.className = "hues-button hues-button--disabled";
this.redoBtn.className = "hues-button hues-button--disabled"; this.redoBtn.className = "hues-button hues-button--disabled";
@ -560,9 +561,9 @@ HuesEditor.prototype.updateUndoUI = function() {
if(this.redoBuffer.length > 0) { if(this.redoBuffer.length > 0) {
this.redoBtn.classList.remove("hues-button--disabled"); this.redoBtn.classList.remove("hues-button--disabled");
} }
}; }
HuesEditor.prototype.halveBeats = function(editor) { halveBeats(editor) {
let commit = false; let commit = false;
if(!this.song.independentBuild) { if(!this.song.independentBuild) {
commit = true; commit = true;
@ -578,9 +579,9 @@ HuesEditor.prototype.halveBeats = function(editor) {
// We set it so any rounding is padded // We set it so any rounding is padded
this.setIndependentBuild(false); this.setIndependentBuild(false);
} }
}; }
HuesEditor.prototype.doubleBeats = function(editor) { doubleBeats(editor) {
let commit = false; let commit = false;
if(!this.song.independentBuild) { if(!this.song.independentBuild) {
commit = true; commit = true;
@ -596,9 +597,9 @@ HuesEditor.prototype.doubleBeats = function(editor) {
// We set it so any rounding is padded // We set it so any rounding is padded
this.setIndependentBuild(false); this.setIndependentBuild(false);
} }
}; }
HuesEditor.prototype.updateHalveDoubleButtons = function(editor) { updateHalveDoubleButtons(editor) {
editor._halveBtn.className = "hues-button hues-button--disabled"; editor._halveBtn.className = "hues-button hues-button--disabled";
editor._doubleBtn.className = "hues-button hues-button--disabled"; editor._doubleBtn.className = "hues-button hues-button--disabled";
@ -615,9 +616,9 @@ HuesEditor.prototype.updateHalveDoubleButtons = function(editor) {
editor._halveBtn.className = "hues-button"; editor._halveBtn.className = "hues-button";
} }
} }
}; }
HuesEditor.prototype.createTextInput = function(label, subtitle, parent) { createTextInput(label, subtitle, parent) {
let div = document.createElement("div"); let div = document.createElement("div");
div.className = "editor__label"; div.className = "editor__label";
let caption = document.createElement("label"); let caption = document.createElement("label");
@ -635,9 +636,9 @@ HuesEditor.prototype.createTextInput = function(label, subtitle, parent) {
parent.appendChild(div); parent.appendChild(div);
return input; return input;
}; }
HuesEditor.prototype.createButton = function(label, parent, disabled, extraClass) { createButton(label, parent, disabled, extraClass) {
let button = document.createElement("span"); let button = document.createElement("span");
button.className = "hues-button"; button.className = "hues-button";
if(disabled) { if(disabled) {
@ -660,9 +661,9 @@ HuesEditor.prototype.createButton = function(label, parent, disabled, extraClass
button.innerHTML = label.toUpperCase(); button.innerHTML = label.toUpperCase();
parent.appendChild(button); parent.appendChild(button);
return button; return button;
}; }
HuesEditor.prototype.uiCreateInfo = function() { uiCreateInfo() {
let info = document.createElement("div"); let info = document.createElement("div");
this.topBar.appendChild(info); this.topBar.appendChild(info);
info.className = "editor__info"; info.className = "editor__info";
@ -684,9 +685,9 @@ HuesEditor.prototype.uiCreateInfo = function() {
this.source = this.createTextInput("Link:&nbsp;", "Source link", info); this.source = this.createTextInput("Link:&nbsp;", "Source link", info);
this.source.oninput = songUpdate.bind(this, "source"); this.source.oninput = songUpdate.bind(this, "source");
this.source.disabled = true; this.source.disabled = true;
}; }
HuesEditor.prototype.uiCreateImport = function() { uiCreateImport() {
let imports = document.createElement("div"); let imports = document.createElement("div");
this.topBar.appendChild(imports); this.topBar.appendChild(imports);
imports.className = "editor__imports"; imports.className = "editor__imports";
@ -713,9 +714,9 @@ HuesEditor.prototype.uiCreateImport = function() {
this.loopLen = this.uiCreateSongStat("Loop length (s):", "0.00", songInfos); this.loopLen = this.uiCreateSongStat("Loop length (s):", "0.00", songInfos);
this.buildLen = this.uiCreateSongStat("Build length (s):", "0.00", songInfos); this.buildLen = this.uiCreateSongStat("Build length (s):", "0.00", songInfos);
this.beatLen = this.uiCreateSongStat("Beat length (ms):", "0.00", songInfos); this.beatLen = this.uiCreateSongStat("Beat length (ms):", "0.00", songInfos);
}; }
HuesEditor.prototype.uiCreateSongStat = function(name, value, parent) { uiCreateSongStat(name, value, parent) {
let container = document.createElement("div"); let container = document.createElement("div");
parent.appendChild(container); parent.appendChild(container);
let label = document.createElement("span"); let label = document.createElement("span");
@ -726,9 +727,9 @@ HuesEditor.prototype.uiCreateSongStat = function(name, value, parent) {
valueSpan.className = "editor__song-stats__value"; valueSpan.className = "editor__song-stats__value";
container.appendChild(valueSpan); container.appendChild(valueSpan);
return valueSpan; return valueSpan;
}; }
HuesEditor.prototype.uiCreateEditArea = function() { uiCreateEditArea() {
let editArea = document.createElement("div"); let editArea = document.createElement("div");
this.editArea = editArea; this.editArea = editArea;
editArea.className = "edit-area"; editArea.className = "edit-area";
@ -811,9 +812,9 @@ HuesEditor.prototype.uiCreateEditArea = function() {
'<br />' + '<br />' +
'[COPY/SAVE XML] allow for storing the rhythms and easy <br />' + '[COPY/SAVE XML] allow for storing the rhythms and easy <br />' +
'inclusion into a Resource Pack!'; 'inclusion into a Resource Pack!';
}; }
HuesEditor.prototype.uiCreateSingleEditor = function(title, soundName, rhythmName, parent) { uiCreateSingleEditor(title, soundName, rhythmName, parent) {
let container = document.createElement("div"); let container = document.createElement("div");
parent.appendChild(container); parent.appendChild(container);
@ -893,9 +894,9 @@ HuesEditor.prototype.uiCreateSingleEditor = function(title, soundName, rhythmNam
container._locked = 0; container._locked = 0;
return container; return container;
}; }
HuesEditor.prototype.uiCreateControls = function() { uiCreateControls() {
let controls = document.createElement("div"); let controls = document.createElement("div");
controls.className = "edit__controls"; controls.className = "edit__controls";
this.root.appendChild(controls); this.root.appendChild(controls);
@ -948,9 +949,9 @@ HuesEditor.prototype.uiCreateControls = function() {
}; };
wrapControl.appendChild(wrapAt); wrapControl.appendChild(wrapAt);
}; }
HuesEditor.prototype.uiCreateVisualiser = function() { uiCreateVisualiser() {
let wave = document.createElement("canvas"); let wave = document.createElement("canvas");
wave.className = "waveform"; wave.className = "waveform";
wave.height = WAVE_HEIGHT_PIXELS; wave.height = WAVE_HEIGHT_PIXELS;
@ -959,9 +960,9 @@ HuesEditor.prototype.uiCreateVisualiser = function() {
this.waveContext = wave.getContext("2d"); this.waveContext = wave.getContext("2d");
this.core.addEventListener("frame", this.drawWave.bind(this)); this.core.addEventListener("frame", this.drawWave.bind(this));
}; }
HuesEditor.prototype.rightClick = function(editor, event) { rightClick(editor, event) {
if(!this.linked) { if(!this.linked) {
return; return;
} }
@ -990,9 +991,9 @@ HuesEditor.prototype.rightClick = function(editor, event) {
event.preventDefault(); event.preventDefault();
return false; return false;
}; }
HuesEditor.prototype.getTextCoords = function(event) { getTextCoords(event) {
// http://stackoverflow.com/a/10816667 // http://stackoverflow.com/a/10816667
let el = event.target, let el = event.target,
x = 0, x = 0,
@ -1008,9 +1009,9 @@ HuesEditor.prototype.getTextCoords = function(event) {
y = Math.floor((event.clientY - y) / this.hilightHeight); y = Math.floor((event.clientY - y) / this.hilightHeight);
return {x: x, y: y}; return {x: x, y: y};
}; }
HuesEditor.prototype.textUpdated = function(editor) { textUpdated(editor) {
if(!this.song || !this.song[editor._sound]) { if(!this.song || !this.song[editor._sound]) {
this.reflow(editor, ""); this.reflow(editor, "");
return; return;
@ -1021,17 +1022,17 @@ HuesEditor.prototype.textUpdated = function(editor) {
input = "."; input = ".";
} }
this.setText(editor, input); this.setText(editor, input);
}; }
HuesEditor.prototype.getText = function(editor) { getText(editor) {
if(!this.song || !this.song[editor._rhythm]) { if(!this.song || !this.song[editor._rhythm]) {
return ""; return "";
} else { } else {
return this.song[editor._rhythm]; return this.song[editor._rhythm];
} }
}; }
HuesEditor.prototype.setText = function(editor, text, caretFromEnd) { setText(editor, text, caretFromEnd) {
if(!this.song || !this.song[editor._sound]) { if(!this.song || !this.song[editor._sound]) {
this.reflow(editor, ""); this.reflow(editor, "");
return; return;
@ -1098,9 +1099,9 @@ HuesEditor.prototype.setText = function(editor, text, caretFromEnd) {
// We may have to go backwards in time // We may have to go backwards in time
this.core.recalcBeatIndex(); this.core.recalcBeatIndex();
this.updateInfo(); this.updateInfo();
}; }
HuesEditor.prototype.getCaret = function(editable) { getCaret(editable) {
let caret = 0; let caret = 0;
let sel = window.getSelection(); let sel = window.getSelection();
if (sel.rangeCount) { if (sel.rangeCount) {
@ -1117,9 +1118,9 @@ HuesEditor.prototype.getCaret = function(editable) {
} }
} }
return 0; return 0;
}; }
HuesEditor.prototype.setCaret = function(editable, caret) { setCaret(editable, caret) {
let range = document.createRange(); let range = document.createRange();
let sel = window.getSelection(); let sel = window.getSelection();
// <br> elements mean children go up in multiples of 2 // <br> elements mean children go up in multiples of 2
@ -1135,9 +1136,9 @@ HuesEditor.prototype.setCaret = function(editable, caret) {
break; break;
} }
} }
}; }
HuesEditor.prototype.setLocked = function(editor, locked) { setLocked(editor, locked) {
editor._locked = locked; editor._locked = locked;
if(locked) { if(locked) {
editor._lockedBtn.innerHTML = "&#xe906;"; // LOCKED editor._lockedBtn.innerHTML = "&#xe906;"; // LOCKED
@ -1153,9 +1154,9 @@ HuesEditor.prototype.setLocked = function(editor, locked) {
this.song.independentBuild = false; this.song.independentBuild = false;
} }
this.updateHalveDoubleButtons(editor); this.updateHalveDoubleButtons(editor);
}; }
HuesEditor.prototype.updateWaveform = function() { updateWaveform() {
if(this.buildWaveBuff != this.core.soundManager.buildup) { if(this.buildWaveBuff != this.core.soundManager.buildup) {
this.buildWaveBuff = this.core.soundManager.buildup; this.buildWaveBuff = this.core.soundManager.buildup;
this.buildWave = this.renderWave(this.buildWaveBuff, this.core.soundManager.buildLength); this.buildWave = this.renderWave(this.buildWaveBuff, this.core.soundManager.buildLength);
@ -1164,9 +1165,9 @@ HuesEditor.prototype.updateWaveform = function() {
this.loopWaveBuff = this.core.soundManager.loop; this.loopWaveBuff = this.core.soundManager.loop;
this.loopWave = this.renderWave(this.loopWaveBuff, this.core.soundManager.loopLength); this.loopWave = this.renderWave(this.loopWaveBuff, this.core.soundManager.loopLength);
} }
}; }
HuesEditor.prototype.renderWave = function(buffer, length) { renderWave(buffer, length) {
if(!buffer) { if(!buffer) {
return null; return null;
} }
@ -1227,9 +1228,9 @@ HuesEditor.prototype.renderWave = function(buffer, length) {
} }
return wave; return wave;
}; }
HuesEditor.prototype.drawWave = function() { drawWave() {
if((!this.buildWave && !this.loopWave) || !this.linked) if((!this.buildWave && !this.loopWave) || !this.linked)
return; return;
@ -1285,9 +1286,9 @@ HuesEditor.prototype.drawWave = function() {
for(let point of loopPoints) { for(let point of loopPoints) {
this.drawWaveBar("green", point); this.drawWaveBar("green", point);
} }
}; }
HuesEditor.prototype.drawOneWave = function(wave, waveOffset, drawOffset, width) { drawOneWave(wave, waveOffset, drawOffset, width) {
let drawWidth = Math.min(width - drawOffset, wave.width - waveOffset); let drawWidth = Math.min(width - drawOffset, wave.width - waveOffset);
this.waveContext.drawImage(wave, this.waveContext.drawImage(wave,
waveOffset, 0, // source x/y waveOffset, 0, // source x/y
@ -1295,30 +1296,30 @@ HuesEditor.prototype.drawOneWave = function(wave, waveOffset, drawOffset, width)
drawOffset, 0, // dest x/y drawOffset, 0, // dest x/y
drawWidth, WAVE_HEIGHT_PIXELS); // dest width/height drawWidth, WAVE_HEIGHT_PIXELS); // dest width/height
return drawOffset + drawWidth; return drawOffset + drawWidth;
}; }
HuesEditor.prototype.drawWaveBar = function(colour, offset) { drawWaveBar(colour, offset) {
this.waveContext.strokeStyle = colour; this.waveContext.strokeStyle = colour;
this.waveContext.lineWidth = 2; this.waveContext.lineWidth = 2;
this.waveContext.beginPath(); this.waveContext.beginPath();
this.waveContext.moveTo(offset, 0); this.waveContext.moveTo(offset, 0);
this.waveContext.lineTo(offset, WAVE_HEIGHT_PIXELS); this.waveContext.lineTo(offset, WAVE_HEIGHT_PIXELS);
this.waveContext.stroke(); this.waveContext.stroke();
}; }
HuesEditor.prototype.confirmLeave = function() { confirmLeave() {
return "Unsaved beatmap - leave anyway?"; return "Unsaved beatmap - leave anyway?";
}; }
HuesEditor.prototype.alert = function(msg) { alert(msg) {
this.statusMsg.classList.remove("editor__status-msg--fade"); this.statusMsg.classList.remove("editor__status-msg--fade");
this.statusMsg.textContent = msg; this.statusMsg.textContent = msg;
// Trigger a reflow and thus restart the animation // Trigger a reflow and thus restart the animation
var useless = this.statusMsg.offsetWidth; var useless = this.statusMsg.offsetWidth;
this.statusMsg.classList.add("editor__status-msg--fade"); this.statusMsg.classList.add("editor__status-msg--fade");
}; }
HuesEditor.prototype.generateXML = function() { generateXML() {
if(!this.song) { if(!this.song) {
return null; return null;
} }
@ -1339,9 +1340,9 @@ HuesEditor.prototype.generateXML = function() {
} }
result += " </song>\n"; result += " </song>\n";
return result; return result;
}; }
HuesEditor.prototype.saveXML = function() { saveXML() {
let xml = this.generateXML(); let xml = this.generateXML();
if(!xml) { if(!xml) {
return; return;
@ -1363,10 +1364,10 @@ HuesEditor.prototype.saveXML = function() {
document.body.removeChild(element); document.body.removeChild(element);
window.onbeforeunload = null; window.onbeforeunload = null;
}; }
// http://stackoverflow.com/a/30810322 // http://stackoverflow.com/a/30810322
HuesEditor.prototype.copyXML = function() { copyXML() {
let text = this.generateXML(); let text = this.generateXML();
// Clicking when disabled // Clicking when disabled
@ -1397,7 +1398,8 @@ HuesEditor.prototype.copyXML = function() {
} else { } else {
this.alert("Copy failed! Try saving instead"); this.alert("Copy failed! Try saving instead");
} }
}; }
}
window.HuesEditor = HuesEditor; window.HuesEditor = HuesEditor;

@ -26,7 +26,7 @@
/* HuesInfo.js populates the INFO tab in the Hues Window. /* HuesInfo.js populates the INFO tab in the Hues Window.
*/ */
let beatGlossary = [ const beatGlossary = [
"x Vertical blur (snare)", "x Vertical blur (snare)",
"o Horizontal blur (bass)", "o Horizontal blur (bass)",
"- No blur", "- No blur",
@ -44,7 +44,7 @@ let beatGlossary = [
"I Invert & change image" "I Invert & change image"
]; ];
let shortcuts = [ const shortcuts = [
"↑↓ Change song", "↑↓ Change song",
"←→ Change image", "←→ Change image",
"[N] Random song", "[N] Random song",

@ -26,7 +26,7 @@
/* If you're modifying settings for your hues, DON'T EDIT THIS /* If you're modifying settings for your hues, DON'T EDIT THIS
- Go to the HTML and edit the `defaults` object instead! - Go to the HTML and edit the `defaults` object instead!
*/ */
HuesSettings.prototype.defaultSettings = { const defaultSettings = {
// Location relative to root - where do the audio/zip workers live // Location relative to root - where do the audio/zip workers live
// This is required because Web Workers need an absolute path // This is required because Web Workers need an absolute path
workersPath : "lib/workers/", workersPath : "lib/workers/",
@ -80,7 +80,7 @@ HuesSettings.prototype.defaultSettings = {
}; };
// Don't get saved to localStorage // Don't get saved to localStorage
HuesSettings.prototype.ephemeralSettings = [ const ephemeralSettings = [
"load", "load",
"autoplay", "autoplay",
"overwriteLocal", "overwriteLocal",
@ -100,7 +100,7 @@ HuesSettings.prototype.ephemeralSettings = [
]; ];
// To dynamically build the UI like the cool guy I am // To dynamically build the UI like the cool guy I am
HuesSettings.prototype.settingsCategories = { const settingsCategories = {
"Functionality" : [ "Functionality" : [
"autoSong", "autoSong",
"autoSongShuffle", "autoSongShuffle",
@ -126,7 +126,7 @@ HuesSettings.prototype.settingsCategories = {
] ]
}; };
HuesSettings.prototype.settingsOptions = { const settingsOptions = {
smartAlign : { smartAlign : {
name : "Smart Align images", name : "Smart Align images",
options : ["off", "on"] options : ["off", "on"]
@ -218,7 +218,8 @@ HuesSettings.prototype.settingsOptions = {
} }
}; };
function HuesSettings(defaults) { class HuesSettings {
constructor(defaults) {
this.eventListeners = { this.eventListeners = {
/* callback updated() /* callback updated()
* *
@ -234,13 +235,13 @@ function HuesSettings(defaults) {
this.textCallbacks = []; this.textCallbacks = [];
this.visCallbacks = []; this.visCallbacks = [];
for(let attr in this.defaultSettings) { for(let attr in defaultSettings) {
if(this.defaultSettings.hasOwnProperty(attr)) { if(defaultSettings.hasOwnProperty(attr)) {
if(defaults[attr] === undefined) { if(defaults[attr] === undefined) {
defaults[attr] = this.defaultSettings[attr]; defaults[attr] = defaultSettings[attr];
} }
// don't write to local if it's a temp settings // don't write to local if it's a temp settings
if(this.ephemeralSettings.indexOf(attr) != -1) { if(ephemeralSettings.indexOf(attr) != -1) {
continue; continue;
} }
if(defaults.overwriteLocal) { if(defaults.overwriteLocal) {
@ -256,7 +257,7 @@ function HuesSettings(defaults) {
this.defaults = defaults; this.defaults = defaults;
} }
HuesSettings.prototype.initUI = function(huesWin) { initUI(huesWin) {
let root = document.createElement("div"); let root = document.createElement("div");
root.className = "hues-options"; root.className = "hues-options";
@ -273,16 +274,16 @@ HuesSettings.prototype.initUI = function(huesWin) {
}; };
// To order things nicely // To order things nicely
for(let cat in this.settingsCategories) { for(let cat in settingsCategories) {
if(this.settingsCategories.hasOwnProperty(cat)) { if(settingsCategories.hasOwnProperty(cat)) {
let catContainer = document.createElement("div"); let catContainer = document.createElement("div");
catContainer.textContent = cat; catContainer.textContent = cat;
catContainer.className = "settings-category"; catContainer.className = "settings-category";
let cats = this.settingsCategories[cat]; let cats = settingsCategories[cat];
for(let i = 0; i < cats.length; i++) { for(let i = 0; i < cats.length; i++) {
let setName = cats[i]; let setName = cats[i];
let setContainer = document.createElement("div"); let setContainer = document.createElement("div");
let setting = this.settingsOptions[setName]; let setting = settingsOptions[setName];
setContainer.textContent = setting.name; setContainer.textContent = setting.name;
setContainer.className = "settings-individual"; setContainer.className = "settings-individual";
let buttonContainer = document.createElement("div"); let buttonContainer = document.createElement("div");
@ -351,11 +352,11 @@ HuesSettings.prototype.initUI = function(huesWin) {
} }
huesWin.addTab("OPTIONS", root); huesWin.addTab("OPTIONS", root);
this.hasUI = true; this.hasUI = true;
}; }
HuesSettings.prototype.get = function(setting) { get(setting) {
if(this.defaults.hasOwnProperty(setting)) { if(this.defaults.hasOwnProperty(setting)) {
if(this.ephemeralSettings.indexOf(setting) != -1) { if(ephemeralSettings.indexOf(setting) != -1) {
return this.defaults[setting]; return this.defaults[setting];
} else { } else {
return localStorage[setting]; return localStorage[setting];
@ -364,12 +365,12 @@ HuesSettings.prototype.get = function(setting) {
console.log("WARNING: Attempted to fetch invalid setting:", setting); console.log("WARNING: Attempted to fetch invalid setting:", setting);
return null; return null;
} }
}; }
// Set a named index to its named value, returns false if name doesn't exist // Set a named index to its named value, returns false if name doesn't exist
HuesSettings.prototype.set = function(setting, value) { set(setting, value) {
value = value.toLowerCase(); value = value.toLowerCase();
let opt = this.settingsOptions[setting]; let opt = settingsOptions[setting];
if(!opt || opt.options.indexOf(value) == -1) { if(!opt || opt.options.indexOf(value) == -1) {
console.log(value, "is not a valid value for", setting); console.log(value, "is not a valid value for", setting);
return false; return false;
@ -382,9 +383,9 @@ HuesSettings.prototype.set = function(setting, value) {
this.updateConditionals(); this.updateConditionals();
this.callEventListeners("updated"); this.callEventListeners("updated");
return true; return true;
}; }
HuesSettings.prototype.updateConditionals = function() { updateConditionals() {
// update any conditionally formatted settings text // update any conditionally formatted settings text
for(let i = 0; i < this.textCallbacks.length; i++) { for(let i = 0; i < this.textCallbacks.length; i++) {
let text = this.textCallbacks[i]; let text = this.textCallbacks[i];
@ -394,38 +395,38 @@ HuesSettings.prototype.updateConditionals = function() {
let callback = this.visCallbacks[i]; let callback = this.visCallbacks[i];
callback.element.style.visibility = callback.func() ? "visible" : "hidden"; callback.element.style.visibility = callback.func() ? "visible" : "hidden";
} }
}; }
// Note: This is not defaults as per defaultSettings, but those merged with // Note: This is not defaults as per defaultSettings, but those merged with
// the defaults given in the initialiser // the defaults given in the initialiser
HuesSettings.prototype.setDefaults = function() { setDefaults() {
for(let attr in this.defaults) { for(let attr in this.defaults) {
if(this.defaults.hasOwnProperty(attr)) { if(this.defaults.hasOwnProperty(attr)) {
if(this.ephemeralSettings.indexOf(attr) != -1) { if(ephemeralSettings.indexOf(attr) != -1) {
continue; continue;
} }
localStorage[attr] = this.defaults[attr]; localStorage[attr] = this.defaults[attr];
} }
} }
}; }
HuesSettings.prototype.callEventListeners = function(ev) { callEventListeners(ev) {
let args = Array.prototype.slice.call(arguments, 1); let args = Array.prototype.slice.call(arguments, 1);
this.eventListeners[ev].forEach(function(callback) { this.eventListeners[ev].forEach(function(callback) {
callback.apply(null, args); callback.apply(null, args);
}); });
}; }
HuesSettings.prototype.addEventListener = function(ev, callback) { addEventListener(ev, callback) {
ev = ev.toLowerCase(); ev = ev.toLowerCase();
if (typeof(this.eventListeners[ev]) !== "undefined") { if (typeof(this.eventListeners[ev]) !== "undefined") {
this.eventListeners[ev].push(callback); this.eventListeners[ev].push(callback);
} else { } else {
throw Error("Unknown event: " + ev); throw Error("Unknown event: " + ev);
} }
}; }
HuesSettings.prototype.removeEventListener = function(ev, callback) { removeEventListener(ev, callback) {
ev = ev.toLowerCase(); ev = ev.toLowerCase();
if (typeof(this.eventListeners[ev]) !== "undefined") { if (typeof(this.eventListeners[ev]) !== "undefined") {
this.eventListeners[ev] = this.eventListeners[ev].filter(function(a) { this.eventListeners[ev] = this.eventListeners[ev].filter(function(a) {
@ -434,7 +435,8 @@ HuesSettings.prototype.removeEventListener = function(ev, callback) {
} else { } else {
throw Error("Unknown event: " + ev); throw Error("Unknown event: " + ev);
} }
}; }
}
window.HuesSettings = HuesSettings; window.HuesSettings = HuesSettings;

@ -27,7 +27,9 @@
to put all your own elements under, but make a div to put all your own elements under, but make a div
underneath so it can be entirely hidden. underneath so it can be entirely hidden.
*/ */
function HuesUI(parent, name) { class HuesUI {
constructor(parent, name) {
if(!parent) { if(!parent) {
return; return;
} }
@ -74,11 +76,11 @@ function HuesUI(parent, name) {
this.initUI(); this.initUI();
} }
HuesUI.prototype.addCoreCallback = function(name, func) { addCoreCallback(name, func) {
this.callbacks.push({name : name, func : func}); this.callbacks.push({name : name, func : func});
}; }
HuesUI.prototype.initUI = function() { initUI() {
// Major info, image, song names // Major info, image, song names
let imageName = document.createElement("div"); let imageName = document.createElement("div");
this.imageName = imageName; this.imageName = imageName;
@ -161,9 +163,9 @@ HuesUI.prototype.initUI = function() {
this.addCoreCallback("time", this.updateTime.bind(this)); this.addCoreCallback("time", this.updateTime.bind(this));
this.addCoreCallback("invert", this.invert.bind(this)); this.addCoreCallback("invert", this.invert.bind(this));
this.resizeHandler = this.resize.bind(this); this.resizeHandler = this.resize.bind(this);
}; }
HuesUI.prototype.connectCore = function(core) { connectCore(core) {
this.core = core; this.core = core;
this.root.style.display = "block"; this.root.style.display = "block";
if(core.resourceManager.hasUI) { if(core.resourceManager.hasUI) {
@ -176,9 +178,9 @@ HuesUI.prototype.connectCore = function(core) {
}); });
window.addEventListener('resize', this.resizeHandler); window.addEventListener('resize', this.resizeHandler);
this.resizeHandler(); this.resizeHandler();
}; }
HuesUI.prototype.disconnect = function() { disconnect() {
this.callbacks.forEach(callback => { this.callbacks.forEach(callback => {
this.core.removeEventListener(callback.name, callback.func); this.core.removeEventListener(callback.name, callback.func);
}); });
@ -191,40 +193,40 @@ HuesUI.prototype.disconnect = function() {
this.visualiserContainer.removeChild(this.visualiserContainer.firstElementChild); this.visualiserContainer.removeChild(this.visualiserContainer.firstElementChild);
} }
window.removeEventListener('resize', this.resizeHandler); window.removeEventListener('resize', this.resizeHandler);
}; }
// ONLY FOR CHANGING UI, NOT FOR "HIDE" FEATURE // ONLY FOR CHANGING UI, NOT FOR "HIDE" FEATURE
HuesUI.prototype.show = function() { show() {
this.root.style.display = "block"; this.root.style.display = "block";
}; }
// ONLY FOR CHANGING UI, NOT FOR "HIDE" FEATURE // ONLY FOR CHANGING UI, NOT FOR "HIDE" FEATURE
HuesUI.prototype.hide = function() { hide() {
this.root.style.display = "none"; this.root.style.display = "none";
}; }
HuesUI.prototype.toggleHide = function() { toggleHide() {
this.hidden = !this.hidden; this.hidden = !this.hidden;
if(this.hidden) { if(this.hidden) {
this.root.classList.add("hues-ui--hidden"); this.root.classList.add("hues-ui--hidden");
} else { } else {
this.root.classList.remove("hues-ui--hidden"); this.root.classList.remove("hues-ui--hidden");
} }
}; }
HuesUI.prototype.resize = function() {}; resize() {}
HuesUI.prototype.updateVolume = function(vol) {}; updateVolume(vol) {}
HuesUI.prototype.newSong = function(song) { newSong(song) {
if(!song) { if(!song) {
return; return;
} }
this.songLink.textContent = song.title.toUpperCase(); this.songLink.textContent = song.title.toUpperCase();
this.songLink.href = song.source; this.songLink.href = song.source;
}; }
HuesUI.prototype.newImage = function(image) { newImage(image) {
if(!image) { if(!image) {
return; return;
} }
@ -233,62 +235,52 @@ HuesUI.prototype.newImage = function(image) {
this.imageLink.textContent = name.toUpperCase(); this.imageLink.textContent = name.toUpperCase();
this.imageLink.href = image.source ? image.source : ""; this.imageLink.href = image.source ? image.source : "";
}; }
HuesUI.prototype.newColour = function(colour) { newColour(colour) {
this.hueName.textContent = colour.n.toUpperCase(); this.hueName.textContent = colour.n.toUpperCase();
}; }
HuesUI.prototype.blurUpdated = function(x, y) { blurUpdated(x, y) {
x = Math.floor(x * 0xFF); x = Math.floor(x * 0xFF);
y = Math.floor(y * 0xFF); y = Math.floor(y * 0xFF);
this.xBlur.textContent = "X=" + this.intToHex(x, 2); this.xBlur.textContent = "X=" + this.intToHex(x, 2);
this.yBlur.textContent = "Y=" + this.intToHex(y, 2); this.yBlur.textContent = "Y=" + this.intToHex(y, 2);
}; }
HuesUI.prototype.updateTime = function(time) { updateTime(time) {
time = Math.floor(time * 1000); time = Math.floor(time * 1000);
this.timer.textContent = "T=" + this.intToHex(time, 5); this.timer.textContent = "T=" + this.intToHex(time, 5);
}; }
HuesUI.prototype.intToHex = function(num, pad) { intToHex(num, pad) {
let str = Math.abs(num).toString(16); let str = Math.abs(num).toString(16);
while (str.length < pad) while (str.length < pad)
str = "0" + str; str = "0" + str;
let prefix = num < 0 ? "-" : "$"; let prefix = num < 0 ? "-" : "$";
return prefix + "0x" + str; return prefix + "0x" + str;
}; }
HuesUI.prototype.invert = function(invert) { invert(invert) {
if (invert) { if (invert) {
this.root.classList.add("inverted"); this.root.classList.add("inverted");
} else { } else {
this.root.classList.remove("inverted"); this.root.classList.remove("inverted");
} }
}; }
}
/* /*
Individual UIs ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Individual UIs ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
*/ */
function RetroUI(parent, name) { class RetroUI extends HuesUI {
this.container = null; constructor(parent, name) {
this.mode = null; super(parent, name ? name : "RetroUI");
this.beatBar = null;
this.colourIndex = null;
this.version = null;
this.imageModeAuto = null;
this.imageModeAuto = null;
this.subControls = null;
HuesUI.call(this, parent, name ? name : "RetroUI");
} }
RetroUI.prototype = Object.create(HuesUI.prototype); initUI() {
RetroUI.prototype.constructor = RetroUI; super.initUI();
RetroUI.prototype.initUI = function() {
HuesUI.prototype.initUI.call(this);
let container = document.createElement("div"); let container = document.createElement("div");
container.className = "hues-r-container"; container.className = "hues-r-container";
@ -376,9 +368,9 @@ RetroUI.prototype.initUI = function() {
this.addCoreCallback("beat", this.beat.bind(this)); this.addCoreCallback("beat", this.beat.bind(this));
this.addCoreCallback("newmode", this.newMode.bind(this)); this.addCoreCallback("newmode", this.newMode.bind(this));
}; }
RetroUI.prototype.toggleHide = function() { toggleHide() {
this.hidden = !this.hidden; this.hidden = !this.hidden;
if(this.hidden) { if(this.hidden) {
this.subControls.classList.add("hues-ui--hidden"); this.subControls.classList.add("hues-ui--hidden");
@ -391,73 +383,71 @@ RetroUI.prototype.toggleHide = function() {
this.container.classList.remove("hues-ui--hidden"); this.container.classList.remove("hues-ui--hidden");
this.hideRestore.classList.remove("hues-ui--hidden"); this.hideRestore.classList.remove("hues-ui--hidden");
} }
}; }
RetroUI.prototype.connectCore = function(core) { connectCore(core) {
HuesUI.prototype.connectCore.call(this, core); super.connectCore(core);
this.version.textContent = "V=$" + core.versionHex; this.version.textContent = "V=$" + core.versionHex;
}; }
RetroUI.prototype.newMode = function(isAuto) { newMode(isAuto) {
this.mode.textContent = "M=" + (isAuto ? "FULL AUTO" : "NORMAL"); this.mode.textContent = "M=" + (isAuto ? "FULL AUTO" : "NORMAL");
}; }
RetroUI.prototype.newImage = function(image) { newImage(image) {
if(!image) { if(!image) {
return; return;
} }
this.imageLink.textContent = "I=" + image.name.toUpperCase(); this.imageLink.textContent = "I=" + image.name.toUpperCase();
this.imageLink.href = image.source; this.imageLink.href = image.source;
}; }
RetroUI.prototype.newColour = function(colour) { newColour(colour) {
HuesUI.prototype.newColour.call(this, colour); super.newColour(colour);
this.colourIndex.textContent = "C=" + this.intToHex(this.core.colourIndex, 2); this.colourIndex.textContent = "C=" + this.intToHex(this.core.colourIndex, 2);
}; }
RetroUI.prototype.beat = function(beats, index) { beat(beats, index) {
let rest = beats.slice(1); let rest = beats.slice(1);
this.beatBar.textContent = ">>" + rest; this.beatBar.textContent = ">>" + rest;
this.beatCount.textContent = "B=" + this.intToHex(index, 4); this.beatCount.textContent = "B=" + this.intToHex(index, 4);
}; }
RetroUI.prototype.resize = function() { resize() {
this.core.visualiser.width = this.visualiserContainer.offsetWidth; this.core.visualiser.width = this.visualiserContainer.offsetWidth;
this.core.resizeVisualiser(); this.core.resizeVisualiser();
}; }
function MinimalUI(parent, name) {
RetroUI.call(this, parent, name ? name : "MinimalUI");
} }
MinimalUI.prototype = Object.create(RetroUI.prototype); class MinimalUI extends RetroUI {
MinimalUI.prototype.constructor = MinimalUI; constructor(parent, name) {
super(parent, name ? name : "MinimalUI");
}
MinimalUI.prototype.initUI = function() { initUI() {
RetroUI.prototype.initUI.call(this); super.initUI();
this.root.removeChild(this.controls); this.root.removeChild(this.controls);
this.root.removeChild(this.subControls); this.root.removeChild(this.subControls);
this.container.removeChild(this.beatBar); this.container.removeChild(this.beatBar);
this.container.innerHTML = ""; this.container.innerHTML = "";
this.container.appendChild(this.beatBar); this.container.appendChild(this.beatBar);
}; }
}
function WeedUI(parent, name) { class WeedUI extends RetroUI {
RetroUI.call(this, parent, name ? name : "WeedUI"); constructor(parent, name) {
super(parent, name ? name : "WeedUI");
this.xVariance = 10; this.xVariance = 10;
this.yVariance = 20; this.yVariance = 20;
} }
WeedUI.prototype = Object.create(RetroUI.prototype); initUI() {
WeedUI.prototype.constructor = WeedUI; super.initUI();
WeedUI.prototype.initUI = function() {
RetroUI.prototype.initUI.call(this);
this.container.removeChild(this.beatBar); this.container.removeChild(this.beatBar);
@ -483,18 +473,18 @@ WeedUI.prototype.initUI = function() {
this.imageModeAuto.textContent = "MANY"; this.imageModeAuto.textContent = "MANY";
this.visualiserContainer.className += " hues-w-visualisercontainer"; this.visualiserContainer.className += " hues-w-visualisercontainer";
}; }
WeedUI.prototype.toggleHide = function() { toggleHide() {
RetroUI.prototype.toggleHide.call(this); super.toggleHide(this);
if(this.hidden) { if(this.hidden) {
this.beatBar.classList.add("hues-ui--hidden"); this.beatBar.classList.add("hues-ui--hidden");
} else { } else {
this.beatBar.classList.remove("hues-ui--hidden"); this.beatBar.classList.remove("hues-ui--hidden");
} }
}; }
WeedUI.prototype.beat = function(beats, index) { beat(beats, index) {
let rest = beats.slice(1); let rest = beats.slice(1);
this.beatLeft.textContent = rest; this.beatLeft.textContent = rest;
@ -516,29 +506,20 @@ WeedUI.prototype.beat = function(beats, index) {
this.root.appendChild(beatCenter); this.root.appendChild(beatCenter);
window.setTimeout(this.removeBeat.bind(this, beatCenter), 1500); window.setTimeout(this.removeBeat.bind(this, beatCenter), 1500);
} }
}; }
WeedUI.prototype.round10 = function(num) { round10(num) {
return Math.round(num * 10) / 10; return Math.round(num * 10) / 10;
}; }
WeedUI.prototype.removeBeat = function(element) { removeBeat(element) {
this.root.removeChild(element); this.root.removeChild(element);
}; }
}
function ModernUI(parent, name) { class ModernUI extends HuesUI {
this.beatBar = null; constructor(parent, name) {
this.beatLeft = null; super(parent, name ? name : "ModernUI");
this.beatRight = null;
this.beatCenter = null;
this.rightBox = null;
this.leftBox = null;
this.rightInfo = null;
this.leftInfo = null;
this.controls = null;
this.volInput = null;
this.volLabel = null;
this.hideRestore = null;
this.textSize_normal = 0; this.textSize_normal = 0;
this.textSize_small = 0; this.textSize_small = 0;
@ -547,16 +528,11 @@ function ModernUI(parent, name) {
this.currentBeat = "."; this.currentBeat = ".";
HuesUI.call(this, parent, name ? name : "ModernUI");
this.hidden = 0; // we have a 3 stage hide this.hidden = 0; // we have a 3 stage hide
} }
ModernUI.prototype = Object.create(HuesUI.prototype); initUI() {
ModernUI.prototype.constructor = ModernUI; super.initUI();
ModernUI.prototype.initUI = function() {
HuesUI.prototype.initUI.call(this);
this.imageName.className = "hues-m-imagename"; this.imageName.className = "hues-m-imagename";
this.songName.className = "hues-m-songtitle"; this.songName.className = "hues-m-songtitle";
@ -715,9 +691,9 @@ ModernUI.prototype.initUI = function() {
this.addCoreCallback("beat", this.beat.bind(this)); this.addCoreCallback("beat", this.beat.bind(this));
this.addCoreCallback("newmode", this.newMode.bind(this)); this.addCoreCallback("newmode", this.newMode.bind(this));
}; }
ModernUI.prototype.toggleHide = function() { toggleHide() {
// classList is new-ish, but if you have web audio you'll have this // classList is new-ish, but if you have web audio you'll have this
this.beatBar.classList.remove("hues-ui--hidden"); this.beatBar.classList.remove("hues-ui--hidden");
this.beatCenter.classList.remove("hues-ui--hidden"); this.beatCenter.classList.remove("hues-ui--hidden");
@ -733,26 +709,26 @@ ModernUI.prototype.toggleHide = function() {
this.hideRestore.classList.add("hues-ui--hidden"); this.hideRestore.classList.add("hues-ui--hidden");
} }
this.hidden = (this.hidden+1) % 3; this.hidden = (this.hidden+1) % 3;
}; }
ModernUI.prototype.updateVolume = function(vol) { updateVolume(vol) {
this.volInput.value = vol; this.volInput.value = vol;
if(vol === 0) { if(vol === 0) {
this.volLabel.textContent = "(VOL)"; this.volLabel.textContent = "(VOL)";
} else { } else {
this.volLabel.textContent = "VOL"; this.volLabel.textContent = "VOL";
} }
}; }
ModernUI.prototype.newMode = function(isAuto) { newMode (isAuto) {
if(isAuto) { if(isAuto) {
this.imageMode.innerHTML = '&#xe902;'; // PAUSE; this.imageMode.innerHTML = '&#xe902;'; // PAUSE;
} else { } else {
this.imageMode.innerHTML = "&#xe901;"; // PLAY this.imageMode.innerHTML = "&#xe901;"; // PLAY
} }
}; }
ModernUI.prototype.beat = function(beats, index) { beat(beats, index) {
this.currentBeat = beats[0]; this.currentBeat = beats[0];
let rest = beats.slice(1); let rest = beats.slice(1);
@ -769,10 +745,10 @@ ModernUI.prototype.beat = function(beats, index) {
this.beatCenter.appendChild(span); this.beatCenter.appendChild(span);
} }
this.beatCount.textContent = "B=" + this.intToHex(index, 4); this.beatCount.textContent = "B=" + this.intToHex(index, 4);
}; }
// get the width of a single character in the link box for a given classname // get the width of a single character in the link box for a given classname
ModernUI.prototype.textWidth = function(className) { textWidth(className) {
// Could be song or image link, don't care // Could be song or image link, don't care
let el = this.songLink; let el = this.songLink;
let oldContent = el.innerHTML; let oldContent = el.innerHTML;
@ -792,7 +768,7 @@ ModernUI.prototype.textWidth = function(className) {
return size; return size;
} }
ModernUI.prototype.resize = function() { resize() {
this.textSize_normal = this.textWidth(""); this.textSize_normal = this.textWidth("");
this.textSize_small = this.textWidth("small"); this.textSize_small = this.textWidth("small");
this.songLink_size = this.songName.clientWidth; this.songLink_size = this.songName.clientWidth;
@ -802,9 +778,9 @@ ModernUI.prototype.resize = function() {
this.resizeImage(); this.resizeImage();
this.core.visualiser.width = this.controls.offsetWidth; this.core.visualiser.width = this.controls.offsetWidth;
this.core.resizeVisualiser(); this.core.resizeVisualiser();
}; }
ModernUI.prototype.resizeElement = function(el, parentSize) { resizeElement(el, parentSize) {
let chars = el.textContent.length; let chars = el.textContent.length;
if (chars * this.textSize_normal < parentSize) { if (chars * this.textSize_normal < parentSize) {
el.className = ""; el.className = "";
@ -813,38 +789,40 @@ ModernUI.prototype.resizeElement = function(el, parentSize) {
} else { } else {
el.className = "x-small"; el.className = "x-small";
} }
}; }
ModernUI.prototype.resizeSong = function() { resizeSong() {
this.resizeElement(this.songLink, this.songLink_size); this.resizeElement(this.songLink, this.songLink_size);
}; }
ModernUI.prototype.resizeImage = function() { resizeImage() {
this.resizeElement(this.imageLink, this.imageLink_size); this.resizeElement(this.imageLink, this.imageLink_size);
}; }
ModernUI.prototype.newSong = function(song) { newSong(song) {
HuesUI.prototype.newSong.call(this, song); super.newSong(song);
if(!song) { if(!song) {
return; return;
} }
this.resizeSong(); this.resizeSong();
}; }
ModernUI.prototype.newImage = function(image) { newImage(image) {
HuesUI.prototype.newImage.call(this, image); super.newImage(image);
if(!image) { if(!image) {
return; return;
} }
this.resizeImage(); this.resizeImage();
}; }
}
function XmasUI(parent, name) { class XmasUI extends ModernUI {
ModernUI.call(this, parent, name ? name : "XmasUI"); constructor(parent, name) {
super(parent, name ? name : "XmasUI");
this.initSnow(); this.initSnow();
// This will cache our inverted lights images // This will cache our inverted lights images
@ -913,59 +891,56 @@ function XmasUI(parent, name) {
this.beatBar.appendChild(this.visualiserContainer); this.beatBar.appendChild(this.visualiserContainer);
} }
XmasUI.prototype = Object.create(ModernUI.prototype); invert(invert) {
XmasUI.prototype.constructor = XmasUI; super.invert(invert);
XmasUI.prototype.invert = function(invert) {
HuesUI.prototype.invert.call(this, invert);
if(invert) { if(invert) {
this.snowContext.fillStyle = "rgba(0, 0, 0, 0.8)"; this.snowContext.fillStyle = "rgba(0, 0, 0, 0.8)";
} else { } else {
this.snowContext.fillStyle = "rgba(255, 255, 255, 0.8)"; this.snowContext.fillStyle = "rgba(255, 255, 255, 0.8)";
} }
}; }
XmasUI.prototype.connectCore = function(core) { connectCore(core) {
HuesUI.prototype.connectCore.call(this, core); super.connectCore(core);
this.startSnow(); this.startSnow();
}; }
XmasUI.prototype.disconnect = function() { disconnect() {
this.stopSnow(); this.stopSnow();
HuesUI.prototype.disconnect.call(this); super.disconnect();
}; }
XmasUI.prototype.lightOn = function(light) { lightOn(light) {
light.on.className = "hues-x-lighton"; light.on.className = "hues-x-lighton";
light.off.className = "hues-x-lightoff"; light.off.className = "hues-x-lightoff";
}; }
XmasUI.prototype.lightOff = function(light) { lightOff(light) {
light.on.className = "hues-x-lighton off"; light.on.className = "hues-x-lighton off";
light.off.className = "hues-x-lightoff off"; light.off.className = "hues-x-lightoff off";
}; }
XmasUI.prototype.lightFadeOut = function(light) { lightFadeOut(light) {
light.on.className = "hues-x-lighton hues-x-fade off"; light.on.className = "hues-x-lighton hues-x-fade off";
light.off.className = "hues-x-lightoff hues-x-fade off"; light.off.className = "hues-x-lightoff hues-x-fade off";
}; }
XmasUI.prototype.lightRecolour = function(light) { lightRecolour(light) {
let hue = Math.floor(Math.random() * 7) * -56; let hue = Math.floor(Math.random() * 7) * -56;
light.on.style.backgroundPosition = hue + "px 0"; light.on.style.backgroundPosition = hue + "px 0";
light.off.style.backgroundPosition = hue + "px 0"; light.off.style.backgroundPosition = hue + "px 0";
}; }
XmasUI.prototype.randomLight = function(light) { randomLight(light) {
if(Math.random() >= 0.5) { if(Math.random() >= 0.5) {
this.lightOn(light); this.lightOn(light);
} else { } else {
this.lightOff(light); this.lightOff(light);
} }
}; }
XmasUI.prototype.newLight = function(l, parent) { newLight(l, parent) {
let light = document.createElement("div"); let light = document.createElement("div");
light.className = "hues-x-light"; light.className = "hues-x-light";
let bulb = document.createElement("div"); let bulb = document.createElement("div");
@ -981,10 +956,10 @@ XmasUI.prototype.newLight = function(l, parent) {
this.randomLight(light); this.randomLight(light);
this.lightRecolour(light); this.lightRecolour(light);
return light; return light;
}; }
XmasUI.prototype.beat = function(beats, index) { beat(beats, index) {
ModernUI.prototype.beat.call(this, beats, index); super.beat(beats, index);
if(this.currentBeat != ".") { if(this.currentBeat != ".") {
this.lights.forEach(function(light, i, a) { this.lights.forEach(function(light, i, a) {
switch(this.currentBeat) { switch(this.currentBeat) {
@ -1000,9 +975,9 @@ XmasUI.prototype.beat = function(beats, index) {
} }
}, this); }, this);
} }
}; }
XmasUI.prototype.initSnow = function() { initSnow() {
this.snowCanvas = document.createElement("canvas"); this.snowCanvas = document.createElement("canvas");
this.snowContext = this.snowCanvas.getContext("2d"); this.snowContext = this.snowCanvas.getContext("2d");
this.snowCanvas.width = 1280; this.snowCanvas.width = 1280;
@ -1019,11 +994,11 @@ XmasUI.prototype.initSnow = function() {
this.snowflakes = []; this.snowflakes = [];
this.addCoreCallback("frame", this.drawSnow.bind(this)); this.addCoreCallback("frame", this.drawSnow.bind(this));
}; }
// From http://thecodeplayer.com/walkthrough/html5-canvas-snow-effect // From http://thecodeplayer.com/walkthrough/html5-canvas-snow-effect
XmasUI.prototype.startSnow = function() { startSnow() {
this.snowing = true; this.snowing = true;
this.snowCanvas.style.display = "block"; this.snowCanvas.style.display = "block";
let height = this.snowCanvas.height; let height = this.snowCanvas.height;
@ -1039,14 +1014,14 @@ XmasUI.prototype.startSnow = function() {
}); });
} }
this.lastSnow = Date.now() / 1000; this.lastSnow = Date.now() / 1000;
}; }
XmasUI.prototype.stopSnow = function() { stopSnow() {
this.snowing = false; this.snowing = false;
this.snowCanvas.style.display = "none"; this.snowCanvas.style.display = "none";
}; }
XmasUI.prototype.drawSnow = function() { drawSnow() {
let width = this.snowCanvas.width; let width = this.snowCanvas.width;
let height = this.snowCanvas.height; let height = this.snowCanvas.height;
let now = Date.now() / 1000; let now = Date.now() / 1000;
@ -1091,33 +1066,32 @@ XmasUI.prototype.drawSnow = function() {
} }
} }
} }
}; }
XmasUI.prototype.resize = function() { resize() {
ModernUI.prototype.resize.call(this); super.resize();
let ratio = window.innerWidth / window.innerHeight; let ratio = window.innerWidth / window.innerHeight;
// cleared on resize // cleared on resize
let savedFill = this.snowContext.fillStyle; let savedFill = this.snowContext.fillStyle;
this.snowCanvas.width = Math.ceil(720 * ratio); this.snowCanvas.width = Math.ceil(720 * ratio);
this.snowContext.fillStyle = savedFill; this.snowContext.fillStyle = savedFill;
}; }
XmasUI.prototype.newColour = function(colour) {}; newColour(colour) {}
XmasUI.prototype.blurUpdated = function(x, y) {}; blurUpdated(x, y) {}
XmasUI.prototype.updateTime = function(time) {}; updateTime(time) {}
}
function HalloweenUI(parent, name) { class HalloweenUI extends ModernUI {
ModernUI.call(this, parent, name ? name : "HalloweenUI"); constructor(parent, name) {
super(parent, name ? name : "HalloweenUI");
// This will cache our inverted tombstone image // This will cache our inverted tombstone image
this.invert(true); this.invert(true);
} }
HalloweenUI.prototype = Object.create(ModernUI.prototype); initUI() {
HalloweenUI.prototype.constructor = HalloweenUI; super.initUI();
HalloweenUI.prototype.initUI = function() {
ModernUI.prototype.initUI.call(this);
this.controls.className += " hues-h-controls"; this.controls.className += " hues-h-controls";
this.beatBar.className += " hues-h-beatbar"; this.beatBar.className += " hues-h-beatbar";
@ -1183,29 +1157,30 @@ HalloweenUI.prototype.initUI = function() {
this.vignette = document.createElement("div"); this.vignette = document.createElement("div");
this.vignette.className = "hues-h-vignette"; this.vignette.className = "hues-h-vignette";
this.root.appendChild(this.vignette); this.root.appendChild(this.vignette);
}; }
HalloweenUI.prototype.beat = function(beats, index) { beat(beats, index) {
ModernUI.prototype.beat.call(this, beats, index); super.beat(beats, index);
if (this.currentBeat != ".") { if (this.currentBeat != ".") {
let eyes = this.beatCenter.ownerDocument.createElement("div"); let eyes = this.beatCenter.ownerDocument.createElement("div");
eyes.className = "hues-m-beatcenter hues-h-eyes"; eyes.className = "hues-m-beatcenter hues-h-eyes";
this.beatCenter.appendChild(eyes); this.beatCenter.appendChild(eyes);
} }
}; }
HalloweenUI.prototype.connectCore = function(core) { connectCore(core) {
ModernUI.prototype.connectCore.call(this, core); super.connectCore(core);
this.core.preloader.classList.add("hues-h-text"); this.core.preloader.classList.add("hues-h-text");
}; }
HalloweenUI.prototype.disconnect = function() { disconnect() {
this.core.preloader.classList.remove("hues-h-text"); this.core.preloader.classList.remove("hues-h-text");
ModernUI.prototype.disconnect.call(this); super.disconnect();
}; }
}
// Positions and angles for the Xmas lights // Positions and angles for the Xmas lights
let xleft = [ let xleft = [

@ -22,7 +22,8 @@
(function(window, document) { (function(window, document) {
"use strict"; "use strict";
function HuesWindow(root, defaults) { class HuesWindow {
constructor(root, defaults) {
this.eventListeners = { this.eventListeners = {
/* callback windowshown(shown) /* callback windowshown(shown)
* *
@ -75,7 +76,7 @@ function HuesWindow(root, defaults) {
} }
} }
HuesWindow.prototype.addTab = function(tabName, tabContent) { addTab(tabName, tabContent) {
if(!this.hasUI) if(!this.hasUI)
return; return;
@ -92,9 +93,9 @@ HuesWindow.prototype.addTab = function(tabName, tabContent) {
content.appendChild(tabContent); content.appendChild(tabContent);
this.contentContainer.appendChild(content); this.contentContainer.appendChild(content);
this.contents.push(content); this.contents.push(content);
}; }
HuesWindow.prototype.selectTab = function(tabName, dontShowWin) { selectTab(tabName, dontShowWin) {
if(!this.hasUI) if(!this.hasUI)
return; return;
if(!dontShowWin) { if(!dontShowWin) {
@ -111,25 +112,25 @@ HuesWindow.prototype.selectTab = function(tabName, dontShowWin) {
this.tabs[i].classList.remove("tab-label--active"); this.tabs[i].classList.remove("tab-label--active");
} }
} }
}; }
HuesWindow.prototype.hide = function() { hide() {
if(!this.hasUI) if(!this.hasUI)
return; return;
this.window.classList.add("hidden"); this.window.classList.add("hidden");
this.callEventListeners("windowshown", false); this.callEventListeners("windowshown", false);
}; }
HuesWindow.prototype.show = function() { show() {
if(!this.hasUI) if(!this.hasUI)
return; return;
this.window.classList.remove("hidden"); this.window.classList.remove("hidden");
this.callEventListeners("windowshown", true); this.callEventListeners("windowshown", true);
}; }
HuesWindow.prototype.toggle = function() { toggle() {
if(!this.hasUI) if(!this.hasUI)
return; return;
if(this.window.classList.contains("hidden")) { if(this.window.classList.contains("hidden")) {
@ -137,25 +138,25 @@ HuesWindow.prototype.toggle = function() {
} else { } else {
this.hide(); this.hide();
} }
}; }
HuesWindow.prototype.callEventListeners = function(ev) { callEventListeners(ev) {
let args = Array.prototype.slice.call(arguments, 1); let args = Array.prototype.slice.call(arguments, 1);
this.eventListeners[ev].forEach(function(callback) { this.eventListeners[ev].forEach(function(callback) {
callback.apply(null, args); callback.apply(null, args);
}); });
}; }
HuesWindow.prototype.addEventListener = function(ev, callback) { addEventListener(ev, callback) {
ev = ev.toLowerCase(); ev = ev.toLowerCase();
if (typeof(this.eventListeners[ev]) !== "undefined") { if (typeof(this.eventListeners[ev]) !== "undefined") {
this.eventListeners[ev].push(callback); this.eventListeners[ev].push(callback);
} else { } else {
throw Error("Unknown event: " + ev); throw Error("Unknown event: " + ev);
} }
}; }
HuesWindow.prototype.removeEventListener = function(ev, callback) { removeEventListener(ev, callback) {
ev = ev.toLowerCase(); ev = ev.toLowerCase();
if (typeof(this.eventListeners[ev]) !== "undefined") { if (typeof(this.eventListeners[ev]) !== "undefined") {
this.eventListeners[ev] = this.eventListeners[ev].filter(function(a) { this.eventListeners[ev] = this.eventListeners[ev].filter(function(a) {
@ -164,7 +165,8 @@ HuesWindow.prototype.removeEventListener = function(ev, callback) {
} else { } else {
throw Error("Unknown event: " + ev); throw Error("Unknown event: " + ev);
} }
}; }
}
window.HuesWindow = HuesWindow; window.HuesWindow = HuesWindow;

@ -29,12 +29,13 @@ let TAB_IMAGES = 1;
let unique = 0; let unique = 0;
let getAndIncrementUnique = function() { let getAndIncrementUnique = function() {
return unique++; return unique++;
} };
// NOTE: Any packs referenced need CORS enabled or loads fail // NOTE: Any packs referenced need CORS enabled or loads fail
let packsURL = "https://cdn.0x40hu.es/getRespacks.php"; let packsURL = "https://cdn.0x40hu.es/getRespacks.php";
function Resources(core, huesWin) { class Resources {
constructor(core, huesWin) {
this.core = core; this.core = core;
this.hasUI = false; this.hasUI = false;
@ -89,7 +90,7 @@ function Resources(core, huesWin) {
/* Uses HTTP HEAD requests to get the size of all the linked URLs /* Uses HTTP HEAD requests to get the size of all the linked URLs
Returns an Promise.all which will resolve to an array of sizes */ Returns an Promise.all which will resolve to an array of sizes */
Resources.prototype.getSizes = function(urls) { getSizes(urls) {
let promises = []; let promises = [];
urls.forEach(url => { urls.forEach(url => {
@ -118,11 +119,11 @@ Resources.prototype.getSizes = function(urls) {
}); });
return Promise.all(promises); return Promise.all(promises);
}; }
// Array of URLs to load, and a callback for when we're done // Array of URLs to load, and a callback for when we're done
// Preserves order of URLs being loaded // Preserves order of URLs being loaded
Resources.prototype.addAll = function(urls, progressCallback) { addAll(urls, progressCallback) {
if(progressCallback) { if(progressCallback) {
this.progressCallback = progressCallback; this.progressCallback = progressCallback;
this.progressState = Array.apply(null, Array(urls.length)).map(Number.prototype.valueOf,0); this.progressState = Array.apply(null, Array(urls.length)).map(Number.prototype.valueOf,0);
@ -147,18 +148,18 @@ Resources.prototype.addAll = function(urls, progressCallback) {
this.addPack(pack); this.addPack(pack);
}); });
}, Promise.resolve()); }, Promise.resolve());
}; }
Resources.prototype.updateProgress = function(pack) { updateProgress(pack) {
let total = 0; let total = 0;
for(let i = 0; i < this.progressState.length; i++) { for(let i = 0; i < this.progressState.length; i++) {
total += this.progressState[i]; total += this.progressState[i];
} }
total /= this.progressState.length; total /= this.progressState.length;
this.progressCallback(total, pack); this.progressCallback(total, pack);
}; }
Resources.prototype.addPack = function(pack) { addPack(pack) {
console.log("Added", pack.name, "to respacks"); console.log("Added", pack.name, "to respacks");
let id = this.resourcePacks.length; let id = this.resourcePacks.length;
this.resourcePacks.push(pack); this.resourcePacks.push(pack);
@ -175,14 +176,14 @@ Resources.prototype.addPack = function(pack) {
this.selectPack(id); this.selectPack(id);
}.bind(this, id) }.bind(this, id)
); );
}; }
Resources.prototype.addResourcesToArrays = function(pack) { addResourcesToArrays(pack) {
this.allImages = this.allImages.concat(pack.images); this.allImages = this.allImages.concat(pack.images);
this.allSongs = this.allSongs.concat(pack.songs); this.allSongs = this.allSongs.concat(pack.songs);
}; }
Resources.prototype.rebuildArrays = function() { rebuildArrays() {
this.allSongs = []; this.allSongs = [];
this.allImages = []; this.allImages = [];
this.allAnimations = []; this.allAnimations = [];
@ -190,9 +191,9 @@ Resources.prototype.rebuildArrays = function() {
for(let i = 0; i < this.resourcePacks.length; i++) { for(let i = 0; i < this.resourcePacks.length; i++) {
this.addResourcesToArrays(this.resourcePacks[i]); this.addResourcesToArrays(this.resourcePacks[i]);
} }
}; }
Resources.prototype.rebuildEnabled = function() { rebuildEnabled() {
this.enabledSongs = []; this.enabledSongs = [];
this.enabledImages = []; this.enabledImages = [];
@ -238,30 +239,30 @@ Resources.prototype.rebuildEnabled = function() {
} }
} }
this.updateTotals(); this.updateTotals();
}; }
Resources.prototype.removePack = function(pack) { removePack(pack) {
let index = this.resourcePacks.indexOf(pack); let index = this.resourcePacks.indexOf(pack);
if (index != -1) { if (index != -1) {
this.resourcePacks.splice(index, 1); this.resourcePacks.splice(index, 1);
this.rebuildArrays(); this.rebuildArrays();
} }
}; }
Resources.prototype.removeAllPacks = function() { removeAllPacks() {
this.resourcePacks = []; this.resourcePacks = [];
this.rebuildArrays(); this.rebuildArrays();
}; }
Resources.prototype.getSongNames = function() { getSongNames() {
let names = []; let names = [];
for(let i = 0; i < this.allSongs.length; i++) { for(let i = 0; i < this.allSongs.length; i++) {
names.push(this.allSongs[i]); names.push(this.allSongs[i]);
} }
return names; return names;
}; }
Resources.prototype.loadLocal = function() { loadLocal() {
console.log("Loading local zip(s)"); console.log("Loading local zip(s)");
let files = this.fileInput.files; let files = this.fileInput.files;
@ -281,9 +282,9 @@ Resources.prototype.loadLocal = function() {
return p.then(() => { return p.then(() => {
console.log("Local respack parsing complete"); console.log("Local respack parsing complete");
}); });
}; }
Resources.prototype.localProgress = function(progress, respack) { localProgress(progress, respack) {
if(!this.hasUI) {return;} if(!this.hasUI) {return;}
this.packsView.progressStatus.textContent = "Processing..."; this.packsView.progressStatus.textContent = "Processing...";
@ -291,9 +292,9 @@ Resources.prototype.localProgress = function(progress, respack) {
this.packsView.progressCurrent.textContent = respack.filesLoaded; this.packsView.progressCurrent.textContent = respack.filesLoaded;
this.packsView.progressTop.textContent = respack.filesToLoad; this.packsView.progressTop.textContent = respack.filesToLoad;
this.packsView.progressPercent.textContent = Math.round(progress * 100) + "%"; this.packsView.progressPercent.textContent = Math.round(progress * 100) + "%";
}; }
Resources.prototype.localComplete = function(progress) { localComplete(progress) {
let progStat = this.packsView.progressStatus; let progStat = this.packsView.progressStatus;
progStat.textContent = "Complete"; progStat.textContent = "Complete";
window.setTimeout(function() {progStat.textContent = "Idle";}, 2000); window.setTimeout(function() {progStat.textContent = "Idle";}, 2000);
@ -302,9 +303,9 @@ Resources.prototype.localComplete = function(progress) {
this.packsView.progressCurrent.textContent = "0b"; this.packsView.progressCurrent.textContent = "0b";
this.packsView.progressTop.textContent = "0b"; this.packsView.progressTop.textContent = "0b";
this.packsView.progressPercent.textContent = "0%"; this.packsView.progressPercent.textContent = "0%";
}; }
Resources.prototype.initUI = function() { initUI() {
this.root = document.createElement("div"); this.root = document.createElement("div");
this.root.className = "respacks"; this.root.className = "respacks";
@ -529,15 +530,15 @@ Resources.prototype.initUI = function() {
this.listView.appendChild(this.enabledImageList); this.listView.appendChild(this.enabledImageList);
this.hasUI = true; this.hasUI = true;
}; }
Resources.prototype.hideLists = function() { hideLists() {
if(!this.hasUI) {return;} if(!this.hasUI) {return;}
this.enabledSongList.classList.add("hidden"); this.enabledSongList.classList.add("hidden");
this.enabledImageList.classList.add("hidden"); this.enabledImageList.classList.add("hidden");
}; }
Resources.prototype.toggleVisible = function(me, other) { toggleVisible(me, other) {
if(!this.hasUI) {return;} if(!this.hasUI) {return;}
if(me.classList.contains("hidden")) { if(me.classList.contains("hidden")) {
me.classList.remove("hidden"); me.classList.remove("hidden");
@ -545,29 +546,29 @@ Resources.prototype.toggleVisible = function(me, other) {
me.classList.add("hidden"); me.classList.add("hidden");
} }
other.classList.add("hidden"); other.classList.add("hidden");
}; }
Resources.prototype.toggleSongList = function() { toggleSongList() {
this.toggleVisible(this.enabledSongList, this.enabledImageList); this.toggleVisible(this.enabledSongList, this.enabledImageList);
}; }
Resources.prototype.toggleImageList = function() { toggleImageList() {
this.toggleVisible(this.enabledImageList, this.enabledSongList); this.toggleVisible(this.enabledImageList, this.enabledSongList);
}; }
Resources.prototype.updateTotals = function() { updateTotals() {
if(!this.hasUI) {return;} if(!this.hasUI) {return;}
this.packView.totalSongs.textContent = this.packView.totalSongs.textContent =
this.enabledSongs.length + "/" + this.allSongs.length; this.enabledSongs.length + "/" + this.allSongs.length;
this.packView.totalImages.textContent = this.packView.totalImages.textContent =
this.enabledImages.length + "/" + this.allImages.length; this.enabledImages.length + "/" + this.allImages.length;
}; }
Resources.prototype.truncateNum = function(num) { truncateNum(num) {
return Math.round(num * 100) / 100; return Math.round(num * 100) / 100;
}; }
Resources.prototype.selectPack = function(id) { selectPack(id) {
let pack = this.resourcePacks[id]; let pack = this.resourcePacks[id];
this.packView.pack = pack; this.packView.pack = pack;
@ -611,17 +612,17 @@ Resources.prototype.selectPack = function(id) {
this.clickResourceCallback.bind(this, image, false), this.clickResourceCallback.bind(this, image, false),
image.enabled); image.enabled);
} }
}; }
Resources.prototype.selectResourceCallback = function(res) { selectResourceCallback(res) {
let self = this; let self = this;
return function() { return function() {
res.enabled = this.checked; res.enabled = this.checked;
self.rebuildEnabled(); self.rebuildEnabled();
}; };
}; }
Resources.prototype.clickResourceCallback = function(res, isSong) { clickResourceCallback(res, isSong) {
if(!res.enabled) { if(!res.enabled) {
res.enabled = true; res.enabled = true;
this.rebuildEnabled(); this.rebuildEnabled();
@ -634,9 +635,9 @@ Resources.prototype.clickResourceCallback = function(res, isSong) {
this.core.setImage(this.enabledImages.indexOf(res)); this.core.setImage(this.enabledImages.indexOf(res));
this.core.setIsFullAuto(false); this.core.setIsFullAuto(false);
} }
}; }
Resources.prototype.getEnabledTabContents = function() { getEnabledTabContents() {
let pack = this.packView.pack; let pack = this.packView.pack;
if(!pack) { if(!pack) {
return null; return null;
@ -648,9 +649,9 @@ Resources.prototype.getEnabledTabContents = function() {
return {arr: pack.images, return {arr: pack.images,
elName: "image"}; elName: "image"};
} }
}; }
Resources.prototype.enableAll = function() { enableAll() {
let tab = this.getEnabledTabContents(); let tab = this.getEnabledTabContents();
if(!tab) if(!tab)
return; return;
@ -659,9 +660,9 @@ Resources.prototype.enableAll = function() {
document.getElementById(tab.elName + i + "-" + this.unique).checked = true; document.getElementById(tab.elName + i + "-" + this.unique).checked = true;
} }
this.rebuildEnabled(); this.rebuildEnabled();
}; }
Resources.prototype.disableAll = function() { disableAll() {
let tab = this.getEnabledTabContents(); let tab = this.getEnabledTabContents();
if(!tab) if(!tab)
return; return;
@ -670,9 +671,9 @@ Resources.prototype.disableAll = function() {
document.getElementById(tab.elName + i + "-" + this.unique).checked = false; document.getElementById(tab.elName + i + "-" + this.unique).checked = false;
} }
this.rebuildEnabled(); this.rebuildEnabled();
}; }
Resources.prototype.invert = function() { invert() {
let tab = this.getEnabledTabContents(); let tab = this.getEnabledTabContents();
if(!tab) if(!tab)
return; return;
@ -681,9 +682,9 @@ Resources.prototype.invert = function() {
document.getElementById(tab.elName + i + "-" + this.unique).checked = tab.arr[i].enabled; document.getElementById(tab.elName + i + "-" + this.unique).checked = tab.arr[i].enabled;
} }
this.rebuildEnabled(); this.rebuildEnabled();
}; }
Resources.prototype.appendListItem = function(name, value, id, root, oncheck, onclick, checked) { appendListItem(name, value, id, root, oncheck, onclick, checked) {
if(!this.hasUI) {return;} if(!this.hasUI) {return;}
if(checked === undefined) { if(checked === undefined) {
checked = true; checked = true;
@ -706,9 +707,9 @@ Resources.prototype.appendListItem = function(name, value, id, root, oncheck, on
div.appendChild(checkStyler); div.appendChild(checkStyler);
div.appendChild(label); div.appendChild(label);
root.appendChild(div); root.appendChild(div);
}; }
Resources.prototype.loadRemotes = function() { loadRemotes() {
let remoteList = this.packsView.remoteList; let remoteList = this.packsView.remoteList;
while(remoteList.firstElementChild) { while(remoteList.firstElementChild) {
remoteList.removeChild(remoteList.firstElementChild); remoteList.removeChild(remoteList.firstElementChild);
@ -730,9 +731,9 @@ Resources.prototype.loadRemotes = function() {
item.onclick = this.loadRemotes.bind(this); item.onclick = this.loadRemotes.bind(this);
}; };
req.send(); req.send();
}; }
Resources.prototype.populateRemotes = function() { populateRemotes() {
let remoteList = this.packsView.remoteList; let remoteList = this.packsView.remoteList;
while(remoteList.firstElementChild) { while(remoteList.firstElementChild) {
remoteList.removeChild(remoteList.firstElementChild); remoteList.removeChild(remoteList.firstElementChild);
@ -744,9 +745,9 @@ Resources.prototype.populateRemotes = function() {
this.selectRemotePack(index); this.selectRemotePack(index);
}.bind(this, i)); }.bind(this, i));
} }
}; }
Resources.prototype.selectRemotePack = function(id) { selectRemotePack(id) {
let pack = this.remotes[id]; let pack = this.remotes[id];
this.packView.pack = pack; this.packView.pack = pack;
@ -809,9 +810,9 @@ Resources.prototype.selectRemotePack = function(id) {
this.appendSimpleListItem(text + ".", imageList); this.appendSimpleListItem(text + ".", imageList);
this.appendSimpleListItem("Load the respack to show the rest!", imageList); this.appendSimpleListItem("Load the respack to show the rest!", imageList);
} }
}; }
Resources.prototype.loadCurrentRemote = function() { loadCurrentRemote() {
let pack = this.packView.pack; let pack = this.packView.pack;
// Not actually a remote, ignore. How did you press this :< // Not actually a remote, ignore. How did you press this :<
@ -827,9 +828,9 @@ Resources.prototype.loadCurrentRemote = function() {
this.remoteProgress(progress, respack); this.remoteProgress(progress, respack);
} }
).then(this.remoteComplete.bind(this)); ).then(this.remoteComplete.bind(this));
}; }
Resources.prototype.remoteProgress = function(progress, respack) { remoteProgress(progress, respack) {
if(progress < 0.5) { if(progress < 0.5) {
this.packsView.progressStatus.textContent = "Downloading..."; this.packsView.progressStatus.textContent = "Downloading...";
this.packsView.progressCurrent.textContent = Math.round(respack.downloaded / 1024) + "b"; this.packsView.progressCurrent.textContent = Math.round(respack.downloaded / 1024) + "b";
@ -843,9 +844,9 @@ Resources.prototype.remoteProgress = function(progress, respack) {
this.packsView.progressBar.style.width = ((progress - 0.5) * 2 * 100) + "%"; this.packsView.progressBar.style.width = ((progress - 0.5) * 2 * 100) + "%";
this.packsView.progressPercent.textContent = Math.round((progress - 0.5) * 2 * 100) + "%"; this.packsView.progressPercent.textContent = Math.round((progress - 0.5) * 2 * 100) + "%";
} }
}; }
Resources.prototype.remoteComplete = function() { remoteComplete() {
let progStat = this.packsView.progressStatus; let progStat = this.packsView.progressStatus;
progStat.textContent = "Complete"; progStat.textContent = "Complete";
window.setTimeout(function() {progStat.textContent = "Idle";}, 2000); window.setTimeout(function() {progStat.textContent = "Idle";}, 2000);
@ -855,9 +856,9 @@ Resources.prototype.remoteComplete = function() {
this.packsView.progressCurrent.textContent = "0b"; this.packsView.progressCurrent.textContent = "0b";
this.packsView.progressTop.textContent = "0b"; this.packsView.progressTop.textContent = "0b";
this.packsView.progressPercent.textContent = "0%"; this.packsView.progressPercent.textContent = "0%";
}; }
Resources.prototype.appendSimpleListItem = function(value, root, onclick) { appendSimpleListItem(value, root, onclick) {
let div = document.createElement("div"); let div = document.createElement("div");
div.className = "respacks-listitem"; div.className = "respacks-listitem";
let label = document.createElement("span"); let label = document.createElement("span");
@ -867,7 +868,8 @@ Resources.prototype.appendSimpleListItem = function(value, root, onclick) {
div.appendChild(label); div.appendChild(label);
root.appendChild(div); root.appendChild(div);
return label; return label;
}; }
}
window.Resources = Resources; window.Resources = Resources;

@ -22,14 +22,19 @@
(function(window, document) { (function(window, document) {
"use strict"; "use strict";
let debugConsole = false; const debugConsole = false;
function debug() { function debug() {
if(debugConsole) { if(debugConsole) {
console.log.apply(window.console, arguments); console.log.apply(window.console, arguments);
} }
} }
function Respack() { const audioExtensions = new RegExp("\\.(mp3|ogg|wav)$", "i");
const imageExtensions = new RegExp("\\.(png|gif|jpg|jpeg)$", "i");
const animRegex = new RegExp("(.*?)_\\d+$");
class Respack {
constructor() {
this.songs = []; this.songs = [];
this.songQueue = []; this.songQueue = [];
this.images = []; this.images = [];
@ -55,11 +60,7 @@ function Respack() {
this.loadedFromURL = false; this.loadedFromURL = false;
} }
Respack.prototype.audioExtensions = new RegExp("\\.(mp3|ogg|wav)$", "i"); updateProgress(override) {
Respack.prototype.imageExtensions = new RegExp("\\.(png|gif|jpg|jpeg)$", "i");
Respack.prototype.animRegex = new RegExp("(.*?)_\\d+$");
Respack.prototype.updateProgress = function(override) {
if(this.progressCallback) { if(this.progressCallback) {
let percent = this.filesLoaded / this.filesToLoad; let percent = this.filesLoaded / this.filesToLoad;
if(this.loadedFromURL) { if(this.loadedFromURL) {
@ -67,9 +68,9 @@ Respack.prototype.updateProgress = function(override) {
} }
this.progressCallback(typeof override === "number" ? override : percent, this); this.progressCallback(typeof override === "number" ? override : percent, this);
} }
}; }
Respack.prototype.loadFromURL = function(url, progress) { loadFromURL(url, progress) {
this.loadedFromURL = true; this.loadedFromURL = true;
if(progress) { if(progress) {
this.progressCallback = progress; this.progressCallback = progress;
@ -79,9 +80,9 @@ Respack.prototype.loadFromURL = function(url, progress) {
.then(response => { .then(response => {
return this.loadFromBlob(response); return this.loadFromBlob(response);
}); });
}; }
Respack.prototype.getBlob = function(url, progress) { getBlob(url, progress) {
if(progress) { if(progress) {
this.progressCallback = progress; this.progressCallback = progress;
} }
@ -118,9 +119,9 @@ Respack.prototype.getBlob = function(url, progress) {
throw error; throw error;
} }
}); });
}; }
Respack.prototype.loadFromBlob = function(blob, progress) { loadFromBlob(blob, progress) {
if(progress) { if(progress) {
this.progressCallback = progress; this.progressCallback = progress;
} }
@ -142,9 +143,9 @@ Respack.prototype.loadFromBlob = function(blob, progress) {
}).then(() => { }).then(() => {
return this; return this;
}); });
}; }
Respack.prototype.parseZip = function(zip) { parseZip(zip) {
let entries = zip.entries; let entries = zip.entries;
this.totalFiles = 0; this.totalFiles = 0;
@ -171,24 +172,23 @@ Respack.prototype.parseZip = function(zip) {
console.log("Loaded", this.name, "successfully with", this.songs.length, console.log("Loaded", this.name, "successfully with", this.songs.length,
"songs and", this.images.length, "images."); "songs and", this.images.length, "images.");
}); });
}; }
Respack.prototype.parseFile = function(file) { parseFile(file) {
let name = file.name; let name = file.name;
if (name.match(this.audioExtensions)) { if (name.match(audioExtensions)) {
this.songQueue.push(this.parseSong(file)); this.songQueue.push(this.parseSong(file));
this.filesToLoad++; this.filesToLoad++;
} else if (name.match(this.imageExtensions)) { } else if (name.match(imageExtensions)) {
this.imageQueue.push(this.parseImage(file)); this.imageQueue.push(this.parseImage(file));
this.filesToLoad++; this.filesToLoad++;
} } else if(name.toLowerCase().endsWith(".xml")){
else if(name.toLowerCase().endsWith(".xml")){
this._xmlQueue.push(this.loadXML(file)); this._xmlQueue.push(this.loadXML(file));
} }
}; }
Respack.prototype.parseSong = function(file) { parseSong(file) {
let name = file.name.replace(this.audioExtensions, ""); let name = file.name.replace(audioExtensions, "");
debug("parsing song: " + name); debug("parsing song: " + name);
if (this.containsSong(name)) { if (this.containsSong(name)) {
let oldSong = this.getSong(name); let oldSong = this.getSong(name);
@ -238,20 +238,20 @@ Respack.prototype.parseSong = function(file) {
this.updateProgress(); this.updateProgress();
}); });
} }
}; }
Respack.prototype.parseSongQueue = function() { parseSongQueue() {
return this.songQueue.reduce((sequence, songPromise) => { return this.songQueue.reduce((sequence, songPromise) => {
return sequence.then(() => { return sequence.then(() => {
// Maintain order // Maintain order
return songPromise; return songPromise;
}); });
}, Promise.resolve()); }, Promise.resolve());
}; }
Respack.prototype.parseImage = function(file) { parseImage(file) {
let match; let match;
let name = file.name.replace(this.imageExtensions, ""); let name = file.name.replace(imageExtensions, "");
let img; let img;
// Animation // Animation
@ -289,9 +289,9 @@ Respack.prototype.parseImage = function(file) {
} }
return this.loadImage(file, img); return this.loadImage(file, img);
}; }
Respack.prototype.loadImage = function(imgFile, imageObj) { loadImage(imgFile, imageObj) {
let extension = imgFile.name.split('.').pop().toLowerCase(); let extension = imgFile.name.split('.').pop().toLowerCase();
let mime = ""; let mime = "";
switch(extension) { switch(extension) {
@ -315,9 +315,9 @@ Respack.prototype.loadImage = function(imgFile, imageObj) {
this.updateProgress(); this.updateProgress();
return {bitmap: bitmap, img: imageObj}; return {bitmap: bitmap, img: imageObj};
}); });
}; }
Respack.prototype.parseImageQueue = function() { parseImageQueue() {
return this.imageQueue.reduce((sequence, imagePromise) => { return this.imageQueue.reduce((sequence, imagePromise) => {
return sequence.then(() => { return sequence.then(() => {
// Maintain order // Maintain order
@ -335,9 +335,9 @@ Respack.prototype.parseImageQueue = function() {
} }
}); });
}, Promise.resolve()); }, Promise.resolve());
}; }
Respack.prototype.loadXML = function(file) { loadXML(file) {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
file.getText(text => { file.getText(text => {
//XML parser will complain about a bare '&', but some respacks use &amp //XML parser will complain about a bare '&', but some respacks use &amp
@ -348,9 +348,9 @@ Respack.prototype.loadXML = function(file) {
resolve(dom); resolve(dom);
}); });
}); });
}; }
Respack.prototype.parseXML = function() { parseXML() {
for(let i = 0; i < this._xmlQueue.length; i++) { for(let i = 0; i < this._xmlQueue.length; i++) {
this._xmlQueue[i] = this._xmlQueue[i].then(dom => { this._xmlQueue[i] = this._xmlQueue[i].then(dom => {
switch(dom.documentElement.nodeName) { switch(dom.documentElement.nodeName) {
@ -372,15 +372,9 @@ Respack.prototype.parseXML = function() {
}); });
} }
return Promise.all(this._xmlQueue); return Promise.all(this._xmlQueue);
}; }
// Save some chars
Element.prototype.getTag = function(tag, def) {
let t = this.getElementsByTagName(tag)[0];
return t ? t.textContent : (def ? def : null);
};
Respack.prototype.parseSongFile = function(dom) { parseSongFile(dom) {
debug(" - Parsing songFile"); debug(" - Parsing songFile");
let newSongs = []; let newSongs = [];
@ -436,9 +430,9 @@ Respack.prototype.parseSongFile = function(dom) {
} }
} }
this.songs = newSongs; this.songs = newSongs;
}; }
Respack.prototype.parseInfoFile = function(dom) { parseInfoFile(dom) {
debug(" - Parsing infoFile"); debug(" - Parsing infoFile");
let info = dom.documentElement; let info = dom.documentElement;
@ -448,9 +442,9 @@ Respack.prototype.parseInfoFile = function(dom) {
this.author = info.getTag("author", this.author); this.author = info.getTag("author", this.author);
this.description = info.getTag("description", this.description); this.description = info.getTag("description", this.description);
this.link = info.getTag("link", this.link); this.link = info.getTag("link", this.link);
}; }
Respack.prototype.parseImageFile = function(dom) { parseImageFile(dom) {
debug(" - Parsing imagefile"); debug(" - Parsing imagefile");
let newImages = []; let newImages = [];
@ -501,34 +495,41 @@ Respack.prototype.parseImageFile = function(dom) {
return a.name.localeCompare(b.name); return a.name.localeCompare(b.name);
}); });
this.images = newImages; this.images = newImages;
}; }
Respack.prototype.containsSong = function(name) { containsSong(name) {
return this.getSong(name) !== null; return this.getSong(name) !== null;
}; }
Respack.prototype.containsImage = function(name) { containsImage(name) {
return this.getImage(name) !== null; return this.getImage(name) !== null;
}; }
Respack.prototype.getSong = function(name) { getSong(name) {
for(let i = 0; i < this.songs.length; i++) { for(let i = 0; i < this.songs.length; i++) {
if (name == this.songs[i].name) { if (name == this.songs[i].name) {
return this.songs[i]; return this.songs[i];
} }
} }
return null; return null;
}; }
Respack.prototype.getImage = function(name) { getImage(name) {
for(let i = 0; i < this.images.length; i++) { for(let i = 0; i < this.images.length; i++) {
if (name == this.images[i].name) { if (name == this.images[i].name) {
return this.images[i]; return this.images[i];
} }
} }
return null; return null;
}; }
}
window.Respack = Respack; window.Respack = Respack;
// Save some chars
Element.prototype.getTag = function(tag, def) {
let t = this.getElementsByTagName(tag)[0];
return t ? t.textContent : (def ? def : null);
};
})(window, document); })(window, document);

@ -22,7 +22,8 @@
(function(window, document) { (function(window, document) {
"use strict"; "use strict";
function SoundManager(core) { class SoundManager {
constructor(core) {
this.core = core; this.core = core;
this.playing = false; this.playing = false;
this.playbackRate = 1; this.playbackRate = 1;
@ -62,7 +63,7 @@ function SoundManager(core) {
this.maxBinLin = 0; this.maxBinLin = 0;
} }
SoundManager.prototype.init = function() { init() {
if(!this.initPromise) { if(!this.initPromise) {
this.initPromise = new Promise((resolve, reject) => { this.initPromise = new Promise((resolve, reject) => {
// Check Web Audio API Support // Check Web Audio API Support
@ -118,9 +119,9 @@ SoundManager.prototype.init = function() {
}); });
} }
return this.initPromise; return this.initPromise;
}; }
SoundManager.prototype.unlock = function() { unlock() {
if(this.lockedPromise) { if(this.lockedPromise) {
return this.lockedPromise; return this.lockedPromise;
} }
@ -148,9 +149,9 @@ SoundManager.prototype.unlock = function() {
window.addEventListener('click', unlocker, false); window.addEventListener('click', unlocker, false);
}); });
return this.lockedPromise; return this.lockedPromise;
}; }
SoundManager.prototype.playSong = function(song, playBuild, forcePlay) { playSong(song, playBuild, forcePlay) {
let p = Promise.resolve(); let p = Promise.resolve();
// Editor forces play on audio updates // Editor forces play on audio updates
if(this.song == song && !forcePlay) { if(this.song == song && !forcePlay) {
@ -197,9 +198,9 @@ SoundManager.prototype.playSong = function(song, playBuild, forcePlay) {
this.playing = true; this.playing = true;
}); });
return p; return p;
}; }
SoundManager.prototype.stop = function(dontDeleteBuffers) { stop(dontDeleteBuffers) {
if (this.playing) { if (this.playing) {
if(this.buildSource) { if(this.buildSource) {
this.buildSource.stop(0); this.buildSource.stop(0);
@ -219,18 +220,18 @@ SoundManager.prototype.stop = function(dontDeleteBuffers) {
this.playing = false; this.playing = false;
this.startTime = 0; this.startTime = 0;
} }
}; }
SoundManager.prototype.setRate = function(rate) { setRate(rate) {
// Double speed is more than enough. Famous last words? // Double speed is more than enough. Famous last words?
rate = Math.max(Math.min(rate, 2), 0.25); rate = Math.max(Math.min(rate, 2), 0.25);
let time = this.clampedTime(); let time = this.clampedTime();
this.playbackRate = rate; this.playbackRate = rate;
this.seek(time); this.seek(time);
}; }
SoundManager.prototype.seek = function(time, noPlayingUpdate) { seek(time, noPlayingUpdate) {
if(!this.song) { if(!this.song) {
return; return;
} }
@ -269,26 +270,26 @@ SoundManager.prototype.seek = function(time, noPlayingUpdate) {
} }
this.initVisualiser(); this.initVisualiser();
this.core.recalcBeatIndex(); this.core.recalcBeatIndex();
}; }
// In seconds, relative to the loop start // In seconds, relative to the loop start
SoundManager.prototype.currentTime = function() { currentTime() {
if(!this.playing) { if(!this.playing) {
return 0; return 0;
} }
return (this.context.currentTime - this.startTime) * this.playbackRate; return (this.context.currentTime - this.startTime) * this.playbackRate;
}; }
SoundManager.prototype.clampedTime = function() { clampedTime() {
let time = this.currentTime(); let time = this.currentTime();
if(time > 0) { if(time > 0) {
time %= this.loopLength; time %= this.loopLength;
} }
return time; return time;
}; }
SoundManager.prototype.loadSong = function(song) { loadSong(song) {
if(song._loadPromise) { if(song._loadPromise) {
/* Caused when moving back/forwards rapidly. /* Caused when moving back/forwards rapidly.
The sound is still loading. We reject this promise, and the already The sound is still loading. We reject this promise, and the already
@ -315,9 +316,9 @@ SoundManager.prototype.loadSong = function(song) {
return buffers; return buffers;
}); });
return song._loadPromise; return song._loadPromise;
}; }
SoundManager.prototype.loadBuffer = function(song, soundName) { loadBuffer(song, soundName) {
let buffer = song[soundName]; let buffer = song[soundName];
// Is this an ogg file? // Is this an ogg file?
@ -365,10 +366,10 @@ SoundManager.prototype.loadBuffer = function(song, soundName) {
}); });
} }
}; }
// Converts continuous PCM array to Web Audio API friendly format // Converts continuous PCM array to Web Audio API friendly format
SoundManager.prototype.audioBufFromRaw = function(raw) { audioBufFromRaw(raw) {
let buffer = raw.array; let buffer = raw.array;
let channels = raw.channels; let channels = raw.channels;
let samples = buffer.length/channels; let samples = buffer.length/channels;
@ -384,13 +385,13 @@ SoundManager.prototype.audioBufFromRaw = function(raw) {
} }
} }
return audioBuf; return audioBuf;
}; }
SoundManager.prototype.createWorker = function() { createWorker() {
return new Worker(this.core.settings.defaults.workersPath + 'audio-worker.js'); return new Worker(this.core.settings.defaults.workersPath + 'audio-worker.js');
}; }
SoundManager.prototype.initVisualiser = function(bars) { initVisualiser(bars) {
// When restarting the visualiser // When restarting the visualiser
if(!bars) { if(!bars) {
bars = this.vTotalBars; bars = this.vTotalBars;
@ -414,9 +415,9 @@ SoundManager.prototype.initVisualiser = function(bars) {
this.maxBinLin = 0; this.maxBinLin = 0;
this.attachVisualiser(); this.attachVisualiser();
}; }
SoundManager.prototype.attachVisualiser = function() { attachVisualiser() {
if(!this.playing || this.vReady) { if(!this.playing || this.vReady) {
return; return;
} }
@ -470,17 +471,17 @@ SoundManager.prototype.attachVisualiser = function() {
this.binCutoffs.push(binCutoff); this.binCutoffs.push(binCutoff);
} }
this.vReady = true; this.vReady = true;
}; }
SoundManager.prototype.sumArray = function(array, low, high) { sumArray(array, low, high) {
let total = 0; let total = 0;
for(let i = low; i <= high; i++) { for(let i = low; i <= high; i++) {
total += array[i]; total += array[i];
} }
return total/(high-low+1); return total/(high-low+1);
}; }
SoundManager.prototype.getVisualiserData = function() { getVisualiserData() {
if(!this.vReady) { if(!this.vReady) {
return null; return null;
} }
@ -501,9 +502,9 @@ SoundManager.prototype.getVisualiserData = function() {
} }
} }
return this.logArrays; return this.logArrays;
}; }
SoundManager.prototype.setMute = function(mute) { setMute(mute) {
if(!this.mute && mute) { // muting if(!this.mute && mute) { // muting
this.lastVol = this.gainNode.gain.value; this.lastVol = this.gainNode.gain.value;
} }
@ -515,38 +516,39 @@ SoundManager.prototype.setMute = function(mute) {
this.core.userInterface.updateVolume(this.gainNode.gain.value); this.core.userInterface.updateVolume(this.gainNode.gain.value);
this.mute = mute; this.mute = mute;
return mute; return mute;
}; }
SoundManager.prototype.toggleMute = function() { toggleMute() {
return this.setMute(!this.mute); return this.setMute(!this.mute);
}; }
SoundManager.prototype.decreaseVolume = function() { decreaseVolume() {
this.setMute(false); this.setMute(false);
let val = Math.max(this.gainNode.gain.value - 0.1, 0); let val = Math.max(this.gainNode.gain.value - 0.1, 0);
this.setVolume(val); this.setVolume(val);
}; }
SoundManager.prototype.increaseVolume = function() { increaseVolume() {
this.setMute(false); this.setMute(false);
let val = Math.min(this.gainNode.gain.value + 0.1, 1); let val = Math.min(this.gainNode.gain.value + 0.1, 1);
this.setVolume(val); this.setVolume(val);
}; }
SoundManager.prototype.setVolume = function(vol) { setVolume(vol) {
this.gainNode.gain.value = vol; this.gainNode.gain.value = vol;
this.lastVol = vol; this.lastVol = vol;
this.core.userInterface.updateVolume(vol); this.core.userInterface.updateVolume(vol);
}; }
SoundManager.prototype.fadeOut = function(callback) { fadeOut(callback) {
if(!this.mute) { if(!this.mute) {
// Firefox hackery // Firefox hackery
this.gainNode.gain.setValueAtTime(this.lastVol, this.context.currentTime); this.gainNode.gain.setValueAtTime(this.lastVol, this.context.currentTime);
this.gainNode.gain.exponentialRampToValueAtTime(0.01, this.context.currentTime + 2); this.gainNode.gain.exponentialRampToValueAtTime(0.01, this.context.currentTime + 2);
} }
setTimeout(callback, 2000); setTimeout(callback, 2000);
}; }
}
let miniOggRaw = let miniOggRaw =
"T2dnUwACAAAAAAAAAADFYgAAAAAAAMLKRdwBHgF2b3JiaXMAAAAAAUSsAAAA" + "T2dnUwACAAAAAAAAAADFYgAAAAAAAMLKRdwBHgF2b3JiaXMAAAAAAUSsAAAA" +

Loading…
Cancel
Save