@@ -6,10 +6,10 @@ import { checkUpdate } from './update';
6
6
7
7
// This function prepares a set of changes to be applied to the instance
8
8
function diffProps ( instance : NgtAnyRecord , props : NgtAnyRecord ) {
9
- const propsEntries = Object . entries ( props ) ;
10
9
const changes : [ key : string , value : unknown ] [ ] = [ ] ;
11
10
12
- for ( const [ propKey , propValue ] of propsEntries ) {
11
+ for ( const propKey in props ) {
12
+ const propValue = props [ propKey ] ;
13
13
let key = propKey ;
14
14
if ( is . colorSpaceExist ( instance ) ) {
15
15
if ( propKey === 'encoding' ) {
@@ -50,6 +50,21 @@ function getMemoizedPrototype(root: any) {
50
50
return ctor ;
51
51
}
52
52
53
+ function resolve ( instance : any , key : string ) : { root : any ; targetKey : string ; targetProp : any } {
54
+ let targetProp = instance [ key ] ;
55
+ if ( ! key . includes ( '.' ) ) return { root : instance , targetKey : key , targetProp } ;
56
+
57
+ // Resolve pierced target
58
+ const chain = key . split ( '.' ) ;
59
+ targetProp = chain . reduce ( ( acc , part ) => acc [ part ] , instance ) ;
60
+ const targetKey = chain . pop ( ) ! ;
61
+
62
+ // Switch root if atomic
63
+ if ( ! targetProp ?. set ) instance = chain . reduce ( ( acc , part ) => acc [ part ] , instance ) ;
64
+
65
+ return { root : instance , targetKey, targetProp } ;
66
+ }
67
+
53
68
// This function applies a set of changes to the instance
54
69
export function applyProps < T extends NgtAnyRecord > ( instance : NgtInstanceState < T > [ 'object' ] , props : NgtAnyRecord ) {
55
70
// if props is empty
@@ -83,8 +98,12 @@ export function applyProps<T extends NgtAnyRecord>(instance: NgtInstanceState<T>
83
98
// }
84
99
// }
85
100
86
- const currentInstance = instance ;
87
- const targetProp = ( currentInstance as NgtAnyRecord ) [ key ] ;
101
+ const { root, targetKey, targetProp } = resolve ( instance , key ) ;
102
+
103
+ // we have switched due to pierced props
104
+ if ( root !== instance ) {
105
+ return applyProps ( root , { [ targetKey ] : value } ) ;
106
+ }
88
107
89
108
// Copy if properties match signatures
90
109
if (
@@ -97,13 +116,13 @@ export function applyProps<T extends NgtAnyRecord>(instance: NgtInstanceState<T>
97
116
is . three < THREE . BufferGeometry > ( targetProp , 'isBufferGeometry' ) &&
98
117
is . three < THREE . BufferGeometry > ( value , 'isBufferGeometry' )
99
118
) {
100
- Object . assign ( currentInstance , { [ key ] : value } ) ;
119
+ Object . assign ( root , { [ targetKey ] : value } ) ;
101
120
} else {
102
121
// fetch the default state of the target
103
- const ctor = getMemoizedPrototype ( currentInstance ) ;
122
+ const ctor = getMemoizedPrototype ( root ) ;
104
123
// The target key was originally null or undefined, which indicates that the object which
105
124
// is now present was externally set by the user, we should therefore assign the value directly
106
- if ( ctor !== undefined && ctor [ key ] == null ) Object . assign ( currentInstance , { [ key ] : value } ) ;
125
+ if ( ctor !== undefined && ctor [ targetKey ] == null ) Object . assign ( root , { [ targetKey ] : value } ) ;
107
126
// Otherwise copy is correct
108
127
else targetProp . copy ( value ) ;
109
128
}
@@ -127,26 +146,26 @@ export function applyProps<T extends NgtAnyRecord>(instance: NgtInstanceState<T>
127
146
}
128
147
// Else, just overwrite the value
129
148
else {
130
- Object . assign ( currentInstance , { [ key ] : value } ) ;
149
+ Object . assign ( root , { [ targetKey ] : value } ) ;
131
150
132
151
// Auto-convert sRGB texture parameters for built-in materials
133
152
// https://github.com/pmndrs/react-three-fiber/issues/344
134
153
// https://github.com/mrdoob/three.js/pull/25857
135
154
if (
136
155
rootState &&
137
156
! rootState . linear &&
138
- colorMaps . includes ( key ) &&
139
- ( currentInstance [ key ] as THREE . Texture | undefined ) ?. isTexture &&
157
+ colorMaps . includes ( targetKey ) &&
158
+ ( root [ targetKey ] as THREE . Texture | undefined ) ?. isTexture &&
140
159
// sRGB textures must be RGBA8 since r137 https://github.com/mrdoob/three.js/pull/23129
141
- currentInstance [ key ] . format === THREE . RGBAFormat &&
142
- currentInstance [ key ] . type === THREE . UnsignedByteType
160
+ root [ targetKey ] . format === THREE . RGBAFormat &&
161
+ root [ targetKey ] . type === THREE . UnsignedByteType
143
162
) {
144
163
// NOTE: this cannot be set from the renderer (e.g. sRGB source textures rendered to P3)
145
- currentInstance [ key ] . colorSpace = THREE . SRGBColorSpace ;
164
+ root [ targetKey ] . colorSpace = THREE . SRGBColorSpace ;
146
165
}
147
166
}
148
167
149
- checkUpdate ( currentInstance [ key ] ) ;
168
+ checkUpdate ( root [ targetKey ] ) ;
150
169
checkUpdate ( targetProp ) ;
151
170
invalidateInstance ( instance as NgtInstanceNode < T > ) ;
152
171
}
0 commit comments