react-native-filament
Version:
A real-time physically based 3D rendering engine for React Native
103 lines (98 loc) • 4.41 kB
JavaScript
import { useMemo } from 'react';
import { FilamentProxy, FilamentWorkletContext } from '../native/FilamentProxy';
import { useEngine } from '../hooks/useEngine';
import { useDisposableResource } from '../hooks/useDisposableResource';
import { useWorklet } from 'react-native-worklets-core';
import React from 'react';
import { Configurator } from './Configurator';
import { FilamentContext } from '../hooks/useFilamentContext';
import { RenderCallbackContext } from './RenderCallbackContext';
/**
* The `<FilamentScene>` holds contextual values for a Filament rendering scene.
*
* You need to wrap your rendering scene (= a component that uses `<FilamentView>`, hooks or
* other Filament components) with a `<FilamentScene>`.
*
* @note Make sure to wrap your scene in a parent component, otherwise the React context cannot be inferred.
* @example
* ```tsx
* function Scene() {
* // in here you can use Filament's hooks and components
* return (
* <FilamentView style={styles.container}>
* <DefaultLight />
* <Model source={{ uri: modelPath }} />
* </FilamentView>
* )
* }
*
* export function RocketModel() {
* // in here you only need to wrap the child-component with <FilamentScene>
* return (
* <FilamentScene>
* <Scene />
* </FilamentScene>
* )
* }
* ```
*/
export function FilamentScene({
children,
fallback,
config,
backend,
frameRateOptions,
...viewProps
}) {
// First create the engine, which we need to create (almost) all other filament APIs
const engine = useEngine({
config,
backend,
context: FilamentWorkletContext
});
// Create all Filament APIs using the engine
const transformManager = useDisposableResource(() => Promise.resolve(engine === null || engine === void 0 ? void 0 : engine.createTransformManager()), [engine]);
const renderableManager = useDisposableResource(() => Promise.resolve(engine === null || engine === void 0 ? void 0 : engine.createRenderableManager()), [engine]);
const scene = useDisposableResource(() => Promise.resolve(engine === null || engine === void 0 ? void 0 : engine.getScene()), [engine]);
const lightManager = useDisposableResource(() => Promise.resolve(engine === null || engine === void 0 ? void 0 : engine.createLightManager()), [engine]);
const view = useDisposableResource(() => Promise.resolve(engine === null || engine === void 0 ? void 0 : engine.getView()), [engine]);
const camera = useDisposableResource(() => Promise.resolve(engine === null || engine === void 0 ? void 0 : engine.getCamera()), [engine]);
const renderer = useDisposableResource(() => Promise.resolve(engine === null || engine === void 0 ? void 0 : engine.createRenderer()), [engine]);
const nameComponentManager = useDisposableResource(() => Promise.resolve(engine === null || engine === void 0 ? void 0 : engine.createNameComponentManager()), [engine]);
// Create a choreographer for this context tree
const choreographer = useDisposableResource(useWorklet(FilamentWorkletContext, () => {
'worklet';
return FilamentProxy.createChoreographer();
}));
// Construct the context object value:
const value = useMemo(() => {
if (transformManager == null || renderableManager == null || scene == null || lightManager == null || view == null || camera == null || renderer == null || nameComponentManager == null || choreographer == null || engine == null) {
return undefined;
}
return {
engine,
transformManager,
renderableManager,
scene,
lightManager,
view,
camera,
renderer,
nameComponentManager,
workletContext: FilamentWorkletContext,
choreographer: choreographer
};
}, [engine, transformManager, renderableManager, scene, lightManager, view, camera, renderer, nameComponentManager, choreographer]);
const rendererProps = useMemo(() => ({
frameRateOptions
}), [frameRateOptions]);
// If the APIs aren't ready yet render the fallback component (or nothing)
if (value == null) return fallback ?? null;
return /*#__PURE__*/React.createElement(FilamentContext.Provider, {
value: value
}, /*#__PURE__*/React.createElement(Configurator, {
rendererProps: rendererProps,
viewProps: viewProps
}, /*#__PURE__*/React.createElement(RenderCallbackContext.RenderContextProvider, null, children)));
}
//# sourceMappingURL=FilamentScene.js.map