import * as OGL from 'ogl' ; import { Asset } from 'expo-asset' ; import { readAsStringAsync } from 'expo-file-system' ; import { decode } from 'base64-arraybuffer' ; import { suspend } from 'suspend-react' ; import { useOGL } from '../hooks' ; import { buildGraph } from '../shared/utils' ; /**
 * Generates an asset based on input type.
 */ export 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.' ; } } ; /**
 * Downloads from a local URI and decodes into an ArrayBuffer.
 */ export const toBuffer = async ( localUri ) => readAsStringAsync ( localUri , { encoding : 'base64' } ) . then ( decode ) ; /**
 * Loads assets suspensefully.
 */ export const useLoader = ( loader , input , extensions ? ) => { const { gl } = useOGL ( ) ; const keys = Array . isArray ( input ) ? input : [ input ] ; return suspend ( async ( loader , ... urls ) => { extensions ?. ( loader ) ; const result = await Promise . all ( urls . map ( async ( url ) => { if ( loader === OGL . TextureLoader ) { const asset = await getAsset ( url ) . downloadAsync ( ) ; const image = { data : asset , width : asset . width , height : asset . height } ; const texture = new OGL . Texture ( gl , { image } ) ; return texture ; } let data ; if ( url . startsWith ?. ( 'http' ) ) { data = await loader . load ( gl , url ) ; } else { const { localUri } = await getAsset ( url ) . downloadAsync ( ) ; const arrayBuffer = await toBuffer ( localUri ) ; data = await loader . parse ( gl , arrayBuffer ) ; } if ( data . scene ) { const scene = data . scene ?. length ? data . scene [ 0 ] : data . scene ; const graph = buildGraph ( scene ) ; Object . assign ( data , { scene , ... graph } ) ; } return data ; } ) ) ; return Array . isArray ( input ) ? result : result [ 0 ] ; } , [ loader , ... keys ] ) ; } ;