Skip to content

Instantly share code, notes, and snippets.

@CodyJasonBennett
Last active May 25, 2022 23:01
Show Gist options
  • Save CodyJasonBennett/e5cce5854abb2324459601da5f14bb44 to your computer and use it in GitHub Desktop.
Save CodyJasonBennett/e5cce5854abb2324459601da5f14bb44 to your computer and use it in GitHub Desktop.
import * as THREE from 'three'
import { Asset } from 'expo-asset'
/**
* Generates an asset based on input type.
*/
const getAsset = (input) => {
if (input instanceof Asset) return input
switch (typeof input) {
case 'string':
return Asset.fromURI(input)
case 'number':
return Asset.fromModule(input)
default:
throw 'Invalid asset! Must be a URI or module.'
}
}
// Don't pre-process urls, let expo-asset generate an absolute URL
const extractUrlBase = THREE.LoaderUtils.extractUrlBase.bind(THREE.LoaderUtils)
THREE.LoaderUtils.extractUrlBase = (url) => (typeof url === 'string' ? extractUrlBase(url) : './')
// There's no Image in native, so create a data texture instead
THREE.TextureLoader.prototype.load = function load(url, onLoad, onProgress, onError) {
const texture = new THREE.Texture()
texture.isDataTexture = true
getAsset(url)
.downloadAsync()
.then((asset) => {
texture.image = {
data: asset,
width: asset.width,
height: asset.height,
}
texture.flipY = true
texture.unpackAlignment = 1
texture.needsUpdate = true
onLoad?.(texture)
})
.catch(onError)
return texture
}
// Fetches assets via XMLHttpRequest
THREE.FileLoader.prototype.load = function (url, onLoad, onProgress, onError) {
if (this.path) url = this.path + url
const request = new XMLHttpRequest()
getAsset(url)
.downloadAsync()
.then((asset) => {
request.open('GET', asset.uri, true)
request.addEventListener(
'load',
(event) => {
if (request.status === 200) {
onLoad?.(request.response)
this.manager.itemEnd(url)
} else {
onError?.(event)
this.manager.itemError(url)
this.manager.itemEnd(url)
}
},
false,
)
request.addEventListener(
'progress',
(event) => {
onProgress?.(event)
},
false,
)
request.addEventListener(
'error',
(event) => {
onError?.(event)
this.manager.itemError(url)
this.manager.itemEnd(url)
},
false,
)
request.addEventListener(
'abort',
(event) => {
onError?.(event)
this.manager.itemError(url)
this.manager.itemEnd(url)
},
false,
)
if (this.responseType) request.responseType = this.responseType
if (this.withCredentials) request.withCredentials = this.withCredentials
for (const header in this.requestHeader) {
request.setRequestHeader(header, this.requestHeader[header])
}
request.send(null)
this.manager.itemStart(url)
})
return request
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment