Skip to content

Commit b1d5a31

Browse files
committed
fix: react API separate context + view to handle all use-cases (#202)
BREAKING CHANGE: The `<Filament />` component has been split into `<FilamentContext><FilamentView /></FilamentContext>`. Also note that the FilamentView doesn't support any other children than the RNF ones.
1 parent 13a9b54 commit b1d5a31

28 files changed

+237
-263
lines changed

README.md

Lines changed: 12 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -39,19 +39,21 @@ cd ios && pod install
3939
### Example
4040

4141
```tsx
42-
import { Filament, Model, Camera } from 'react-native-filament'
42+
import { FilamentContext, FilamentView, Model, Camera } from 'react-native-filament'
4343

4444
function App() {
4545
return (
46-
<Filament
47-
style={{ width: 100, height: 100 }}
48-
model={model}
49-
>
50-
// Render with the default camera:
51-
<Camera />
52-
// Add a model to the scene (only glb supported yet):
53-
<Model source={require('./duck.glb')}>
54-
</Filament>
46+
<FilamentContext>
47+
<FilamentView
48+
style={{ width: 100, height: 100 }}
49+
model={model}
50+
>
51+
// Render with the default camera:
52+
<Camera />
53+
// Add a model to the scene (only glb supported yet):
54+
<Model source={require('./duck.glb')}>
55+
</FilamentView>
56+
</FilamentContext>
5557
)
5658
}
5759
```

package/example/Shared/src/AnimationTransitions.tsx

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,10 @@ import {
77
useAnimator,
88
getAssetFromModel,
99
useFilamentContext,
10-
Filament,
11-
RenderCallbackContext,
10+
FilamentContext,
11+
FilamentView,
1212
Camera,
13+
RenderCallback,
1314
} from 'react-native-filament'
1415
import { useSharedValue } from 'react-native-worklets-core'
1516
import PenguGlb from '~/assets/pengu.glb'
@@ -19,7 +20,7 @@ import { DefaultLight } from './components/DefaultLight'
1920
const animationInterpolationTime = 5
2021

2122
function Renderer() {
22-
const { camera, view, scene } = useFilamentContext()
23+
const { view, scene } = useFilamentContext()
2324

2425
const pengu = useModel(PenguGlb)
2526
const penguAnimator = useAnimator(pengu)
@@ -43,7 +44,7 @@ function Renderer() {
4344
const animationInterpolation = useSharedValue(0)
4445
const currentAnimationIndex = useSharedValue(0)
4546

46-
RenderCallbackContext.useRenderCallback(
47+
const renderCallback: RenderCallback = useCallback(
4748
({ passedSeconds }) => {
4849
'worklet'
4950

@@ -75,7 +76,7 @@ function Renderer() {
7576

7677
penguAnimator.updateBoneMatrices()
7778
},
78-
[view, camera, penguAnimator, currentAnimationIndex, prevAnimationIndex, prevAnimationStarted, animationInterpolation]
79+
[penguAnimator, currentAnimationIndex, prevAnimationIndex, prevAnimationStarted, animationInterpolation]
7980
)
8081

8182
const animations = useMemo(() => {
@@ -121,8 +122,10 @@ function Renderer() {
121122

122123
return (
123124
<View style={styles.container} onTouchStart={onTouchStart}>
124-
<Camera />
125-
<DefaultLight />
125+
<FilamentView style={styles.filamentView} renderCallback={renderCallback}>
126+
<Camera />
127+
<DefaultLight />
128+
</FilamentView>
126129

127130
<ScrollView style={styles.btnContainer}>
128131
<Button
@@ -168,9 +171,9 @@ export function AnimationTransitions() {
168171

169172
return (
170173
<View style={styles.container}>
171-
<Filament style={styles.filamentView} key={count}>
174+
<FilamentContext key={count}>
172175
<Renderer />
173-
</Filament>
176+
</FilamentContext>
174177
<Button title="Create a new react element" onPress={increment} />
175178
</View>
176179
)

package/example/Shared/src/AnimationTransitionsRecording.tsx

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,7 @@ import {
1111
useRecorder,
1212
useRecorderRenderLoop,
1313
Camera,
14-
FilamentAPIContextProvider,
15-
BackgroundImage,
14+
FilamentContext,
1615
} from 'react-native-filament'
1716
import { useRunOnJS, useSharedValue } from 'react-native-worklets-core'
1817
import PenguGlb from '~/assets/pengu.glb'
@@ -168,9 +167,9 @@ function Renderer() {
168167
export function AnimationTransitionsRecording() {
169168
return (
170169
// Provide the API necessary for recording (accessing the RNF apis) in a react context
171-
<FilamentAPIContextProvider>
170+
<FilamentContext>
172171
<Renderer />
173-
</FilamentAPIContextProvider>
172+
</FilamentContext>
174173
)
175174
}
176175

package/example/Shared/src/CameraPan.tsx

Lines changed: 11 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
1-
import { Camera, Filament, Model, useCameraManipulator } from 'react-native-filament'
2-
import React, { useCallback, useState } from 'react'
1+
import React from 'react'
2+
import { Camera, FilamentContext, FilamentView, Model, useCameraManipulator } from 'react-native-filament'
33
import { Gesture, GestureDetector } from 'react-native-gesture-handler'
4-
import { LayoutChangeEvent, StyleSheet, View } from 'react-native'
4+
import { Dimensions, StyleSheet, View } from 'react-native'
55
import { useSharedValue } from 'react-native-worklets-core'
66
import { DefaultLight } from './components/DefaultLight'
77

@@ -15,17 +15,13 @@ function Scene() {
1515
})
1616

1717
// Pan gesture
18-
const [viewHeight, setViewHeight] = useState<number>() // As we need to invert the Y axis we must know the view height
18+
const viewHeight = Dimensions.get('window').height
1919
const panGesture = Gesture.Pan()
2020
.onBegin((event) => {
21-
if (viewHeight == null) return
22-
2321
const yCorrected = viewHeight - event.translationY
2422
cameraManipulator?.grabBegin(event.translationX, yCorrected, false) // false means rotation instead of translation
2523
})
2624
.onUpdate((event) => {
27-
if (viewHeight == null) return
28-
2925
const yCorrected = viewHeight - event.translationY
3026
cameraManipulator?.grabUpdate(event.translationX, yCorrected)
3127
})
@@ -49,27 +45,25 @@ function Scene() {
4945
})
5046
const combinedGesture = Gesture.Race(pinchGesture, panGesture)
5147

52-
const onLayout = useCallback((event: LayoutChangeEvent) => {
53-
setViewHeight(event.nativeEvent.layout.height)
54-
}, [])
55-
5648
return (
5749
<GestureDetector gesture={combinedGesture}>
58-
<View onLayout={onLayout} style={styles.container}>
50+
<FilamentView style={styles.container}>
5951
<Camera cameraManipulator={cameraManipulator} />
6052
<DefaultLight />
6153

6254
<Model source={{ uri: modelPath }} transformToUnitCube />
63-
</View>
55+
</FilamentView>
6456
</GestureDetector>
6557
)
6658
}
6759

6860
export function CameraPan() {
6961
return (
70-
<Filament>
71-
<Scene />
72-
</Filament>
62+
<View style={styles.container}>
63+
<FilamentContext>
64+
<Scene />
65+
</FilamentContext>
66+
</View>
7367
)
7468
}
7569

package/example/Shared/src/ImageExample.tsx

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,28 +1,28 @@
11
import React from 'react'
22
import { StyleSheet } from 'react-native'
3-
import { BackgroundImage, Camera, Filament, Model } from 'react-native-filament'
3+
import { BackgroundImage, Camera, FilamentContext, FilamentView, Model } from 'react-native-filament'
44
import { DefaultLight } from './components/DefaultLight'
55
import BackgroundImageMaterial from '~/assets/background_image.matc'
66

77
const imageResource = require('~/assets/example_background.jpeg')
88

99
function Renderer() {
1010
return (
11-
<>
11+
<FilamentView style={styles.container}>
1212
<Camera />
1313
<DefaultLight />
1414
<Model source={require('~/assets/pengu.glb')} transformToUnitCube />
1515

1616
<BackgroundImage source={imageResource} materialSource={BackgroundImageMaterial} resizeMode="cover" />
17-
</>
17+
</FilamentView>
1818
)
1919
}
2020

2121
export function ImageExample() {
2222
return (
23-
<Filament style={styles.container}>
23+
<FilamentContext>
2424
<Renderer />
25-
</Filament>
25+
</FilamentContext>
2626
)
2727
}
2828

package/src/hooks/useAnimator.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { useMemo } from 'react'
22
import { Animator, FilamentAsset, FilamentInstance } from '../types'
3-
import { useFilamentContext } from '../react/FilamentContext'
3+
import { useFilamentContext } from '../react/Context'
44
import { FilamentModel } from './useModel'
55

66
function isFilamentModel(asset: FilamentAsset | FilamentInstance | FilamentModel): asset is FilamentModel {

package/src/hooks/useCameraManipulator.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { useFilamentContext } from '../react/FilamentContext'
1+
import { useFilamentContext } from '../react/Context'
22
import { Float3, OrbitCameraManipulatorConfig } from '../types'
33
import { useDisposableResource } from './useDisposableResource'
44

package/src/hooks/useConfigureAssetShadow.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { useEffect, useMemo, useRef } from 'react'
22
import { FilamentAsset, RenderableManager } from '../types'
3-
import { useFilamentContext } from '../react/FilamentContext'
3+
import { useFilamentContext } from '../react/Context'
44

55
export type UseAssetShadowProps = {
66
renderableManager: RenderableManager

package/src/hooks/useLightEntity.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { useEffect, useMemo } from 'react'
22
import { LightConfig, LightManager } from '../types'
33
import { ISharedValue } from 'react-native-worklets-core'
4-
import { useFilamentContext } from '../react/FilamentContext'
4+
import { useFilamentContext } from '../react/Context'
55

66
export type UseLightEntityProps =
77
| LightConfig

package/src/hooks/useModel.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { type BufferSource, useBuffer } from './useBuffer'
22
import { FilamentAsset } from '../types/FilamentAsset'
3-
import { useFilamentContext } from '../react/FilamentContext'
3+
import { useFilamentContext } from '../react/Context'
44
import { useDisposableResource } from './useDisposableResource'
55
import usePrevious from './usePrevious'
66
import { useWorkletEffect } from './useWorkletEffect'

0 commit comments

Comments
 (0)