1
1
import * as React from 'react'
2
- import { useCallback } from 'react'
2
+ import { useCallback , useMemo } from 'react'
3
3
import { Button , Dimensions , PixelRatio , StyleSheet , View } from 'react-native'
4
4
import {
5
5
Float3 ,
6
6
useModel ,
7
7
useAnimator ,
8
8
getAssetFromModel ,
9
- FilamentProvider ,
10
9
useFilamentContext ,
11
- useDisposableResource ,
12
10
useSkybox ,
13
11
useRecorder ,
14
12
useRecorderRenderLoop ,
13
+ Camera ,
14
+ FilamentAPIContextProvider ,
15
15
} from 'react-native-filament'
16
- import { useDefaultLight } from './hooks/useDefaultLight'
17
- import { getAssetPath } from './utils/getAssetPasth'
18
16
import { useRunOnJS , useSharedValue } from 'react-native-worklets-core'
17
+ import PenguGlb from '~/assets/pengu.glb'
18
+ import PirateGlb from '~/assets/pirate.glb'
19
+ import { DefaultLight } from './components/DefaultLight'
19
20
import Video from 'react-native-video'
20
21
21
- const penguModelPath = getAssetPath ( 'pengu.glb' )
22
- const pirateHatPath = getAssetPath ( 'pirate.glb' )
23
-
24
22
// Camera config:
25
23
const cameraPosition : Float3 = [ 0 , 0 , 8 ]
26
24
const cameraTarget : Float3 = [ 0 , 0 , 0 ]
@@ -34,39 +32,37 @@ const DURATION = 3 // seconds
34
32
35
33
function Renderer ( ) {
36
34
const { camera } = useFilamentContext ( )
37
- useDefaultLight ( )
38
35
useSkybox ( { color : '#88defb' } )
39
36
40
- const pengu = useModel ( { source : penguModelPath } )
41
- const penguAsset = getAssetFromModel ( pengu )
42
- const pirateHat = useModel ( { source : pirateHatPath } )
37
+ const pengu = useModel ( PenguGlb )
38
+ const penguAnimator = useAnimator ( pengu )
39
+ const pirateHat = useModel ( PirateGlb )
43
40
const pirateHatAsset = getAssetFromModel ( pirateHat )
44
- const pirateHatAnimator = useDisposableResource ( ( ) => {
45
- if ( pirateHatAsset == null || penguAsset == null ) {
46
- return undefined
47
- }
48
- return Promise . resolve ( pirateHatAsset . createAnimatorWithAnimationsFrom ( penguAsset ) )
49
- } , [ pirateHatAsset , penguAsset ] )
41
+ const pirateHatInstance = useMemo ( ( ) => pirateHatAsset ?. getInstance ( ) , [ pirateHatAsset ] )
50
42
51
- const penguAnimator = useAnimator ( penguAsset )
43
+ // Sync pirate hat animation with pengu
44
+ React . useEffect ( ( ) => {
45
+ if ( penguAnimator == null || pirateHatInstance == null ) return
46
+ const id = penguAnimator . addToSyncList ( pirateHatInstance )
47
+ return ( ) => {
48
+ penguAnimator . removeFromSyncList ( id )
49
+ }
50
+ } , [ penguAnimator , pirateHatInstance ] )
52
51
53
52
const renderCallback = useCallback (
54
53
( passedSeconds : number ) => {
55
54
'worklet'
56
55
camera . lookAt ( cameraPosition , cameraTarget , cameraUp )
57
56
58
- if ( pirateHatAnimator == null || penguAnimator == null ) {
57
+ if ( penguAnimator == null ) {
59
58
return
60
59
}
61
60
62
61
// Update the animators to play the current animation
63
62
penguAnimator . applyAnimation ( 0 , passedSeconds )
64
- pirateHatAnimator . applyAnimation ( 0 , passedSeconds )
65
-
66
63
penguAnimator . updateBoneMatrices ( )
67
- pirateHatAnimator . updateBoneMatrices ( )
68
64
} ,
69
- [ camera , pirateHatAnimator , penguAnimator ]
65
+ [ camera , penguAnimator ]
70
66
)
71
67
72
68
const framesToRender = DURATION * FPS
@@ -145,7 +141,13 @@ function Renderer() {
145
141
146
142
return (
147
143
< View style = { styles . container } >
148
- { videoUri != null ? (
144
+ { videoUri == null ? (
145
+ // Render our scene that we want to record
146
+ < >
147
+ < Camera />
148
+ < DefaultLight />
149
+ </ >
150
+ ) : (
149
151
< Video
150
152
style = { { flex : 1 } }
151
153
paused = { false }
@@ -156,17 +158,18 @@ function Renderer() {
156
158
onLoad = { ( ) => console . log ( 'On load' ) }
157
159
onEnd = { ( ) => console . log ( 'On end' ) }
158
160
/>
159
- ) : null }
161
+ ) }
160
162
< Button onPress = { onStartRecording } title = { 'Start recording' } />
161
163
</ View >
162
164
)
163
165
}
164
166
165
167
export function AnimationTransitionsRecording ( ) {
166
168
return (
167
- < FilamentProvider >
169
+ // Provide the API necessary for recording (accessing the RNF apis) in a react context
170
+ < FilamentAPIContextProvider >
168
171
< Renderer />
169
- </ FilamentProvider >
172
+ </ FilamentAPIContextProvider >
170
173
)
171
174
}
172
175
0 commit comments