diff --git a/packages/react-three-cannon-examples/src/demos/demo-SphereDebug.tsx b/packages/react-three-cannon-examples/src/demos/demo-SphereDebug.tsx
index 24ca3efb..8f3cc120 100644
--- a/packages/react-three-cannon-examples/src/demos/demo-SphereDebug.tsx
+++ b/packages/react-three-cannon-examples/src/demos/demo-SphereDebug.tsx
@@ -1,13 +1,17 @@
import { Debug, Physics, usePlane, useSphere } from '@react-three/cannon'
import { Canvas } from '@react-three/fiber'
-import { useState } from 'react'
+import { useRef, useState } from 'react'
+import type { Mesh } from 'three'
function ScalableBall() {
- const [ref, api] = useSphere(() => ({
- args: [1],
- mass: 1,
- position: [0, 5, 0],
- }))
+ const [ref, api] = useSphere(
+ () => ({
+ args: [1],
+ mass: 1,
+ position: [0, 5, 0],
+ }),
+ useRef
(null),
+ )
const [sleeping, setSleeping] = useState(false)
// Very quick demo to test forced sleep states. Catch ball mid-air to stop it.
@@ -30,7 +34,7 @@ function ScalableBall() {
}
function Plane() {
- const [ref] = usePlane(() => ({ rotation: [-Math.PI / 2, 0, 0], type: 'Static' }))
+ const [ref] = usePlane(() => ({ rotation: [-Math.PI / 2, 0, 0], type: 'Static' }), useRef(null))
return (
diff --git a/packages/react-three-cannon-examples/src/demos/demo-Triggers.tsx b/packages/react-three-cannon-examples/src/demos/demo-Triggers.tsx
index 2b065bc7..cfddcc44 100644
--- a/packages/react-three-cannon-examples/src/demos/demo-Triggers.tsx
+++ b/packages/react-three-cannon-examples/src/demos/demo-Triggers.tsx
@@ -2,10 +2,11 @@ import type { BoxProps, PlaneProps } from '@react-three/cannon'
import { Physics, useBox, usePlane, useSphere } from '@react-three/cannon'
import { OrbitControls } from '@react-three/drei'
import { Canvas } from '@react-three/fiber'
-import { useState } from 'react'
+import { useRef, useState } from 'react'
+import type { Mesh } from 'three'
function BoxTrigger({ args, onCollide, position }: BoxProps) {
- const [ref] = useBox(() => ({ args, isTrigger: true, onCollide, position }))
+ const [ref] = useBox(() => ({ args, isTrigger: true, onCollide, position }), useRef(null))
return (
@@ -15,11 +16,14 @@ function BoxTrigger({ args, onCollide, position }: BoxProps) {
}
function Ball() {
- const [ref] = useSphere(() => ({
- args: [1],
- mass: 1,
- position: [0, 10, 0],
- }))
+ const [ref] = useSphere(
+ () => ({
+ args: [1],
+ mass: 1,
+ position: [0, 10, 0],
+ }),
+ useRef(null),
+ )
return (
@@ -29,7 +33,7 @@ function Ball() {
}
function Plane(props: PlaneProps) {
- const [ref] = usePlane(() => ({ type: 'Static', ...props }))
+ const [ref] = usePlane(() => ({ type: 'Static', ...props }), useRef(null))
return (
diff --git a/packages/react-three-cannon-examples/src/demos/demo-Trimesh.tsx b/packages/react-three-cannon-examples/src/demos/demo-Trimesh.tsx
index 5df3df7b..f2f2d89c 100644
--- a/packages/react-three-cannon-examples/src/demos/demo-Trimesh.tsx
+++ b/packages/react-three-cannon-examples/src/demos/demo-Trimesh.tsx
@@ -2,7 +2,7 @@ import type { SphereProps, TrimeshProps } from '@react-three/cannon'
import { Physics, useSphere, useTrimesh } from '@react-three/cannon'
import { OrbitControls, TorusKnot, useGLTF } from '@react-three/drei'
import { Canvas, invalidate } from '@react-three/fiber'
-import { useEffect, useState } from 'react'
+import { useEffect, useRef, useState } from 'react'
import type { BufferGeometry, Mesh } from 'three'
import type { GLTF } from 'three-stdlib/loaders/GLTFLoader'
import create from 'zustand'
@@ -40,7 +40,7 @@ function Controls() {
}
const WeirdCheerio = ({ args = [0.1], position }: Pick) => {
- const [ref] = useSphere(() => ({ args, mass: 1, position }))
+ const [ref] = useSphere(() => ({ args, mass: 1, position }), useRef(null))
const [radius] = args
return (
@@ -65,11 +65,14 @@ const Bowl = ({ rotation }: Pick) => {
const [hovered, setHover] = useState(false)
const { isPaused } = useStore()
- const [ref] = useTrimesh(() => ({
- args: [vertices, indices],
- mass: 0,
- rotation,
- }))
+ const [ref] = useTrimesh(
+ () => ({
+ args: [vertices, indices],
+ mass: 0,
+ rotation,
+ }),
+ useRef(null),
+ )
useEffect(() => {
if (!isPaused) invalidate()
diff --git a/packages/react-three-cannon-examples/src/styles.ts b/packages/react-three-cannon-examples/src/styles.ts
index c491d8bd..02e45ed1 100644
--- a/packages/react-three-cannon-examples/src/styles.ts
+++ b/packages/react-three-cannon-examples/src/styles.ts
@@ -1,6 +1,6 @@
import styled, { createGlobalStyle } from 'styled-components'
-const Page = styled.div`
+export const PageStyle = styled.div`
position: relative;
width: 100%;
height: 100vh;
@@ -29,7 +29,7 @@ const Page = styled.div`
}
`
-const Global = createGlobalStyle`
+export const GlobalStyle = createGlobalStyle`
* {
box-sizing: border-box;
}
@@ -63,5 +63,3 @@ const Global = createGlobalStyle`
background: #171720;
}
`
-
-export { Global, Page }
diff --git a/packages/react-three-cannon/CHANGELOG.md b/packages/react-three-cannon/CHANGELOG.md
index ad37447d..b7fa20d0 100644
--- a/packages/react-three-cannon/CHANGELOG.md
+++ b/packages/react-three-cannon/CHANGELOG.md
@@ -1,5 +1,13 @@
# @react-three/cannon Changelog
+## v6.3.0 - 2022-04-18
+
+- DebugProvider explicitly lists children as a prop (@bjornstar)
+- Prefer PropsWithChildren over FC (@bjornstar)
+- Prefer function declarations over const (@bjornstar)
+- [`hooks`] All hooks are now generic, they accept any Object3D and return refs of whatever type was passed in (@bjornstar)
+- Update @types/react to v18 (@bjornstar)
+
## v6.2.0 - 2022-04-08
- Add scaleOverride (@bjornstar)
diff --git a/packages/react-three-cannon/package.json b/packages/react-three-cannon/package.json
index 05227323..89970140 100644
--- a/packages/react-three-cannon/package.json
+++ b/packages/react-three-cannon/package.json
@@ -1,6 +1,6 @@
{
"name": "@react-three/cannon",
- "version": "6.2.0",
+ "version": "6.3.0",
"description": "physics based hooks for react-three-fiber",
"keywords": [
"cannon",
@@ -42,7 +42,7 @@
"@babel/preset-typescript": "^7.16.7",
"@rollup/plugin-babel": "^5.3.1",
"@rollup/plugin-node-resolve": "^13.1.3",
- "@types/react": "^17.0.43",
+ "@types/react": "^18.0.5",
"@types/three": "^0.139.0",
"@typescript-eslint/eslint-plugin": "^5.17.0",
"@typescript-eslint/parser": "^5.17.0",
diff --git a/packages/react-three-cannon/src/debug-provider.tsx b/packages/react-three-cannon/src/debug-provider.tsx
index a3c82cb0..e97796fe 100644
--- a/packages/react-three-cannon/src/debug-provider.tsx
+++ b/packages/react-three-cannon/src/debug-provider.tsx
@@ -2,7 +2,7 @@ import { propsToBody } from '@pmndrs/cannon-worker-api'
import { useFrame } from '@react-three/fiber'
import type { Body, Quaternion as CQuaternion, Vec3, World } from 'cannon-es'
import CannonDebugger from 'cannon-es-debugger'
-import type { FC } from 'react'
+import type { PropsWithChildren } from 'react'
import { useMemo, useRef, useState } from 'react'
import type { Color, Object3D } from 'three'
import { InstancedMesh, Matrix4, Quaternion, Scene, Vector3 } from 'three'
@@ -32,12 +32,12 @@ const getMatrix = (o: Object3D): Matrix4 => {
return o.matrix
}
-export const DebugProvider: FC = ({
+export function DebugProvider({
children,
color = 'black',
impl = CannonDebugger,
scale = 1,
-}) => {
+}: PropsWithChildren): JSX.Element {
const [{ bodies, bodyMap }] = useState({ bodies: [], bodyMap: {} })
const { refs } = usePhysicsContext()
const [scene] = useState(() => new Scene())
diff --git a/packages/react-three-cannon/src/hooks.ts b/packages/react-three-cannon/src/hooks.ts
index 5b0ccd74..7acaba89 100644
--- a/packages/react-three-cannon/src/hooks.ts
+++ b/packages/react-three-cannon/src/hooks.ts
@@ -83,7 +83,7 @@ export type WorkerApi = {
export interface PublicApi extends WorkerApi {
at: (index: number) => WorkerApi
}
-export type Api = [RefObject, PublicApi]
+export type Api = [RefObject, PublicApi]
const temp = new Object3D()
@@ -153,13 +153,13 @@ function setupCollision(
type GetByIndex = (index: number) => T
type ArgFn = (args: T) => unknown[]
-function useBody>(
+function useBody, O extends Object3D>(
type: BodyShapeType,
fn: GetByIndex,
argsFn: ArgFn,
- fwdRef: Ref,
+ fwdRef: Ref = null,
deps: DependencyList = [],
-): Api {
+): Api {
const ref = useForwardedRef(fwdRef)
const { events, refs, scaleOverrides, subscriptions, worker } = usePhysicsContext()
@@ -169,7 +169,8 @@ function useBody>(
if (!ref.current) {
// When the reference isn't used we create a stub
// The body doesn't have a visual representation but can still be constrained
- ref.current = new Object3D()
+ // Yes, this type may be technically incorrect
+ ref.current = new Object3D() as O
}
const object = ref.current
@@ -365,35 +366,43 @@ function makeTriplet(v: Vector3 | Triplet): Triplet {
return v instanceof Vector3 ? [v.x, v.y, v.z] : v
}
-export function usePlane(fn: GetByIndex, fwdRef: Ref = null, deps?: DependencyList) {
+export function usePlane(
+ fn: GetByIndex,
+ fwdRef?: Ref,
+ deps?: DependencyList,
+) {
return useBody('Plane', fn, () => [], fwdRef, deps)
}
-export function useBox(fn: GetByIndex, fwdRef: Ref = null, deps?: DependencyList) {
+export function useBox(fn: GetByIndex, fwdRef?: Ref, deps?: DependencyList) {
const defaultBoxArgs: Triplet = [1, 1, 1]
return useBody('Box', fn, (args = defaultBoxArgs): Triplet => args, fwdRef, deps)
}
-export function useCylinder(
+export function useCylinder(
fn: GetByIndex,
- fwdRef: Ref = null,
+ fwdRef?: Ref,
deps?: DependencyList,
) {
return useBody('Cylinder', fn, (args = [] as []) => args, fwdRef, deps)
}
-export function useHeightfield(
+export function useHeightfield(
fn: GetByIndex,
- fwdRef: Ref = null,
+ fwdRef?: Ref,
deps?: DependencyList,
) {
return useBody('Heightfield', fn, (args) => args, fwdRef, deps)
}
-export function useParticle(
+export function useParticle(
fn: GetByIndex,
- fwdRef: Ref = null,
+ fwdRef?: Ref,
deps?: DependencyList,
) {
return useBody('Particle', fn, () => [], fwdRef, deps)
}
-export function useSphere(fn: GetByIndex, fwdRef: Ref = null, deps?: DependencyList) {
+export function useSphere(
+ fn: GetByIndex,
+ fwdRef?: Ref,
+ deps?: DependencyList,
+) {
return useBody(
'Sphere',
fn,
@@ -405,20 +414,20 @@ export function useSphere(fn: GetByIndex, fwdRef: Ref = n
deps,
)
}
-export function useTrimesh(
+export function useTrimesh(
fn: GetByIndex,
- fwdRef: Ref = null,
+ fwdRef?: Ref,
deps?: DependencyList,
) {
- return useBody('Trimesh', fn, (args) => args, fwdRef, deps)
+ return useBody('Trimesh', fn, (args) => args, fwdRef, deps)
}
-export function useConvexPolyhedron(
+export function useConvexPolyhedron(
fn: GetByIndex,
- fwdRef: Ref = null,
+ fwdRef?: Ref,
deps?: DependencyList,
) {
- return useBody(
+ return useBody(
'ConvexPolyhedron',
fn,
([vertices, faces, normals, axes, boundingSphereRadius] = []): ConvexPolyhedronArgs => [
@@ -432,26 +441,26 @@ export function useConvexPolyhedron(
deps,
)
}
-export function useCompoundBody(
+export function useCompoundBody(
fn: GetByIndex,
- fwdRef: Ref = null,
+ fwdRef?: Ref,
deps?: DependencyList,
) {
return useBody('Compound', fn, (args) => args as unknown[], fwdRef, deps)
}
-type ConstraintApi = [
- RefObject,
- RefObject,
+type ConstraintApi = [
+ RefObject,
+ RefObject,
{
disable: () => void
enable: () => void
},
]
-type HingeConstraintApi = [
- RefObject,
- RefObject,
+type HingeConstraintApi = [
+ RefObject,
+ RefObject,
{
disable: () => void
disableMotor: () => void
@@ -462,9 +471,9 @@ type HingeConstraintApi = [
},
]
-type SpringApi = [
- RefObject,
- RefObject,
+type SpringApi = [
+ RefObject,
+ RefObject