import { MeshPhysicalMaterial , Shader } from 'three' ; import { getKeyValue , setKeyValue } from './helpers/objects' ; import { MaterialConstructor } from './types/index' ; import { Uniforms } from './types/internal' ; function createMaterial ( baseMaterial = MeshPhysicalMaterial , uniforms = { } , onBeforeCompile ? ) { return class ComponentMaterial extends baseMaterial { constructor ( parameters = { } ) { const entries = Object . keys ( uniforms ) ; super ( parameters ) ; this . setValues ( parameters ) ; entries . forEach ( key => { setKeyValue ( this , `_${ key }` , { value : uniforms [ key ] } ) ; Object . defineProperty ( this , key , { get : ( ) => this [ `_${ key }` ] . value , set : v => ( this [ `_${ key }` ] . value = v ) } ) ; } ) ; } onBeforeCompile ( shader ) { const handler = { get : function ( target , key ) { return getKeyValue ( target , key ) ; } , set : function ( target , key , value ) { setKeyValue ( target , key , value ) ; return true ; } } ; const entries = Object . keys ( uniforms ) ; entries . forEach ( key => { shader . uniforms [ key ] = this [ `_${ key }` ] ; } ) ; const proxiedShader = new Proxy ( shader , handler ) ; if ( onBeforeCompile ) { onBeforeCompile ( proxiedShader ) ; } } } ; } export default createMaterial ;