|
26 | 26 | - [useThree](#usethree) |
27 | 27 | - [useFrame](#useframe) |
28 | 28 | - [useLoader](#useloader) |
| 29 | + - [useProps](#useprops) |
29 | 30 | 5. [Utilities](#utilities) |
30 | 31 | - [autodispose](#autodispose) |
31 | 32 | 6. [Event Handling](#event-handling) |
|
37 | 38 | - [Hover Events](#hover-events) |
38 | 39 | 7. [TypeScript Support](#typescript-support) |
39 | 40 | 8. [Performance Optimization](#performance-optimization) |
40 | | -9. [API Reference](#api-reference) |
41 | | -10. [Differences from React-Three-Fiber](#differences-from-react-three-fiber) |
42 | | -11. [Contributing](#contributing) |
43 | | -12. [License](#license) |
| 41 | +9. [Differences from React-Three-Fiber](#differences-from-react-three-fiber) |
| 42 | +10. [Contributing](#contributing) |
| 43 | +11. [License](#license) |
44 | 44 |
|
45 | 45 | ## Installation |
46 | 46 |
|
@@ -501,6 +501,74 @@ export const App = () => { |
501 | 501 | } |
502 | 502 | ``` |
503 | 503 |
|
| 504 | +### useProps |
| 505 | + |
| 506 | +The `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. |
| 507 | + |
| 508 | +**Signature:** |
| 509 | + |
| 510 | +```tsx |
| 511 | +function useProps<T extends object>(object: Accessor<T>, props: any): void |
| 512 | +``` |
| 513 | + |
| 514 | +**Parameters:** |
| 515 | + |
| 516 | +- **object** (`Accessor<T>`): An accessor function that returns the target THREE.js object |
| 517 | +- **props** (`any`): Object containing props to apply (including `ref`, `children`, and THREE.js properties) |
| 518 | + |
| 519 | +**Usage:** |
| 520 | + |
| 521 | +This hook is primarily used internally by `solid-three` components, but can be useful when creating custom components or integrating existing THREE.js objects: |
| 522 | + |
| 523 | +```tsx |
| 524 | +import { createSignal } from "solid-js" |
| 525 | +import { useProps } from "solid-three" |
| 526 | +import { Mesh, BoxGeometry, MeshBasicMaterial } from "three" |
| 527 | +
|
| 528 | +const CustomMesh = props => { |
| 529 | + const mesh = new Mesh(new BoxGeometry(), new MeshBasicMaterial()) |
| 530 | +
|
| 531 | + // Apply solid-three props reactively to the mesh |
| 532 | + useProps(() => mesh, props) |
| 533 | +
|
| 534 | + return mesh // Return the THREE.js object for use in JSX |
| 535 | +} |
| 536 | +
|
| 537 | +// Usage |
| 538 | +;<CustomMesh position={[1, 2, 3]} rotation={[0, Math.PI, 0]} color="red" /> |
| 539 | +``` |
| 540 | + |
| 541 | +**What it handles:** |
| 542 | + |
| 543 | +- **Reactive prop updates**: Automatically applies prop changes to the THREE.js object |
| 544 | +- **Ref assignment**: Handles both function refs and object refs |
| 545 | +- **Children management**: Attaches/detaches child objects from the scene graph |
| 546 | +- **Automatic disposal**: Cleans up the object when the component unmounts |
| 547 | +- **Special props**: Processes `onUpdate` callbacks after prop applications |
| 548 | + |
| 549 | +**Advanced usage:** |
| 550 | + |
| 551 | +```tsx |
| 552 | +import { createMemo, createRenderEffect, onCleanup } from "solid-js" |
| 553 | +import { useProps, useThree } from "solid-three" |
| 554 | +import { Mesh, SphereGeometry, MeshStandardMaterial } from "three" |
| 555 | +
|
| 556 | +export function OrbitControls(props: S3.Props<typeof ThreeOrbitControls>) { |
| 557 | + const three = useThree() |
| 558 | + const controls = createMemo<ThreeOrbitControls>(previous => { |
| 559 | + const controls = autodispose(new ThreeOrbitControls(three.camera)) |
| 560 | + controls.connect(three.gl.domElement) |
| 561 | + return controls |
| 562 | + }) |
| 563 | +
|
| 564 | + useFrame(() => controls().update()) |
| 565 | +
|
| 566 | + useProps(controls, rest) |
| 567 | +
|
| 568 | + return null! |
| 569 | +} |
| 570 | +``` |
| 571 | + |
504 | 572 | ## Utilities |
505 | 573 |
|
506 | 574 | ### autodispose |
@@ -548,24 +616,18 @@ function ConditionalMesh() { |
548 | 616 |
|
549 | 617 | `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. |
550 | 618 |
|
551 | | -### Controlling Raycasting with pointerEvents |
| 619 | +### Controlling Raycasting with raycastable |
552 | 620 |
|
553 | | -The `pointerEvents` prop controls whether an Object3D can be targeted by raycasting: |
| 621 | +The `raycastable` prop controls whether an Object3D can be targeted by raycasting: |
554 | 622 |
|
555 | | -- **pointerEvents** (`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`. |
| 623 | +- **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`. |
556 | 624 |
|
557 | 625 | ```tsx |
558 | | -// Object won't be hit by rays but children can still be interactive |
559 | | -<T.Group pointerEvents={false}> |
560 | | - <T.Mesh onClick={() => console.log("Child clicked!")}> |
561 | | - <T.BoxGeometry /> |
562 | | - <T.MeshBasicMaterial /> |
563 | | - </T.Mesh> |
564 | | -</T.Group> |
| 626 | +<T.Mesh name="parent" raycastable={false} onClick={() => console.log("Child clicked!")}> |
| 627 | + <T.Mesh name="child" /> |
| 628 | +</T.Mesh> |
565 | 629 | ``` |
566 | 630 |
|
567 | | -This is useful for creating invisible containers or optimizing performance by excluding objects from raycasting calculations. |
568 | | - |
569 | 631 | ### Supported Events |
570 | 632 |
|
571 | 633 | - `onClick` - Fired when clicking on an object |
@@ -804,108 +866,6 @@ solid-three's hover event handling differs from react-three-fiber in several key |
804 | 866 | - **react-three-fiber**: When moving from child to parent, the parent receives both leave and immediate re-enter events |
805 | 867 | </details> |
806 | 868 |
|
807 | | -## TypeScript Support |
808 | | - |
809 | | -`solid-three` provides comprehensive TypeScript support through the `S3` namespace, which contains all type definitions for working with `three.js` in a type-safe manner. |
810 | | - |
811 | | -### Core Types |
812 | | - |
813 | | -```tsx |
814 | | -import type { S3 } from "solid-three" |
815 | | -import type * as THREE from "three" |
816 | | -
|
817 | | -// Component types |
818 | | -type MeshComponent = S3.Component<THREE.Mesh> |
819 | | -type BoxProps = S3.Props<THREE.BoxGeometry> |
820 | | -
|
821 | | -// Instance types - `three.js` objects augmented with solid-three metadata |
822 | | -type AugmentedMesh = S3.Instance<THREE.Mesh> |
823 | | -
|
824 | | -// Generic Three instance |
825 | | -type AnyInstance = S3.ThreeInstance |
826 | | -
|
827 | | -// Camera types |
828 | | -type Camera = S3.CameraType // PerspectiveCamera | OrthographicCamera |
829 | | -``` |
830 | | - |
831 | | -### Props Types |
832 | | - |
833 | | -```tsx |
834 | | -import type { S3 } from "solid-three" |
835 | | -
|
836 | | -// Get props type for a specific `three.js` class |
837 | | -type MeshProps = S3.Props<THREE.Mesh> |
838 | | -type MaterialProps = S3.Props<THREE.MeshStandardMaterial> |
839 | | -
|
840 | | -// Using in components |
841 | | -const MyMesh = (props: MeshProps) => { |
842 | | - return <T.Mesh {...props} /> |
843 | | -} |
844 | | -``` |
845 | | - |
846 | | -### Event Types |
847 | | - |
848 | | -```tsx |
849 | | -// Event handler types |
850 | | -type ClickHandler = S3.EventHandlers["onClick"] |
851 | | -type PointerHandler = S3.EventHandlers["onPointerMove"] |
852 | | -
|
853 | | -// Event object type |
854 | | -const handleClick: ClickHandler = (event: S3.Event<MouseEvent>) => { |
855 | | - console.log(event.point) // Vector3 |
856 | | - console.log(event.distance) // number |
857 | | - event.stopPropagation() |
858 | | -} |
859 | | -
|
860 | | -// All event names |
861 | | -type EventName = S3.EventName // "onClick" | "onPointerMove" | ... |
862 | | -``` |
863 | | - |
864 | | -### Representation Types |
865 | | - |
866 | | -These types represent how `three.js` objects can be specified in props: |
867 | | - |
868 | | -```tsx |
869 | | -// Vector representations - can be arrays or `three.js` objects |
870 | | -type Position = S3.Vector3 // [x, y, z] | Vector3 | { x, y, z } |
871 | | -type Scale = S3.Vector3 |
872 | | -
|
873 | | -// Color representation |
874 | | -type Color = S3.Color // string | number | Color | [r, g, b] |
875 | | -
|
876 | | -// Rotation representations |
877 | | -type Rotation = S3.Euler // [x, y, z] | Euler |
878 | | -type Quaternion = S3.Quaternion // [x, y, z, w] | Quaternion |
879 | | -
|
880 | | -// Other representations |
881 | | -type Layers = S3.Layers // number | Layers |
882 | | -type Matrix = S3.Matrix4 // number[] | Matrix4 |
883 | | -``` |
884 | | - |
885 | | -### Context Type |
886 | | - |
887 | | -```tsx |
888 | | -// The full context returned by useThree |
889 | | -type Context = S3.Context |
890 | | -
|
891 | | -const MyComponent = () => { |
892 | | - const context: Context = useThree() |
893 | | -
|
894 | | - // All properties are properly typed |
895 | | - context.camera // Camera |
896 | | - context.gl // WebGLRenderer |
897 | | - context.pointer // Vector2 |
898 | | - // ... etc |
899 | | -} |
900 | | -``` |
901 | | - |
902 | | -### Metadata Type |
903 | | - |
904 | | -```tsx |
905 | | -// Access instance metadata |
906 | | -type Metadata = S3.Metadata<Mesh> |
907 | | -``` |
908 | | - |
909 | 869 | ## Performance Optimization |
910 | 870 |
|
911 | 871 | `solid-three` provides several mechanisms to optimize rendering performance: |
@@ -947,6 +907,8 @@ const ManualDisposal = () => { |
947 | 907 | } |
948 | 908 | ``` |
949 | 909 |
|
| 910 | +or use the [`autodispose()`-utility](#autodispose) |
| 911 | + |
950 | 912 | ### Frame Loop Control |
951 | 913 |
|
952 | 914 | Use the `frameloop` prop on Canvas to control when rendering occurs: |
@@ -1108,21 +1070,6 @@ While `solid-three` is heavily inspired by– and initially shared a lot of code |
1108 | 1070 |
|
1109 | 1071 | We welcome contributions! Please see our [Contributing Guide](CONTRIBUTION.md) for details on how to get started. |
1110 | 1072 |
|
1111 | | -### Dev Container |
1112 | | - |
1113 | | -If you are using VSCode on windows (or just prefer to develope in a container), you can use the included dev container to get started quickly. |
1114 | | - |
1115 | | -1. Clone this repo to a directory _inside of your wsl instance_ such as `~/Github` |
1116 | | -2. Navigate to the `solid-three` directory and run `code .` |
1117 | | -3. Open the workspace from the provided file. |
1118 | | -4. Make sure the [DevContainers](https://marketplace.visualstudio.com/items?itemName=ms-vscode-remote.remote-containers) extension is installed Click the bottom left corner of the window and select `Reopen in Container` - if the extension is installed, vscode should prompt you to open the project in a dev container when you open the workspace file. |
1119 | | - |
1120 | | -#### Dev Container Notes |
1121 | | - |
1122 | | -- We clone into the `wsl` instance because the dev container is running a linux container, and the windows filesystem will cause extreme performance loss due to IO overhead. |
1123 | | -- If you are using a different shell, you may need to modify the `devcontainer.json` file to use your shell of choice. |
1124 | | -- A port will automatically be forwarded when you run the project in dev mode, so you can access the dev server from your browser on windows at `localhost:<port>` - the port will be displayed in the terminal when you run the project. This can be configured by you as well. |
1125 | | - |
1126 | 1073 | ## License |
1127 | 1074 |
|
1128 | 1075 | `solid-three` is [MIT licensed](LICENSE). |
0 commit comments