@@ -406,34 +406,40 @@ const App = () => {
406406
407407### Resource
408408
409- Declarative component for loading Three.js resources with automatic caching and Suspense integration. When no children are provided, the loaded resource is automatically rendered with any additional props passed through .
409+ Wrapper- component around [ 'useLoader' ] ( #useloader ) .
410410
411411** Props:**
412412
413413- ` loader ` - Three.js loader constructor (e.g., ` TextureLoader ` , ` GLTFLoader ` )
414- - ` url ` - URL(s) to load (string, array, or object)
414+ - ` url ` - URL(s) to load, depending on what the passed loader expects
415415- ` children ` - Optional render function
416416- ` * ` - Additional props are passed to the loaded resource
417417
418418** Examples:**
419419
420420``` tsx
421- // Automatic attachment with the attach prop
421+ // CubeTextureLoader expects an array of strings
422+ <Resource loader = { CubeTextureLoader } url = { [
423+ ' px.png' , ' nx.png' ,
424+ ' py.png' , ' ny.png' ,
425+ ' pz.png' , ' nz.png'
426+ ]} />
427+
428+ // Set props of the resulting resource
422429<T.MeshStandardMaterial >
423430 <Resource loader = { TextureLoader } url = " diffuse.jpg" attach = " map" />
424431 <Resource loader = { TextureLoader } url = " normal.jpg" attach = " normalMap" />
425432</T.MeshStandardMaterial >
426433
427- // Automatic model rendering with transform props
428- <Resource loader = { GLTFLoader } url = " model.gltf" scale = { 2 } position = { [0 , 1 , 0 ]} />
429-
430434// Custom rendering with children function
431- <Resource loader = { TextureLoader } url = " texture.jpg" >
432- { texture => <T.MeshBasicMaterial map = { texture ()} />}
435+ <Resource loader = { GLTFLoader } url = " model.gltf" >
436+ {
437+ (gltf ) => <Entity from = { gltf .scene } scale = { 2 } />
438+ }
433439</Resource >
434440
435441// Disable caching for specific resources
436- <Resource loader = { TextureLoader } url = " dynamic.jpg " cache = { false } />
442+ <Resource loader = { TextureLoader } url = " / dynamic-texture.png " cache = { false } />
437443```
438444
439445## Hooks
@@ -466,27 +472,24 @@ Provides access to the `three.js` context, including the renderer, scene, camera
466472- ** Default at Tail** : The ` defaultCamera ` and ` defaultRaycaster ` from Canvas props form the tail of their respective stacks
467473- ** Current Active Camera at Head** : The camera/raycaster at the top of the stack is the currently active camera/raycaster
468474- ** Push To The Stack To Become Active** : By calling ` setCamera(camera) ` and ` setRaycaster(raycaster) ` , the camera/raycaster is pushed to the stack. This causes it to become the currently active camera/raycaster
469- - ** Easily Pop From The Stack** : ` setCamera(camera) ` and ` setRaycaster(raycaster) ` return a function to pop the camera/raycaster from the stack. If the camera/raycaster was on top of the stack, the previous camera/raycaster in the stack becomes active again
475+ - ** Pop From The Stack To Deactivate ** : ` setCamera(camera) ` and ` setRaycaster(raycaster) ` return a cleanup- function to pop the camera/raycaster from the stack. If the camera/raycaster was on top of the stack, the previous camera/raycaster in the stack becomes active again
470476
471477** Usage:**
472478
473479``` tsx
474- const three = useThree ()
475-
476- // Push a new camera onto the stack
477- const restoreCamera = three .setCamera (myCustomCamera )
480+ function Camera(props ) {
481+ const three = useThree ()
482+ const customCamera = new OrthographicCamera (/* ... */ )
478483
479- // The custom camera is now active
480- // When done, call the cleanup to restore previous camera
481- restoreCamera ()
484+ // Push a new camera onto the stack
485+ const restoreCamera = three .setCamera (customCamera )
482486
483- // Example with automatic cleanup
484- createEffect (() => {
485- const customCamera = new OrthographicCamera (/* ... */ )
486- const restore = three .setCamera (customCamera )
487+ // The custom camera is now active
488+ // When done, call the cleanup to pop camera from the stack
489+ onCleanup (restoreCamera )
487490
488- onCleanup ( restore ) // Automatically restore previous camera when effect re-runs or unmounts
489- })
491+ return null !
492+ }
490493```
491494
492495** Practical Example - Camera Switching:**
@@ -593,39 +596,14 @@ const AnimatedMesh = () => {
593596
594597Manages asynchronous resource loading, such as textures or models, and integrates with ` solid-js ` ' reactivity system. This hook can be used with Solid's ` <Suspense> ` to handle loading states.
595598
596- ** Caching Behavior:**
597-
598- By default, ` useLoader ` automatically caches resources using the built-in [ ` LoaderCache ` ] ( #loadercache ) implementation. This means:
599-
600- - Resources are only loaded once and shared across components
601- - Automatic reference counting tracks resource usage
602- - Resources are added to a freelist when not referenced
603- - Each loader type maintains its own isolated namespace
599+ By default, ` useLoader ` automatically caches resources via [ ` LoaderCache ` ] ( #loadercache ) .
604600
605601You can customize caching behavior:
606602
6076031 . ** Disable caching** : Pass ` cache: false ` in options for specific resources
6086042 . ** Custom cache** : Pass your own ` LoaderRegistry ` implementation in options
6096053 . ** Replace global cache** : Set ` useLoader.cache ` to your own implementation or ` undefined ` to disable
610606
611- ** Usage:**
612-
613- ``` tsx
614- // Load a single resource
615- const texture = useLoader (TextureLoader , url )
616- const gltf = useLoader (GLTFLoader , " model.gltf" )
617-
618- // Load multiple resources (with object keys)
619- const textures = useLoader (TextureLoader , {
620- diffuse: " wood-diffuse.jpg" ,
621- normal: " wood-normal.jpg" ,
622- })
623-
624- // Reactive URLs (can be signals or getters)
625- const [url, setUrl] = createSignal (" texture.jpg" )
626- const texture = useLoader (TextureLoader , url )
627- ```
628-
629607** Options:**
630608
631609- ** base** : Base URL for resolving relative paths
@@ -647,91 +625,27 @@ interface UseLoaderOptions<TLoader, TResult> {
647625
648626</details >
649627
650- #### Single Resource Loading
628+ #### Example
651629
652630``` tsx
653- import { createSignal , Suspense } from " solid-js"
654- import { Canvas , useLoader , createT } from " solid-three"
655- import { TextureLoader } from " three"
656- import * as THREE from " three"
657-
658- const T = createT ({
659- Mesh: THREE .Mesh ,
660- SphereGeometry: THREE .SphereGeometry ,
661- MeshBasicMaterial: THREE .MeshBasicMaterial ,
662- })
663-
664- const TexturedSphere = () => {
665- const [url, setUrl] = createSignal (" path/to/texture.jpg" )
666- const texture = useLoader (TextureLoader , url )
667-
668- return (
669- <T.Mesh onClick = { () => setUrl (" path/to/other/texture.jpg" )} >
670- <T.SphereGeometry args = { [1 , 32 , 32 ]} />
671- <T.MeshBasicMaterial map = { texture ()} />
672- </T.Mesh >
673- )
674- }
675-
676- const App = () => {
677- return (
678- <Canvas >
679- <Suspense fallback = { <div >Loading...</div >} >
680- <TexturedSphere />
681- </Suspense >
682- </Canvas >
683- )
684- }
685- ```
686-
687- #### Multiple Resource Loading
688-
689- ``` tsx
690- import { For , Suspense } from " solid-js"
691- import { Canvas , useLoader , createT } from " solid-three"
692- import { TextureLoader } from " three"
693- import * as THREE from " three"
631+ // Load a single resource
632+ const texture = useLoader (TextureLoader , url )
633+ const gltf = useLoader (GLTFLoader , " model.gltf" )
694634
695- const T = createT ({
696- Mesh: THREE . Mesh ,
697- PlaneGeometry: THREE . PlaneGeometry ,
698- MeshBasicMaterial: THREE . MeshBasicMaterial ,
635+ // Load multiple resources (with object keys)
636+ const textures = useLoader ( TextureLoader , {
637+ diffuse: " wood-diffuse.jpg " ,
638+ normal: " wood-normal.jpg " ,
699639})
700640
701- const TexturedPlanes = () => {
702- const textures = useLoader (TextureLoader , {
703- wood: " /textures/wood.jpg" ,
704- metal: " /textures/metal.jpg" ,
705- })
706-
707- return (
708- <>
709- <T.Mesh position = { [0 , 0 , 0 ]} >
710- <T.PlaneGeometry args = { [2 , 2 ]} />
711- <T.MeshBasicMaterial map = { textures ()?.wood } />
712- </T.Mesh >
713- <T.Mesh position = { [0 , 0 , 0 ]} >
714- <T.PlaneGeometry args = { [2 , 2 ]} />
715- <T.MeshBasicMaterial map = { textures ()?.metal } />
716- </T.Mesh >
717- </>
718- )
719- }
720-
721- const App = () => {
722- return (
723- <Canvas >
724- <Suspense >
725- <TexturedPlanes />
726- </Suspense >
727- </Canvas >
728- )
729- }
641+ // Reactive URLs (can be signals or getters)
642+ const [url, setUrl] = createSignal (" texture.jpg" )
643+ const texture = useLoader (TextureLoader , url )
730644```
731645
732- #### Caching
646+ #### Custom Cache
733647
734- ` solid-three ` provides the ` LoaderCache ` class for caching , but you can also implement your own cache by conforming to the ` LoaderRegistry ` interface.
648+ ` solid-three ` by default caches useLoader via ` LoaderCache ` , but you can also implement your own cache by conforming to the ` LoaderRegistry ` interface.
735649
736650A cache registry needs two methods:
737651
@@ -743,106 +657,22 @@ A cache registry needs two methods:
743657
744658``` tsx
745659interface LoaderRegistry {
746- set<TData extends object , TUrl extends string | string [] >(
747- loader : Loader < TData , TUrl > ,
748- url : TUrl ,
749- data : Promise < TData >,
660+ set<TLoader extends Loader < object , any > >(
661+ loader : TLoader ,
662+ url : LoaderUrl < TLoader > ,
663+ data : PromiseMaybe < LoaderData < TLoader > >,
750664 ): void
751665
752- get<TData extends object , TUrl extends string | string [] >(
666+ get<TLoader extends Loader < object , any > >(
753667 loader : Loader <TData , TUrl >,
754- url : TUrl ,
668+ url : LoaderUrl < TLoader > ,
755669 warn ? : boolean ,
756- ): Promise < TData > | TData | undefined
670+ ): PromiseMaybe < LoaderData < TLoader >> | undefined
757671}
758672```
759673
760674</details >
761675
762- ** Working with the Default Cache:**
763-
764- ` useLoader ` comes with caching enabled by default using ` LoaderCache ` :
765-
766- ``` tsx
767- import { useLoader } from " solid-three"
768-
769- // Resources are automatically cached
770- const texture1 = useLoader (TextureLoader , " texture1.jpg" ) // Loaded and cached
771- const texture2 = useLoader (TextureLoader , " texture1.jpg" ) // Returns cached version
772-
773- // Disable caching for specific resources
774- const texture3 = useLoader (TextureLoader , " texture2.jpg" , {
775- cache: false , // This resource won't be cached
776- })
777-
778- // Use a different cache for specific calls
779- import { LoaderCache } from " solid-three"
780-
781- const customCache = new LoaderCache ()
782- const texture4 = useLoader (TextureLoader , " texture3.jpg" , {
783- cache: customCache , // Uses custom cache instead of global
784- })
785-
786- // Replace or disable the global cache
787- useLoader .cache = new LoaderCache () // Replace with new instance
788- useLoader .cache = undefined // Disable global caching entirely
789- ```
790-
791- ** Creating a simple custom cache:**
792-
793- ``` tsx
794- import type { LoaderRegistry } from " solid-three"
795- import type { Loader } from " three"
796-
797- class SimpleCache implements LoaderRegistry {
798- private cache = new Map <Loader <any , any >, Map <string , any >>()
799-
800- set(loader : Loader <any , any >, url : string | string [], data : Promise <any >) {
801- let loaderCache = this .cache .get (loader )
802- if (! loaderCache ) {
803- loaderCache = new Map ()
804- this .cache .set (loader , loaderCache )
805- }
806- const key = Array .isArray (url ) ? url .join (" ," ) : url
807- loaderCache .set (key , data )
808- }
809-
810- get(loader : Loader <any , any >, url : string | string []) {
811- const loaderCache = this .cache .get (loader )
812- if (! loaderCache ) return undefined
813-
814- const key = Array .isArray (url ) ? url .join (" ," ) : url
815- return loaderCache .get (key )
816- }
817- }
818-
819- // Use your custom cache
820- const myCache = new SimpleCache ()
821- useLoader .cache = myCache
822-
823- // Or per-call
824- const texture = useLoader (TextureLoader , url , { cache: myCache })
825- ```
826-
827- ** Advanced Usage with Multiple Loaders:**
828-
829- ``` tsx
830- import { useLoader } from " solid-three"
831- import { TextureLoader , GLTFLoader , AudioLoader } from " three"
832-
833- // The default LoaderCache handles multiple loader types automatically
834- const App = () => {
835- // These all use the same cache but different namespaces
836- const texture = useLoader (TextureLoader , " asset.jpg" )
837- const model = useLoader (GLTFLoader , " asset.gltf" )
838- const sound = useLoader (AudioLoader , " asset.mp3" )
839-
840- // Same path but different loader = different resource
841- const textureAsset = useLoader (TextureLoader , " shared-name" )
842- const modelAsset = useLoader (GLTFLoader , " shared-name" ) // Different resource
843- }
844- ```
845-
846676### useProps
847677
848678The ` useProps ` hook manages and applies ` solid-three ` props to THREE.js objects. It sets up reactive effects to ensure properties are correctly applied and updated, manages children attachment, and handles automatic disposal.
0 commit comments