react-native-filament
Version:
A real-time physically based 3D rendering engine for React Native
72 lines (62 loc) • 2.28 kB
text/typescript
import { useEffect, useMemo, useState } from 'react'
import { FilamentBuffer } from '../native/FilamentBuffer'
import { FilamentProxy } from '../native/FilamentProxy'
import { withCleanupScope } from '../utilities/withCleanupScope'
import { Image } from 'react-native'
// In React Native, `require(..)` returns a number.
type Require = number // ReturnType<typeof require>
export type BufferSource =
| Require
| {
/**
* A web URL (http:// or https://), local file (file://) or asset path of the bundled asset.
*/
uri: string
}
export interface BufferProps {
/**
* If you are passing in a `.glb` model or similar from your app's bundle using `require(..)`, make sure to add `glb` as an asset extension to `metro.config.js`!
* If you are passing in a `{ url: ... }`, make sure the URL points directly to a `.glb` model. This can either be a web URL (`http://..`/`https://..`), a local file (`file://..`), or an native asset path (`path/to/asset.glb`)
*/
source: BufferSource
/**
* @default true
*/
releaseOnUnmount?: boolean
}
/**
* Asynchronously load an asset from the given web URL, local file path, or resource ID.
*/
export function useBuffer({ source: source, releaseOnUnmount = true }: BufferProps): FilamentBuffer | undefined {
const [buffer, setBuffer] = useState<FilamentBuffer | undefined>(undefined)
const uri = useMemo(() => {
if (typeof source === 'object') {
return source.uri
}
const asset = Image.resolveAssetSource(source)
if (asset == null) {
throw new Error(
`Failed to load source: ${source}. Are you sure that\n-The asset exists on this path?\n-The metro bundler is configured correctly as explained in the documentation?`
)
}
return asset.uri
}, [source])
// TODO: useDisposableResource
useEffect(() => {
let localBuffer: FilamentBuffer | undefined
FilamentProxy.loadAsset(uri)
.then((asset) => {
localBuffer = asset
setBuffer(asset)
})
.catch((error) => {
console.error(`Failed to load asset: ${uri}`, error)
})
return withCleanupScope(() => {
if (releaseOnUnmount) {
localBuffer?.release()
}
})
}, [releaseOnUnmount, uri])
return buffer
}