/* Copyright (c) 2015 William Toohey * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ // NOTE: Any packs referenced need CORS enabled or loads fail var packsURL = "http://cdn.0x40hu.es/getRespacks.php"; function Resources(core) { this.core = core; this.resourcePacks = []; this.allSongs = []; this.allImages = []; this.enabledSongs = []; this.enabledImages = []; this.toLoad = 0; this.progressState = []; this.rToLoad = [] this.loadFinishCallback = null; this.progressCallback = null; this.root = null; // For songs/images this.listView = null; this.enabledSongList = null; this.enabledImageList = null; this.packView = { pack: null, name: null, creator: null, size: null, desc: null, songCount: null, imageCount: null, songList: null, imageList: null, packButtons: null, totalSongs: null, totalImages: null }; this.packsView = { respackList: null, remoteList: null, loadRemote: null, progressBar: null, progressStatus: null, progressCurrent: null, progressTop: null, progressPercent: null }; this.remotes = null; this.fileInput = null; this.fileParseQueue = []; this.currentlyParsing = false; this.initUI(); } // Array of URLs to load, and a callback for when we're done // Preserves order of URLs being loaded Resources.prototype.addAll = function(urls, callback, progressCallback) { var that = this; this.toLoad += urls.length; if(progressCallback) { this.progressCallback = progressCallback; this.progressState = Array.apply(null, Array(urls.length)).map(Number.prototype.valueOf,0); } if(callback) { this.loadFinishCallback = callback; } for(var i = 0; i < urls.length; i++) { var r = new Respack(); this.rToLoad.push(r); r.loadFromURL(urls[i], function() { that.toLoad--; if(that.toLoad <= 0) { // could use a while() and shift(), but it'd be slower for(var i = 0; i < that.rToLoad.length; i++) { that.addPack(that.rToLoad[i]); } that.rToLoad = []; if(that.loadFinishCallback) { that.loadFinishCallback(); that.loadFinishCallback = null; } that.progressCallback = null; } }, this.createProgCallback(i)); } } Resources.prototype.createProgCallback = function(i) { var that = this; return function(progress) { that.progressState[i] = progress; that.updateProgress(); } } Resources.prototype.updateProgress = function() { var total = 0; for(var i = 0; i < this.progressState.length; i++) { total += this.progressState[i]; } total /= this.progressState.length; this.progressCallback(total); } Resources.prototype.addPack = function(pack) { console.log("Added", pack.name, "to respacks"); var that = this; var id = this.resourcePacks.length; this.resourcePacks.push(pack); this.addResourcesToArrays(pack); this.rebuildEnabled(); this.updateTotals(); this.appendListItem("respacks", pack.name, "res" + id, this.packsView.respackList, function() { pack.enabled = this.checked; that.rebuildEnabled(); }, this.selectPackCallback(id) ); } Resources.prototype.addResourcesToArrays = function(pack) { this.allImages = this.allImages.concat(pack.images); this.allSongs = this.allSongs.concat(pack.songs); } Resources.prototype.rebuildArrays = function() { this.allSongs = []; this.allImages = []; this.allAnimations = []; for(var i = 0; i < this.resourcePacks.length; i++) { this.addResourcesToArrays(this.resourcePacks[i]); } } Resources.prototype.rebuildEnabled = function() { this.enabledSongs = []; this.enabledImages = []; for(var i = 0; i < this.resourcePacks.length; i++) { var pack = this.resourcePacks[i]; if (pack["enabled"] != true) { continue; } for(var j = 0; j < pack.songs.length; j++) { var song = pack.songs[j]; if (song.enabled && this.enabledSongs.indexOf(song) == -1) { this.enabledSongs.push(song); } } for(var j = 0; j < pack.images.length; j++) { var image = pack.images[j]; if (image.enabled && this.enabledImages.indexOf(image) == -1) { this.enabledImages.push(image); } } } var songList = this.enabledSongList; while(songList.firstElementChild) { songList.removeChild(songList.firstElementChild) } var imageList = this.enabledImageList; while(imageList.firstElementChild) { imageList.removeChild(imageList.firstElementChild) } for(var i = 0; i < this.enabledSongs.length; i++) { var song = this.enabledSongs[i]; this.appendSimpleListItem(song.title, songList, this.playSongCallback(i)); } for(var i = 0; i < this.enabledImages.length; i++) { var image = this.enabledImages[i]; this.appendSimpleListItem(image.name, imageList, this.selectImageCallback(i)); } this.updateTotals(); } Resources.prototype.playSongCallback = function(index) { var that = this; return function() { that.core.setSong(index); }; } Resources.prototype.selectImageCallback = function(index) { var that = this; return function() { that.core.setImage(index); }; } Resources.prototype.removePack = function(pack) { var index = this.resourcePacks.indexOf(pack); if (index != -1) { this.resourcePacks.splice(index, 1); this.rebuildArrays(); } } Resources.prototype.removeAllPacks = function() { this.resourcePacks = []; this.rebuildArrays(); } Resources.prototype.getSongNames = function() { var names = [] for(var i = 0; i < this.allSongs.length; i++) { names.push(this.allSongs[i]); } return names; } Resources.prototype.loadLocal = function() { console.log("Loading local zip(s)"); var files = this.fileInput.files; for(var i = 0; i < files.length; i++) { this.fileParseQueue.push(files[i]); } this.parseLocalQueue(); } Resources.prototype.parseLocalQueue = function(recursing) { var that = this; // avoid race conditions if(this.currentlyParsing && !recursing) { return; } this.currentlyParsing = true; if(this.fileParseQueue.length) { var r = new Respack(); r.loadBlob(this.fileParseQueue.shift(), function() { that.addPack(r); that.localComplete(); that.parseLocalQueue(true); }, function(progress, respack) {that.localProgress(progress, respack);}, function() {that.parseLocalQueue(true);}); } else { console.log("Local respack parsing complete"); this.currentlyParsing = false; } } Resources.prototype.localProgress = function(progress, respack) { this.packsView.progressStatus.textContent = "Processing..."; this.packsView.progressBar.style.width = (progress * 100) + "%"; this.packsView.progressCurrent.textContent = respack.filesLoaded; this.packsView.progressTop.textContent = respack.filesToLoad; this.packsView.progressPercent.textContent = Math.round(progress * 100) + "%"; } Resources.prototype.localComplete = function(progress) { var progStat = this.packsView.progressStatus; progStat.textContent = "Complete"; window.setTimeout(function() {progStat.textContent = "Idle";}, 2000); this.packsView.progressBar.style.width = "100%"; this.packsView.progressCurrent.textContent = "0b"; this.packsView.progressTop.textContent = "0b"; this.packsView.progressPercent.textContent = "0%"; } Resources.prototype.initUI = function() { this.root = document.getElementById("huesResources"); var that = this; var packsContainer = document.createElement("div"); packsContainer.className = "res-packscontainer"; var packHeader = document.createElement("div"); packHeader.textContent = "Current respacks"; packHeader.className = "res-header"; packHeader.id = "res-curheader"; var packList = document.createElement("div"); packList.className = "res-list"; packList.id = "res-packlist"; this.packsView.respackList = packList; var remoteHeader = document.createElement("div"); remoteHeader.textContent = "Remote respacks"; remoteHeader.className = "res-header"; var remoteList = document.createElement("div"); remoteList.className = "res-list"; remoteList.id = "res-remotelist"; this.appendSimpleListItem("Click to load the list", remoteList, function() {that.loadRemotes();}); this.packsView.remoteList = remoteList; var buttons = document.createElement("div"); buttons.className = "res-buttons"; var loadRemote = document.createElement("div"); loadRemote.className = "res-button hidden"; loadRemote.textContent = "LOAD REMOTE"; loadRemote.onclick = function() {that.loadCurrentRemote();}; var loadLocal = document.createElement("div"); loadLocal.className = "res-button"; loadLocal.textContent = "LOAD ZIPS"; loadLocal.onclick = function() {that.fileInput.click();}; buttons.appendChild(loadLocal); buttons.appendChild(loadRemote); this.packsView.loadRemote = loadRemote; this.fileInput = document.createElement("input"); this.fileInput.type ="file"; this.fileInput.accept="application/zip"; this.fileInput.multiple = true; this.fileInput.onchange = function() {that.loadLocal();}; var progressContainer = document.createElement("div"); progressContainer.id = "res-progress-container"; var progressBar = document.createElement("div"); progressBar.id = "res-progress-bar"; var progressFilled = document.createElement("span"); progressFilled.id = "res-progress-filled"; progressBar.appendChild(progressFilled); var progressStatus = document.createElement("div"); progressStatus.textContent = "Idle"; var progressTexts = document.createElement("div"); progressTexts.id = "res-progress-texts"; var progressCurrent = document.createElement("div"); progressCurrent.id = "res-progress-current"; progressCurrent.textContent = "0b"; var progressTop = document.createElement("div"); progressTop.id = "res-progress-top"; progressTop.textContent = "0b"; var progressPercent = document.createElement("div"); progressPercent.id = "res-progress-percent"; progressPercent.textContent = "0%"; progressTexts.appendChild(progressCurrent); progressTexts.appendChild(progressTop); progressTexts.appendChild(progressPercent); this.packsView.progressBar = progressFilled; this.packsView.progressStatus = progressStatus; this.packsView.progressCurrent = progressCurrent; this.packsView.progressTop = progressTop; this.packsView.progressPercent = progressPercent; progressContainer.appendChild(progressStatus); progressContainer.appendChild(progressBar); progressContainer.appendChild(progressTexts); packsContainer.appendChild(packHeader); packsContainer.appendChild(packList); packsContainer.appendChild(remoteHeader); packsContainer.appendChild(remoteList); packsContainer.appendChild(buttons); packsContainer.appendChild(progressContainer); var indivView = document.createElement("div"); indivView.className = "res-packcontainer"; var packName = document.createElement("div"); packName.textContent = "