11import { ReactiveMap } from "@solid-primitives/map"
22import {
3- children ,
43 createEffect ,
54 createMemo ,
65 createRenderEffect ,
@@ -24,8 +23,7 @@ import {
2423 VSMShadowMap ,
2524 WebGLRenderer ,
2625} from "three"
27- import type { CanvasProps } from "./canvas.tsx"
28- import { Stack } from "./data-structure/stack.ts"
26+ import type { CanvasProps } from "./create-canvas.tsx"
2927import { frameContext , threeContext } from "./hooks.ts"
3028import { pluginContext } from "./internal-context.ts"
3129import { useProps , useSceneGraph } from "./props.ts"
@@ -38,14 +36,16 @@ import {
3836 meta ,
3937 removeElementFromArray ,
4038 useRef ,
39+ withContext ,
4140 withMultiContexts ,
4241} from "./utils.ts"
42+ import { Stack } from "./utils/stack.ts"
4343import { useMeasure } from "./utils/use-measure.ts"
4444
4545/**
4646 * Creates and manages a `solid-three` scene. It initializes necessary objects like
47- * camera, renderer, raycaster, and scene, manages the scene graph, setups up an event system
48- * and rendering loop based on the provided properties.
47+ * camera, renderer, raycaster, and scene, manages the scene graph, setups up a rendering loop
48+ * based on the provided properties.
4949 */
5050export function createThree ( canvas : HTMLCanvasElement , props : CanvasProps , plugins : Plugin [ ] ) {
5151 const canvasProps = defaultProps ( props , { frameloop : "always" } )
@@ -206,22 +206,24 @@ export function createThree(canvas: HTMLCanvasElement, props: CanvasProps, plugi
206206
207207 const raycasterStack = new Stack < Raycaster > ( "raycaster" )
208208
209+ const glProp = createMemo ( ( ) => props . gl )
209210 const gl = createMemo ( ( ) => {
210- const gl =
211- props . gl instanceof WebGLRenderer
212- ? // props.gl can be a WebGLRenderer provided by the user
213- props . gl
214- : typeof props . gl === "function"
211+ const _glProp = glProp ( )
212+ return meta (
213+ _glProp instanceof WebGLRenderer
214+ ? // _glProp can be a WebGLRenderer provided by the user
215+ _glProp
216+ : typeof _glProp === "function"
215217 ? // or a callback that returns a Renderer
216- props . gl ( canvas )
217- : // if props.gl is not defined we default to a WebGLRenderer
218- new WebGLRenderer ( { canvas } )
219-
220- return meta ( gl , {
221- get props ( ) {
222- return props . gl || { }
218+ _glProp ( canvas )
219+ : // if _glProp is not defined we default to a WebGLRenderer
220+ new WebGLRenderer ( { canvas } ) ,
221+ {
222+ get props ( ) {
223+ return glProp ( ) || { }
224+ } ,
223225 } ,
224- } )
226+ )
225227 } )
226228
227229 const measure = useMeasure ( )
@@ -297,92 +299,98 @@ export function createThree(canvas: HTMLCanvasElement, props: CanvasProps, plugi
297299 /* */
298300 /**********************************************************************************/
299301
300- withMultiContexts ( ( ) => {
301- createRenderEffect ( ( ) => {
302- if ( props . frameloop === "never" ) {
303- context . clock . stop ( )
304- context . clock . elapsedTime = 0
305- } else {
306- context . clock . start ( )
307- }
308- } )
302+ withContext (
303+ ( ) => {
304+ createRenderEffect ( ( ) => {
305+ if ( props . frameloop === "never" ) {
306+ context . clock . stop ( )
307+ context . clock . elapsedTime = 0
308+ } else {
309+ context . clock . start ( )
310+ }
311+ } )
309312
310- // Manage camera
311- createRenderEffect ( ( ) => {
312- if ( cameraStack . peek ( ) ) return
313- if ( ! props . defaultCamera || props . defaultCamera instanceof Camera ) return
314- useProps ( defaultCamera , props . defaultCamera )
315- // NOTE: Manually update camera's matrix with updateMatrixWorld is needed.
316- // Otherwise casting a ray immediately after start-up will cause the incorrect matrix to be used.
317- defaultCamera ( ) . updateMatrixWorld ( true )
318- } )
313+ // Manage camera
314+ createRenderEffect ( ( ) => {
315+ if ( cameraStack . peek ( ) ) return
316+ if ( ! props . defaultCamera || props . defaultCamera instanceof Camera ) return
317+ useProps ( defaultCamera , props . defaultCamera )
318+ // NOTE: Manually update camera's matrix with updateMatrixWorld is needed.
319+ // Otherwise casting a ray immediately after start-up will cause the incorrect matrix to be used.
320+ defaultCamera ( ) . updateMatrixWorld ( true )
321+ } )
319322
320- // Manage scene
321- createRenderEffect ( ( ) => {
322- if ( ! props . scene || props . scene instanceof Scene ) return
323- useProps ( scene , props . scene )
324- } )
323+ // Manage scene
324+ createRenderEffect ( ( ) => {
325+ if ( ! props . scene || props . scene instanceof Scene ) return
326+ useProps ( scene , props . scene )
327+ } )
325328
326- // Manage raycaster
327- createRenderEffect ( ( ) => {
328- if ( ! props . defaultRaycaster || props . defaultRaycaster instanceof Raycaster ) return
329- useProps ( defaultRaycaster , props . defaultRaycaster )
330- } )
329+ // Manage raycaster
330+ createRenderEffect ( ( ) => {
331+ if ( ! props . defaultRaycaster || props . defaultRaycaster instanceof Raycaster ) return
332+ useProps ( defaultRaycaster , props . defaultRaycaster )
333+ } )
331334
332- // Manage gl
333- createRenderEffect ( ( ) => {
334- // Set shadow-map
335+ // Manage gl
335336 createRenderEffect ( ( ) => {
336- const _gl = gl ( )
337- if ( _gl . shadowMap ) {
338- const oldEnabled = _gl . shadowMap . enabled
339- const oldType = _gl . shadowMap . type
340- _gl . shadowMap . enabled = ! ! props . shadows
341-
342- if ( typeof props . shadows === "boolean" ) {
343- _gl . shadowMap . type = PCFSoftShadowMap
344- } else if ( typeof props . shadows === "string" ) {
345- const types = {
346- basic : BasicShadowMap ,
347- percentage : PCFShadowMap ,
348- soft : PCFSoftShadowMap ,
349- variance : VSMShadowMap ,
337+ // Set shadow-map
338+ createRenderEffect ( ( ) => {
339+ const _gl = gl ( )
340+
341+ if ( _gl . shadowMap ) {
342+ const oldEnabled = _gl . shadowMap . enabled
343+ const oldType = _gl . shadowMap . type
344+ _gl . shadowMap . enabled = ! ! props . shadows
345+
346+ if ( typeof props . shadows === "boolean" ) {
347+ _gl . shadowMap . type = PCFSoftShadowMap
348+ } else if ( typeof props . shadows === "string" ) {
349+ const types = {
350+ basic : BasicShadowMap ,
351+ percentage : PCFShadowMap ,
352+ soft : PCFSoftShadowMap ,
353+ variance : VSMShadowMap ,
354+ }
355+ _gl . shadowMap . type = types [ props . shadows ] ?? PCFSoftShadowMap
356+ } else if ( typeof props . shadows === "object" ) {
357+ Object . assign ( _gl . shadowMap , props . shadows )
350358 }
351- _gl . shadowMap . type = types [ props . shadows ] ?? PCFSoftShadowMap
352- } else if ( typeof props . shadows === "object" ) {
353- Object . assign ( _gl . shadowMap , props . shadows )
359+
360+ if ( oldEnabled !== _gl . shadowMap . enabled || oldType !== _gl . shadowMap . type )
361+ _gl . shadowMap . needsUpdate = true
354362 }
363+ } )
355364
356- if ( oldEnabled !== _gl . shadowMap . enabled || oldType !== _gl . shadowMap . type )
357- _gl . shadowMap . needsUpdate = true
358- }
359- } )
365+ createEffect ( ( ) => {
366+ const renderer = gl ( )
367+ // Connect to xr if property exists
368+ if ( renderer . xr ) context . xr . connect ( )
369+ } )
360370
361- createEffect ( ( ) => {
362- const renderer = gl ( )
363- // Connect to xr if property exists
364- if ( renderer . xr ) context . xr . connect ( )
365- } )
371+ // Set color space and tonemapping preferences
372+ const LinearEncoding = 3000
373+ const sRGBEncoding = 3001
374+ // Color management and tone-mapping
375+ useProps ( gl , {
376+ get outputEncoding ( ) {
377+ return props . linear ? LinearEncoding : sRGBEncoding
378+ } ,
379+ get toneMapping ( ) {
380+ return props . flat ? NoToneMapping : ACESFilmicToneMapping
381+ } ,
382+ } )
366383
367- // Set color space and tonemapping preferences
368- const LinearEncoding = 3000
369- const sRGBEncoding = 3001
370- // Color management and tone-mapping
371- useProps ( gl , {
372- get outputEncoding ( ) {
373- return props . linear ? LinearEncoding : sRGBEncoding
374- } ,
375- get toneMapping ( ) {
376- return props . flat ? NoToneMapping : ACESFilmicToneMapping
377- } ,
384+ // Manage props
385+ const _glProp = glProp ( )
386+ if ( _glProp && ! ( _glProp instanceof WebGLRenderer ) ) {
387+ useProps ( gl , _glProp )
388+ }
378389 } )
379-
380- // Manage props
381- if ( props . gl && ! ( props . gl instanceof WebGLRenderer ) ) {
382- useProps ( gl , props . gl )
383- }
384- } )
385- } , [ [ threeContext , context ] ] )
390+ } ,
391+ threeContext ,
392+ context ,
393+ )
386394
387395 /**********************************************************************************/
388396 /* */
@@ -408,20 +416,16 @@ export function createThree(canvas: HTMLCanvasElement, props: CanvasProps, plugi
408416 /* */
409417 /**********************************************************************************/
410418
411- const c = children ( ( ) => (
412- < pluginContext . Provider value = { plugins } >
413- < frameContext . Provider value = { addFrameListener } >
414- < threeContext . Provider value = { context } > { canvasProps . children } </ threeContext . Provider >
415- </ frameContext . Provider >
416- </ pluginContext . Provider >
417- ) )
418-
419419 useSceneGraph (
420420 context . scene ,
421421 mergeProps ( props , {
422- get children ( ) {
423- return c ( )
424- } ,
422+ children : (
423+ < pluginContext . Provider value = { plugins } >
424+ < frameContext . Provider value = { addFrameListener } >
425+ < threeContext . Provider value = { context } > { canvasProps . children } </ threeContext . Provider >
426+ </ frameContext . Provider >
427+ </ pluginContext . Provider >
428+ ) ,
425429 } ) ,
426430 )
427431
0 commit comments