@@ -6,10 +6,10 @@ import { checkUpdate } from './update';
66
77// This function prepares a set of changes to be applied to the instance
88function diffProps ( instance : NgtAnyRecord , props : NgtAnyRecord ) {
9- const propsEntries = Object . entries ( props ) ;
109 const changes : [ key : string , value : unknown ] [ ] = [ ] ;
1110
12- for ( const [ propKey , propValue ] of propsEntries ) {
11+ for ( const propKey in props ) {
12+ const propValue = props [ propKey ] ;
1313 let key = propKey ;
1414 if ( is . colorSpaceExist ( instance ) ) {
1515 if ( propKey === 'encoding' ) {
@@ -50,6 +50,21 @@ function getMemoizedPrototype(root: any) {
5050 return ctor ;
5151}
5252
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+
5368// This function applies a set of changes to the instance
5469export function applyProps < T extends NgtAnyRecord > ( instance : NgtInstanceState < T > [ 'object' ] , props : NgtAnyRecord ) {
5570 // if props is empty
@@ -83,8 +98,12 @@ export function applyProps<T extends NgtAnyRecord>(instance: NgtInstanceState<T>
8398 // }
8499 // }
85100
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+ }
88107
89108 // Copy if properties match signatures
90109 if (
@@ -97,13 +116,13 @@ export function applyProps<T extends NgtAnyRecord>(instance: NgtInstanceState<T>
97116 is . three < THREE . BufferGeometry > ( targetProp , 'isBufferGeometry' ) &&
98117 is . three < THREE . BufferGeometry > ( value , 'isBufferGeometry' )
99118 ) {
100- Object . assign ( currentInstance , { [ key ] : value } ) ;
119+ Object . assign ( root , { [ targetKey ] : value } ) ;
101120 } else {
102121 // fetch the default state of the target
103- const ctor = getMemoizedPrototype ( currentInstance ) ;
122+ const ctor = getMemoizedPrototype ( root ) ;
104123 // The target key was originally null or undefined, which indicates that the object which
105124 // 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 } ) ;
107126 // Otherwise copy is correct
108127 else targetProp . copy ( value ) ;
109128 }
@@ -127,26 +146,26 @@ export function applyProps<T extends NgtAnyRecord>(instance: NgtInstanceState<T>
127146 }
128147 // Else, just overwrite the value
129148 else {
130- Object . assign ( currentInstance , { [ key ] : value } ) ;
149+ Object . assign ( root , { [ targetKey ] : value } ) ;
131150
132151 // Auto-convert sRGB texture parameters for built-in materials
133152 // https://github.com/pmndrs/react-three-fiber/issues/344
134153 // https://github.com/mrdoob/three.js/pull/25857
135154 if (
136155 rootState &&
137156 ! 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 &&
140159 // 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
143162 ) {
144163 // 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 ;
146165 }
147166 }
148167
149- checkUpdate ( currentInstance [ key ] ) ;
168+ checkUpdate ( root [ targetKey ] ) ;
150169 checkUpdate ( targetProp ) ;
151170 invalidateInstance ( instance as NgtInstanceNode < T > ) ;
152171 }
0 commit comments