Skip to content

Commit 7866353

Browse files
committed
docs: tweak LoaderCache-section and add to utilities
1 parent 95d16fa commit 7866353

1 file changed

Lines changed: 82 additions & 94 deletions

File tree

README.md

Lines changed: 82 additions & 94 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
- [useProps](#useprops)
3030
5. [Utilities](#utilities)
3131
- [Raycasters](#raycasters)
32+
- [LoaderCache](#loadercache)
3233
- [autodispose](#autodispose)
3334
- [Metadata Utilities](#metadata-utilities)
3435
- [Testing Utilities](#testing-utilities)
@@ -408,6 +409,7 @@ const App = () => {
408409
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.
409410

410411
**Props:**
412+
411413
- `loader` - Three.js loader constructor (e.g., `TextureLoader`, `GLTFLoader`)
412414
- `url` - URL(s) to load (string, array, or object)
413415
- `children` - Optional render function
@@ -822,82 +824,6 @@ useLoader.cache = myCache
822824
const texture = useLoader(TextureLoader, url, { cache: myCache })
823825
```
824826

825-
### LoaderCache
826-
827-
`LoaderCache` is the built-in implementation of the `LoaderRegistry` interface that `solid-three` exports. It's automatically set as the default cache for `useLoader`, providing a sophisticated caching system with automatic memory management for Three.js loader resources.
828-
829-
**Features:**
830-
831-
- **Automatic Reference Counting**: Tracks how many components are using each resource
832-
- **Solid.js Integration**: Automatically decrements reference counts when components unmount
833-
- **Deferred Disposal**: Resources are added to a "free list" when no longer referenced
834-
- **Memory Management**: Call `emptyFreeList()` to dispose of unused resources
835-
- **Multi-Loader Support**: Each Three.js loader gets its own isolated cache namespace
836-
- **Path-based Storage**: Hierarchical storage using paths for efficient lookups
837-
838-
**Basic Usage:**
839-
840-
```tsx
841-
import { LoaderCache } from "solid-three"
842-
843-
// Create a cache instance
844-
const cache = new LoaderCache()
845-
846-
// Store a resource
847-
const texturePromise = textureLoader.loadAsync("wood.jpg")
848-
cache.set(textureLoader, "wood.jpg", texturePromise)
849-
850-
// Retrieve a resource (automatically tracked in reactive contexts)
851-
const texture = cache.get(textureLoader, "wood.jpg")
852-
```
853-
854-
**Memory Management:**
855-
856-
```tsx
857-
const cache = new LoaderCache()
858-
859-
// Resources with zero references are added to the free list
860-
// They are not immediately disposed to allow for re-use
861-
862-
// Periodically clean up unused resources
863-
setInterval(() => {
864-
cache.emptyFreeList()
865-
}, 60000) // Every minute
866-
867-
// Force delete a specific resource
868-
cache.deleteResource(texture, { force: true })
869-
870-
// Delete by loader and path
871-
cache.delete(textureLoader, "wood.jpg", { force: true })
872-
```
873-
874-
**Reference Counting Example:**
875-
876-
```tsx
877-
const TexturedBox = () => {
878-
// This increments the reference count for 'texture.jpg'
879-
const texture = useLoader(TextureLoader, "texture.jpg")
880-
881-
// When this component unmounts, the reference count decreases
882-
// If it reaches zero, the texture is added to the free list
883-
return (
884-
<T.Mesh>
885-
<T.BoxGeometry />
886-
<T.MeshBasicMaterial map={texture()} />
887-
</T.Mesh>
888-
)
889-
}
890-
891-
// Multiple components can share the same cached resource
892-
const Scene = () => (
893-
<>
894-
<TexturedBox /> {/* ref count: 1 */}
895-
<TexturedBox /> {/* ref count: 2 */}
896-
<TexturedBox /> {/* ref count: 3 */}
897-
</>
898-
)
899-
```
900-
901827
**Advanced Usage with Multiple Loaders:**
902828

903829
```tsx
@@ -1086,6 +1012,68 @@ const App = () => {
10861012
}
10871013
```
10881014

1015+
### LoaderCache
1016+
1017+
`LoaderCache` is the default cache-manager for `useLoader`. It implements the `LoaderRegistry` interface and adds additional methods to simplify managing the cached resources.
1018+
1019+
**Features:**
1020+
1021+
- **Automatic Reference Counting**: Tracks if a resource is currently actively in-use
1022+
- **Deferred Disposal**: Resources are added to a free list when no longer referenced
1023+
- **Disposal Methods**: Several methods to ease managing disposal of resources
1024+
- **dispose(loader, path)**: dispose a resource based on loader and path
1025+
- **disposeResource(resource)**: dispose a resource by passing the resource directly
1026+
- **disposeFreeList()**: dispose all currently not referenced resources
1027+
1028+
**Example:**
1029+
1030+
```tsx
1031+
const TexturedBox = () => {
1032+
// This increments the reference count for 'texture.jpg'
1033+
const texture = useLoader(TextureLoader, "texture.jpg")
1034+
1035+
// When this component unmounts, the reference count decreases
1036+
// If it reaches zero, the texture is added to the free list
1037+
return (
1038+
<T.Mesh>
1039+
<T.BoxGeometry />
1040+
<T.MeshBasicMaterial map={texture()} />
1041+
</T.Mesh>
1042+
)
1043+
}
1044+
1045+
// Multiple components can share the same cached resource
1046+
const Scene = () => (
1047+
<>
1048+
<TexturedBox /> {/* ref count: 1 */}
1049+
<TexturedBox /> {/* ref count: 2 */}
1050+
<TexturedBox /> {/* ref count: 3 */}
1051+
</>
1052+
)
1053+
1054+
const App = () => {
1055+
const [visible, setVisible] = createSignal(true)
1056+
1057+
onMount(() => {
1058+
// ❌ Texture will not be disposed because it is referenced (3 times)
1059+
useLoader.cache.disposeFreeList()
1060+
1061+
setVisible(false)
1062+
1063+
// ✅ Texture will be disposed because it is not referenced anymore
1064+
useLoader.cache.disposeFreeList()
1065+
})
1066+
1067+
return (
1068+
<Canvas>
1069+
<Show when={visible}>
1070+
<Scene />
1071+
</Show>
1072+
</Canvas>
1073+
)
1074+
}
1075+
```
1076+
10891077
### autodispose
10901078

10911079
The `autodispose` utility ensures that three.js objects are properly disposed on cleanup.
@@ -1112,7 +1100,7 @@ import { Show, createSignal } from "solid-js"
11121100
import { Entity, autodispose } from "solid-three"
11131101
import { Mesh, BoxGeometry, MeshBasicMaterial } from "three"
11141102

1115-
function ConditionalMesh() {
1103+
function StrobeMesh() {
11161104
const [visible, setVisible] = createSignal(true)
11171105

11181106
// These will be disposed when ConditionalMesh unmounts
@@ -1171,23 +1159,7 @@ const MyTest = () => {
11711159

11721160
## Event Handling
11731161

1174-
`solid-three` provides a comprehensive event system that integrates `three.js` pointer and mouse events with `solid-js`' reactivity. Events are automatically handled through raycasting and support stopping propagation.
1175-
1176-
### Controlling Raycasting with raycastable
1177-
1178-
The `raycastable` prop controls whether an Object3D can be targeted by raycasting:
1179-
1180-
- **raycastable** (`boolean`): When set to `false`, the object will not be hit by rays, but can still receive events through propagation from its descendants. Default is `true`.
1181-
1182-
```tsx
1183-
const RaycastableMesh = () => {
1184-
return (
1185-
<T.Mesh name="parent" raycastable={false} onClick={() => console.log("Child clicked!")}>
1186-
<T.Mesh name="child" />
1187-
</T.Mesh>
1188-
)
1189-
}
1190-
```
1162+
`solid-three` provides a custom event system inspired by [`react-three-fiber`](https://github.com/pmndrs/react-three-fiber). Events are automatically handled through raycasting and support DOM-like propagation.
11911163

11921164
### Supported Events
11931165

@@ -1413,6 +1385,22 @@ solid-three's hover event handling differs from react-three-fiber in several key
14131385
- **react-three-fiber**: When moving from child to parent, the parent receives both leave and immediate re-enter events
14141386
</details>
14151387

1388+
### Controlling Raycasting with raycastable
1389+
1390+
The `raycastable` prop controls whether an Object3D can be targeted by raycasting:
1391+
1392+
- **raycastable** (`boolean`): When set to `false`, the object will not be hit by rays, but can still receive events through propagation from its descendants. Default is `true`.
1393+
1394+
```tsx
1395+
const RaycastableMesh = () => {
1396+
return (
1397+
<T.Mesh name="parent" raycastable={false} onClick={() => console.log("Child clicked!")}>
1398+
<T.Mesh name="child" />
1399+
</T.Mesh>
1400+
)
1401+
}
1402+
```
1403+
14161404
## Performance Optimization
14171405

14181406
`solid-three` provides several mechanisms to optimize rendering performance:

0 commit comments

Comments
 (0)