11import { getGlobalObject , WMLConstructorDecorator } from "@windmillcode/wml-components-base" ;
2- import { AmbientLight , BufferGeometry , Camera , CameraHelper , Clock , Controls , DirectionalLight , DirectionalLightHelper , HemisphereLight , HemisphereLightHelper , Light , Material , Mesh , Object3D , OrthographicCamera , PerspectiveCamera , PointLight , PointLightHelper , Raycaster , Renderer , Scene , SpotLight , SpotLightHelper , Vector3 , WebGLRenderer } from "three" ;
2+ import { AmbientLight , BufferGeometry , Camera , CameraHelper , Clock , Controls , DirectionalLight , DirectionalLightHelper , HemisphereLight , HemisphereLightHelper , Light , Loader , LoadingManager , Material , Mesh , Object3D , OrthographicCamera , PerspectiveCamera , PointLight , PointLightHelper , Raycaster , Renderer , Scene , SpotLight , SpotLightHelper , Texture , TextureLoader , Vector3 , WebGLRenderer } from "three" ;
33import { GUI as DatGUI } from "dat.gui" ;
44import { GUI as LilGUI } from "lil-gui" ;
55import { OrbitControls } from 'three/addons/controls/OrbitControls.js' ;
6+ import { GLTF } from 'three/examples/jsm/loaders/GLTFLoader.js' ;
67@WMLConstructorDecorator
78export class WMLThreeProps < R = Renderer > {
89 constructor ( params : Partial < WMLThreeProps > = { } ) { }
910 renderers : Array < any | Renderer > = [ new WebGLRenderer ( { antialias : true } ) ] ;
1011 rendererParentElement = getGlobalObject ( ) . document . body ;
11- scenes : Array < Object3D > = [ new Scene ( ) ]
12+ // TODO Array<Object3D> was there for a reason why
13+ scenes : Array < Scene > = [ new Scene ( ) ]
1214 cameras : Array < Camera > = [ ] ;
1315 controls : Array < Controls < any > > = [ ] ;
1416 inspectors : Array < {
@@ -31,31 +33,33 @@ export class WMLThreeProps<R = Renderer> {
3133 addHelper : true
3234 } )
3335 ] ;
34- rayCasters : Array < any > = [ ] ;
36+ rayCasters : Array < any > = [ new Raycaster ( ) ] ;
3537 objects :Array < WMLThreeObjectProps > = [ ]
38+ clock = new Clock ( )
39+ animateFunctions :Array < ( props :{ clock :Clock } ) => void > = [ ]
3640
3741 // init methods
38- init = ( props ?:Partial < {
39- preCheck :boolean
40- addRendererToDOM :boolean
41- initCameras :boolean
42- initControls :boolean
43- initInspectors : boolean
44- initLights : boolean
45- initRayCasters : boolean
46- initObjects : boolean
47- animate :boolean
48- listenForWindowResize :boolean
42+ init = async ( props ?:Partial < {
43+ preCheck :any
44+ addRendererToDOM :any
45+ initCameras :any
46+ initControls :any
47+ initLights : any
48+ initRayCasters : any
49+ initObjects : any
50+ initInspectors : any
51+ animate :any
52+ listenForWindowResize :any
4953 } > ) => {
5054 let { preCheck, addRendererToDOM, initCameras, initControls, initInspectors, initLights, initRayCasters, initObjects, animate, listenForWindowResize } = props || { }
5155 if ( preCheck !== false ) this . preCheck ( )
5256 if ( addRendererToDOM !== false ) this . addRendererToDOM ( ) ;
53- if ( initCameras !== false ) this . initCameras ( )
57+ if ( initCameras !== false ) this . initCameras ( initCameras )
5458 if ( initControls !== false ) this . initControls ( )
55- if ( initInspectors !== false ) this . initInspectors ( )
5659 if ( initLights !== false ) this . initLights ( )
5760 if ( initRayCasters !== false ) this . initRayCasters ( )
58- if ( initObjects !== false ) this . initObjects ( )
61+ if ( initObjects !== false ) await this . initObjects ( ) . then ( console . log )
62+ if ( initInspectors !== false ) this . initInspectors ( )
5963 if ( animate !== false ) this . getCurrentRenderer ( ) . setAnimationLoop ( this . animate ) ;
6064 if ( listenForWindowResize !== false ) this . listenForWindowResize ( )
6165 }
@@ -66,9 +70,6 @@ export class WMLThreeProps<R = Renderer> {
6670 throw new Error ( 'Three.js cannot work in your program, because it requires the "document" global.Browser environments usually hold this in the global window variable' )
6771 }
6872 }
69-
70- clock = new Clock ( )
71- animateFunctions :Array < ( props :{ clock :Clock } ) => void > = [ ]
7273 animate = ( ) => {
7374 this . animateFunctions . forEach ( fn => fn ( { clock :this . clock } ) )
7475 this . getCurrentRenderer ( ) . render ( this . getCurentScene ( ) , this . getCurentCamera ( ) ) ;
@@ -103,6 +104,83 @@ export class WMLThreeProps<R = Renderer> {
103104 new OrbitControls ( this . getCurentCamera ( ) , this . getCurrentRenderer ( ) . domElement )
104105 )
105106 }
107+ initLights = ( ) => {
108+ this . lights . forEach ( ( lightInfo ) => {
109+
110+ let { light, addHelper, helper, addShadowHelper, shadowHelper} = lightInfo
111+ // helps with pixelated shadows
112+ if ( light . shadow ) {
113+ light . shadow . mapSize . width = light . shadow . mapSize . height = 1024
114+ }
115+ //
116+ this . getCurentScene ( ) . add ( light )
117+ if ( addHelper ) {
118+ if ( light instanceof DirectionalLight ) {
119+ lightInfo . helper = helper = new DirectionalLightHelper ( light , 5 )
120+ }
121+ else if ( light instanceof PointLight ) {
122+ lightInfo . helper = helper = new PointLightHelper ( light , 5 )
123+ }
124+ else if ( light instanceof SpotLight ) {
125+ lightInfo . helper = helper = new SpotLightHelper ( light , 5 )
126+ }
127+ else if ( light instanceof HemisphereLight ) {
128+ lightInfo . helper = helper = new HemisphereLightHelper ( light , 5 )
129+ }
130+ else {
131+ console . warn ( `no helper for ${ light . type } ` )
132+ }
133+ }
134+ if ( helper ) {
135+ this . getCurentScene ( ) . add ( helper )
136+ }
137+ if ( addShadowHelper && light . castShadow && light . shadow ) {
138+ lightInfo . shadowHelper = shadowHelper = new CameraHelper ( light . shadow . camera )
139+
140+ }
141+ if ( shadowHelper ) {
142+ this . getCurentScene ( ) . add ( shadowHelper )
143+ }
144+
145+
146+
147+ } )
148+ }
149+ initObjects = ( ) => {
150+ this . objects . forEach ( ( object : WMLThreeObjectProps ) => {
151+
152+ object . regularMeshes . forEach ( ( mesh ) => {
153+ this . getCurentScene ( ) . add ( mesh )
154+
155+ } )
156+ } )
157+
158+ return Promise . all ( this . objects . map ( ( object : WMLThreeObjectProps ) => {
159+ return Promise . all ( object . textures . map ( ( texture ) => {
160+ return Promise . all ( texture . group . map ( ( item , index0 ) => {
161+
162+ item . loader . manager = texture . manager
163+ return new Promise ( ( res , rej ) => {
164+ item . loader . load (
165+ item . url ,
166+ ( data :any ) => {
167+ object . meshes [ index0 ] = data
168+ item . onLoad ?.( data )
169+ res ( data )
170+ } ,
171+ item . onProgress ,
172+ ( err :any ) => {
173+ item . onError ?.( err )
174+ rej ( err )
175+ }
176+ )
177+ } )
178+
179+
180+ } ) )
181+ } ) )
182+ } ) )
183+ }
106184 initInspectors = ( ) => {
107185 this . inspectors . forEach ( ( inspector ) => {
108186 if ( inspector . gui instanceof DatGUI ) {
@@ -129,54 +207,8 @@ export class WMLThreeProps<R = Renderer> {
129207 }
130208 } )
131209 }
132- initLights = ( ) => {
133- this . lights . forEach ( ( lightInfo ) => {
134- if ( lightInfo instanceof Light ) {
135- this . getCurentScene ( ) . add ( lightInfo )
136- }
137- else {
138- let { light, addHelper, helper, addShadowHelper, shadowHelper} = lightInfo
139- if ( light ) {
140- this . getCurentScene ( ) . add ( light )
141- if ( addHelper ) {
142- if ( light instanceof DirectionalLight ) {
143- lightInfo . helper = helper = new DirectionalLightHelper ( light , 5 )
144- }
145- else if ( light instanceof PointLight ) {
146- lightInfo . helper = helper = new PointLightHelper ( light , 5 )
147- }
148- else if ( light instanceof SpotLight ) {
149- lightInfo . helper = helper = new SpotLightHelper ( light , 5 )
150- }
151- else if ( light instanceof HemisphereLight ) {
152- lightInfo . helper = helper = new HemisphereLightHelper ( light , 5 )
153- }
154- else {
155- console . warn ( `no helper for ${ light . type } ` )
156- }
157- }
158- if ( helper ) {
159- this . getCurentScene ( ) . add ( helper )
160- }
161- if ( addShadowHelper && light . castShadow && light . shadow ) {
162- lightInfo . shadowHelper = shadowHelper = new CameraHelper ( light . shadow . camera )
163-
164- }
165- if ( shadowHelper ) {
166- this . getCurentScene ( ) . add ( shadowHelper )
167- }
168- }
169- }
170-
171- } )
172- }
173- initObjects = ( ) => {
174- this . objects . forEach ( ( object : WMLThreeObjectProps ) => {
175- this . getCurentScene ( ) . add ( object . meshes [ 0 ] )
176- } )
177- }
178210 initRayCasters = ( ) => {
179- this . rayCasters . push ( new Raycaster ( ) )
211+ this . rayCasters . push ( )
180212 }
181213 listenForWindowResize = ( ) => {
182214 getGlobalObject ( ) . onresize = ( ) => {
@@ -195,7 +227,7 @@ export class WMLThreeProps<R = Renderer> {
195227 }
196228 }
197229 //
198- private getRendererParentDetails = ( ) => {
230+ getRendererParentDetails = ( ) => {
199231 if ( this . rendererParentElement === document . body ) {
200232 return {
201233 width : window . innerWidth ,
@@ -228,7 +260,7 @@ export class WMLCommonThreeProps extends WMLThreeProps<WebGLRenderer> {
228260
229261
230262 get scene ( ) { return this . getCurentScene ( ) }
231- set scene ( scene : Object3D ) { this . scenes [ 0 ] = scene }
263+ set scene ( scene : Scene ) { this . scenes [ 0 ] = scene }
232264
233265 get camera ( ) { return this . getCurentCamera ( ) }
234266 set camera ( camera : Camera ) { this . cameras [ 0 ] = camera }
@@ -259,9 +291,12 @@ export class WMLThreeObjectProps {
259291 constructor ( params : Partial < WMLThreeObjectProps > = { } ) { }
260292
261293 geometries : Array < BufferGeometry > = [ ]
262- materials : Array < Material > = [ ]
263- meshes : Array < Object3D > = [ ]
294+ materials : Array < Material | Array < Material > > = [ ]
295+ meshes : Array < Object3D | GLTF > = [ ]
296+ textures : Array < WMLThreeTexturesProps > = [ ]
264297
298+ get regularMeshes ( ) { return this . meshes as Array < Object3D > }
299+ get gltfMeshes ( ) { return this . meshes as Array < GLTF > }
265300
266301}
267302
@@ -270,7 +305,7 @@ export class WMLCommonThreeObjectProps extends WMLThreeObjectProps {
270305 constructor ( props : Partial < WMLCommonThreeObjectProps > = { } ) { super ( props ) }
271306 wmlInit ( ) {
272307
273- if ( ! this . mesh ) {
308+ if ( ! this . mesh && this . textures . length === 0 ) {
274309 this . mesh = new Mesh ( this . geometry , this . material )
275310 }
276311 }
@@ -281,53 +316,69 @@ export class WMLCommonThreeObjectProps extends WMLThreeObjectProps {
281316 }
282317
283318 get material ( ) { return this . materials [ 0 ] }
284- set material ( material : Material ) { this . materials [ 0 ] = material }
319+ set material ( material : Material | Array < Material > ) { this . materials [ 0 ] = material }
285320
286321 get mesh ( ) { return this . meshes [ 0 ] }
287- set mesh ( mesh : Object3D ) { this . meshes [ 0 ] = mesh }
322+ set mesh ( mesh : Object3D | GLTF ) { this . meshes [ 0 ] = mesh }
288323
289- toggleCastShadow = ( val ?:boolean ) => {
290- this . mesh . castShadow = val ?? ! this . mesh . castShadow
291- }
324+ get regularMesh ( ) { return this . meshes [ 0 ] as Object3D }
325+ set regularMesh ( mesh : Object3D ) { this . meshes [ 0 ] = mesh }
326+
327+ get gltfMesh ( ) { return this . meshes [ 0 ] as GLTF }
328+ set gltfMesh ( mesh : GLTF ) { this . meshes [ 0 ] = mesh }
329+
330+ get texture ( ) { return this . textures [ 0 ] }
331+ set texture ( texture : WMLThreeTexturesProps ) { this . textures [ 0 ] = texture }
292332
293- toggleReceiveShadow = ( val ?:boolean ) => {
294- this . mesh . receiveShadow = val ?? ! this . mesh . receiveShadow
295- }
296333
297- toggleShadow = ( val ?:boolean ) => {
298- this . mesh . castShadow = val ?? ! this . mesh . castShadow
299- this . mesh . receiveShadow = val ?? ! this . mesh . receiveShadow
334+ toggleShadow = ( props : { cast ?:boolean , receive ?:boolean } ) => {
335+
336+ this . regularMesh . castShadow = props . cast ?? ! this . regularMesh . castShadow
337+ this . regularMesh . receiveShadow = props . receive ?? ! this . regularMesh . receiveShadow
338+
300339 }
340+
341+ loadTexture = ( url :string ) => { }
342+
301343}
302344
303345
304346@WMLConstructorDecorator
305347export class WMLTHREELightProps {
306348 constructor ( params : Partial < WMLTHREELightProps > = { } ) { }
307349
308-
309350 light ! : Light
310351 addHelper = false
311352 helper ! :Object3D
312353 addShadowHelper = false
313354 shadowHelper ! :CameraHelper
314- toggleCastShadow = ( val ?:boolean ) => {
315- this . light . castShadow = val ?? ! this . light . castShadow
316- }
317355
318- toggleReceiveShadow = ( val ?:boolean ) => {
319- this . light . receiveShadow = val ?? ! this . light . receiveShadow
320- }
321356
322- toggleShadow = ( val ?:boolean ) => {
323- this . light . castShadow = val ?? ! this . light . castShadow
324- this . light . receiveShadow = val ?? ! this . light . receiveShadow
325- }
326357
358+ toggleShadow = ( props : { cast ?:boolean , receive ?:boolean } ) => {
359+ this . light . castShadow = props . cast ?? ! this . light . castShadow
360+ this . light . receiveShadow = props . receive ?? ! this . light . receiveShadow
361+ }
327362
328363 updateCamera = ( ) => {
329364 // @ts -ignore
330365 this . light . shadow ?. camera ?. updateProjectionMatrix ( ) ;
331366 this . shadowHelper ?. update ( )
332367 }
333368}
369+
370+ @WMLConstructorDecorator
371+ export class WMLThreeTexturesProps {
372+ constructor ( params : Partial < WMLThreeTexturesProps > = { } ) { }
373+
374+
375+ manager = new LoadingManager ( )
376+ group :Array < {
377+ url : string ;
378+ loader : Loader ;
379+ // TODO change to (Texture | GLTF)=>void
380+ onLoad ?: ( data : any ) => void ;
381+ onProgress ?: ( event : ProgressEvent ) => void ;
382+ onError ?: ( err : unknown ) => void ;
383+ } > = [ ]
384+ }
0 commit comments