Skip to content

Instantly share code, notes, and snippets.

@spacejack
Created December 19, 2016 15:37
Show Gist options
  • Save spacejack/8a0907911556a6d71ebb1609b3dc63cd to your computer and use it in GitHub Desktop.
Save spacejack/8a0907911556a6d71ebb1609b3dc63cd to your computer and use it in GitHub Desktop.
// Loader that provides a dictionary of named assets
import xhr from './xhr'
export interface Assets {
images: {[id: string]: HTMLImageElement}
geometries: {[id: string]: THREE.Geometry}
text: {[id: string]: string}
textures: {[id: string]: THREE.Texture}
sounds: {[id: string]: Howler.Howl}
}
export interface AssetDescription {
name: string
url: string
}
export interface AssetList {
geometries?: AssetDescription[]
images?: AssetDescription[]
text?: AssetDescription[]
textures?: AssetDescription[]
sounds?: AssetDescription[]
}
interface LoaderOptions {
success?: (a: Assets) => any,
progress?: (p: number) => any,
error?: (e: string) => any,
done?: (ok: boolean) => any
}
/**
* Create a Loader instance
*/
export default function Loader() {
let isLoading = false
let totalToLoad = 0
let numLoaded = 0
let numFailed = 0
let success_cb: ((a: Assets) => any) | undefined
let progress_cb: ((p: number) => any) | undefined
let error_cb: ((e: string) => any) | undefined
let done_cb: ((ok: boolean) => any) | undefined
let assets: Assets = {
images: {}, geometries: {}, text: {}, textures: {}, sounds: {}
}
/**
* Start loading a list of assets
*/
function load(assetList: AssetList, opts: LoaderOptions = {}) {
success_cb = opts.success
progress_cb = opts.progress
error_cb = opts.error
done_cb = opts.done
totalToLoad = 0
numLoaded = 0
numFailed = 0
isLoading = true
if (assetList.text) {
totalToLoad += assetList.text.length
for (let i = 0; i < assetList.text.length; ++i)
loadText(assetList.text[i])
}
if (assetList.geometries) {
totalToLoad += assetList.geometries.length
for (let i = 0; i < assetList.geometries.length; ++i)
loadGeometry(assetList.geometries[i])
}
if (assetList.images) {
totalToLoad += assetList.images.length
for (let i = 0; i < assetList.images.length; ++i)
loadImage(assetList.images[i])
}
if (assetList.textures) {
totalToLoad += assetList.textures.length
for (let i = 0; i < assetList.textures.length; ++i)
loadTexture(assetList.textures[i])
}
if (assetList.sounds) {
totalToLoad += assetList.sounds.length
for (let i = 0; i < assetList.sounds.length; ++i)
loadSound(assetList.sounds[i])
}
}
function loadText (ad: AssetDescription) {
const req = new XMLHttpRequest()
req.overrideMimeType('*/*')
req.onreadystatechange = function() {
if (req.readyState === 4) {
if (req.status === 200) {
assets.text[ad.name] = req.responseText
doProgress()
} else {
doError("Error " + req.status + " loading " + ad.url)
}
}
}
req.open('GET', ad.url)
req.send()
}
function loadImage (ad: AssetDescription) {
const img = new Image()
assets.images[ad.name] = img
img.onload = doProgress
img.onerror = doError
img.src = ad.url
}
function loadTexture (ad: AssetDescription) {
assets.textures[ad.name] = new THREE.TextureLoader().load(ad.url, doProgress)
}
function loadGeometry (ad: AssetDescription) {
xhr(ad.url, {
success: jsrc => {
const data = JSON.parse(jsrc)
const jloader = new THREE.JSONLoader()
const result = jloader.parse(data)
assets.geometries[ad.name] = result.geometry
doProgress()
},
error: e => {
doError("Failed to load model: '" + ad.url + "'")
}
})
}
function loadSound (ad: AssetDescription) {
assets.sounds[ad.name] = new Howl({
src: [ad.url + '.ogg', ad.url + '.mp3'],
onload: () => {
doProgress()
},
onloaderror: () => {
doError("Failed to load sound: '" + ad.url + "'")
}
})
}
function doProgress() {
numLoaded += 1
progress_cb && progress_cb(numLoaded / totalToLoad)
tryDone()
}
function doError (e: any) {
error_cb && error_cb(e)
numFailed += 1
tryDone()
}
function tryDone() {
if (!isLoading)
return true
if (numLoaded + numFailed >= totalToLoad) {
const ok = !numFailed
ok && success_cb && success_cb(assets)
done_cb && done_cb(ok)
isLoading = false
}
return !isLoading
}
/**
* Public interface
*/
return {
load: load,
getAssets: () => assets
}
} // end Loader
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment