diff --git a/CHANGELOG.md b/CHANGELOG.md index fad6cf71..e0ab1a69 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,10 @@ # @pmndrs/use-cannon Changelog +## v2.3.0 - 2022-04-18 + +- [@react-three/cannon] v6.3.0 +- [@react-three/cannon-examples] v2.3.0 + ## v2.2.0 - 2022-04-08 - [@react-three/cannon] v6.2.0 diff --git a/package.json b/package.json index 88464712..87155bb7 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@pmndrs/use-cannon", - "version": "2.2.0", + "version": "2.3.0", "description": "monorepo for @pmndrs/use-cannon", "keywords": [ "cannon", diff --git a/packages/react-three-cannon-examples/CHANGELOG.md b/packages/react-three-cannon-examples/CHANGELOG.md index d8e192f7..02f21c0e 100644 --- a/packages/react-three-cannon-examples/CHANGELOG.md +++ b/packages/react-three-cannon-examples/CHANGELOG.md @@ -1,5 +1,13 @@ # @react-three/cannon-examples Changelog +## v2.3.0 - 2022-04-18 + +- Use accurate ref types for all hooks (@bjornstar) +- Prefer `PropsWithChildren` to `FC` (@bjornstar) +- Update `@types/react` to v18 (@bjornstar) +- Update `@react-three/drei` & `@react-three/fiber` (@bjornstar) +- Update `styled-components` (@bjornstar) + ## v2.2.0 - 2022-04-08 - Use `react-dom/client` for react 18 features diff --git a/packages/react-three-cannon-examples/package.json b/packages/react-three-cannon-examples/package.json index 848bd6dc..70c648e5 100755 --- a/packages/react-three-cannon-examples/package.json +++ b/packages/react-three-cannon-examples/package.json @@ -1,6 +1,6 @@ { "name": "@react-three/cannon-examples", - "version": "2.2.0", + "version": "2.3.0", "description": "Examples for @react-three/cannon", "private": true, "scripts": { @@ -21,13 +21,13 @@ ], "devDependencies": { "@react-three/cannon": "^6.2.0", - "@react-three/drei": "^9.0.1", - "@react-three/fiber": "^8.0.4", + "@react-three/drei": "^9.4.3", + "@react-three/fiber": "^8.0.11", "@types/lodash-es": "^4.17.6", - "@types/react": "^17.0.43", + "@types/react": "^18.0.5", "@types/react-dom": "^17.0.14", "@types/react-router-dom": "^5.3.3", - "@types/styled-components": "^5.1.24", + "@types/styled-components": "^5.1.25", "@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-examples/src/App.tsx b/packages/react-three-cannon-examples/src/App.tsx index 66bafc72..d9d4c09c 100644 --- a/packages/react-three-cannon-examples/src/App.tsx +++ b/packages/react-three-cannon-examples/src/App.tsx @@ -3,10 +3,9 @@ import { HashRouter as Router, Link, Route, Routes, useMatch } from 'react-route import styled from 'styled-components' import { demoList, demos, isDemo } from './demos' -import { Global } from './styles' -import { Page as PageImpl } from './styles' +import { GlobalStyle, PageStyle } from './styles' -const Page = styled(PageImpl)` +const Page = styled(PageStyle)` padding: 0px; & > h1 { @@ -71,7 +70,8 @@ function Demos() { export default function App() { return ( - + {/* @ts-expect-error Not sure how to fix the type here */} + ) diff --git a/packages/react-three-cannon-examples/src/demos/MondayMorning/index.tsx b/packages/react-three-cannon-examples/src/demos/MondayMorning/index.tsx index 4b8b8686..2cbb6be2 100644 --- a/packages/react-three-cannon-examples/src/demos/MondayMorning/index.tsx +++ b/packages/react-three-cannon-examples/src/demos/MondayMorning/index.tsx @@ -9,9 +9,14 @@ import { usePointToPointConstraint, useSphere, } from '@react-three/cannon' -import type { BoxBufferGeometryProps, MeshProps, MeshStandardMaterialProps } from '@react-three/fiber' +import type { + BoxBufferGeometryProps, + MeshProps, + MeshStandardMaterialProps, + ThreeEvent, +} from '@react-three/fiber' import { Canvas, useFrame, useLoader } from '@react-three/fiber' -import type { FC, ReactNode, RefObject } from 'react' +import type { ReactNode, RefObject } from 'react' import { createContext, createRef, @@ -23,7 +28,7 @@ import { useMemo, useRef, } from 'react' -import type { Material, Mesh, Object3D } from 'three' +import type { Group, Material, Mesh, Object3D, SpotLight } from 'three' import type { GLTF } from 'three-stdlib/loaders/GLTFLoader' import { GLTFLoader } from 'three-stdlib/loaders/GLTFLoader' @@ -32,7 +37,7 @@ import { createRagdoll } from './createConfig' const { joints, shapes } = createRagdoll(4.8, Math.PI / 16, Math.PI / 16, 0) const context = createContext>(createRef()) -const cursor = createRef() +const cursor = createRef() const double = ([x, y, z]: Readonly): Triplet => [x * 2, y * 2, z * 2] @@ -40,8 +45,9 @@ function useDragConstraint(child: RefObject) { const [, , api] = usePointToPointConstraint(cursor, child, { pivotA: [0, 0, 0], pivotB: [0, 0, 0] }) // TODO: make it so we can start the constraint with it disabled useEffect(() => void api.disable(), []) - const onPointerDown = useCallback((e) => { + const onPointerDown = useCallback((e: ThreeEvent) => { e.stopPropagation() + //@ts-expect-error Investigate proper types here. e.target.setPointerCapture(e.pointerId) api.enable() }, []) @@ -53,7 +59,7 @@ type BoxProps = Omit & Pick & Pick -const Box = forwardRef( +const Box = forwardRef( ({ args = [1, 1, 1], children, color = 'white', opacity = 1, transparent = false, ...props }, ref) => { return ( @@ -71,11 +77,14 @@ type BodyPartProps = BoxProps & { render?: ReactNode } -const BodyPart: FC = ({ children, config = {}, name, render, ...props }) => { +function BodyPart({ children, config = {}, name, render, ...props }: BodyPartProps): JSX.Element { const { color, args, mass, position } = shapes[name] const scale = useMemo(() => double(args), [args]) const parent = useContext(context) - const [ref] = useBox(() => ({ args: [...args], linearDamping: 0.99, mass, position: [...position] })) + const [ref] = useBox( + () => ({ args: [...args], linearDamping: 0.99, mass, position: [...position] }), + useRef(null), + ) useConeTwistConstraint(ref, parent, config) const bind = useDragConstraint(ref) return ( @@ -89,8 +98,8 @@ const BodyPart: FC = ({ children, config = {}, name, render, ...p } function Ragdoll(props: Pick) { - const mouth = useRef(null) - const eyes = useRef(null) + const mouth = useRef(null) + const eyes = useRef(null) useFrame(({ clock }) => { if (!eyes.current || !mouth.current) return @@ -151,7 +160,7 @@ function Ragdoll(props: Pick) { } function Plane(props: PlaneProps) { - const [ref] = usePlane(() => ({ ...props })) + const [ref] = usePlane(() => ({ ...props }), useRef(null)) return ( @@ -161,19 +170,22 @@ function Plane(props: PlaneProps) { } function Chair() { - const [ref] = useCompoundBody(() => ({ - mass: 1, - position: [-6, 0, 0], - shapes: [ - { args: [1.5, 1.5, 0.25], mass: 1, position: [0, 0, 0], type: 'Box' }, - { args: [1.5, 0.25, 1.5], mass: 1, position: [0, -1.75, 1.25], type: 'Box' }, - { args: [0.25, 1.5, 0.25], mass: 10, position: [5 + -6.25, -3.5, 0], type: 'Box' }, - { args: [0.25, 1.5, 0.25], mass: 10, position: [5 + -3.75, -3.5, 0], type: 'Box' }, - { args: [0.25, 1.5, 0.25], mass: 10, position: [5 + -6.25, -3.5, 2.5], type: 'Box' }, - { args: [0.25, 1.5, 0.25], mass: 10, position: [5 + -3.75, -3.5, 2.5], type: 'Box' }, - ], - type: 'Dynamic', - })) + const [ref] = useCompoundBody( + () => ({ + mass: 1, + position: [-6, 0, 0], + shapes: [ + { args: [1.5, 1.5, 0.25], mass: 1, position: [0, 0, 0], type: 'Box' }, + { args: [1.5, 0.25, 1.5], mass: 1, position: [0, -1.75, 1.25], type: 'Box' }, + { args: [0.25, 1.5, 0.25], mass: 10, position: [5 + -6.25, -3.5, 0], type: 'Box' }, + { args: [0.25, 1.5, 0.25], mass: 10, position: [5 + -3.75, -3.5, 0], type: 'Box' }, + { args: [0.25, 1.5, 0.25], mass: 10, position: [5 + -6.25, -3.5, 2.5], type: 'Box' }, + { args: [0.25, 1.5, 0.25], mass: 10, position: [5 + -3.75, -3.5, 2.5], type: 'Box' }, + ], + type: 'Dynamic', + }), + useRef(null), + ) const bind = useDragConstraint(ref) return ( @@ -200,12 +212,15 @@ interface CupGLTF extends GLTF { function Mug() { const { nodes, materials } = useLoader(GLTFLoader, '/cup.glb') as CupGLTF - const [ref] = useCylinder(() => ({ - args: [0.6, 0.6, 1, 16], - mass: 1, - position: [9, 0, 0], - rotation: [Math.PI / 2, 0, 0], - })) + const [ref] = useCylinder( + () => ({ + args: [0.6, 0.6, 1, 16], + mass: 1, + position: [9, 0, 0], + rotation: [Math.PI / 2, 0, 0], + }), + useRef(null), + ) const bind = useDragConstraint(ref) return ( @@ -228,11 +243,26 @@ function Mug() { } function Table() { - const [seat] = useBox(() => ({ args: [2.5, 0.25, 2.5], position: [9, -0.8, 0], type: 'Static' })) - const [leg1] = useBox(() => ({ args: [0.25, 2, 0.25], position: [7.2, -3, 1.8], type: 'Static' })) - const [leg2] = useBox(() => ({ args: [0.25, 2, 0.25], position: [10.8, -3, 1.8], type: 'Static' })) - const [leg3] = useBox(() => ({ args: [0.25, 2, 0.25], position: [7.2, -3, -1.8], type: 'Static' })) - const [leg4] = useBox(() => ({ args: [0.25, 2, 0.25], position: [10.8, -3, -1.8], type: 'Static' })) + const [seat] = useBox( + () => ({ args: [2.5, 0.25, 2.5], position: [9, -0.8, 0], type: 'Static' }), + useRef(null), + ) + const [leg1] = useBox( + () => ({ args: [0.25, 2, 0.25], position: [7.2, -3, 1.8], type: 'Static' }), + useRef(null), + ) + const [leg2] = useBox( + () => ({ args: [0.25, 2, 0.25], position: [10.8, -3, 1.8], type: 'Static' }), + useRef(null), + ) + const [leg3] = useBox( + () => ({ args: [0.25, 2, 0.25], position: [7.2, -3, -1.8], type: 'Static' }), + useRef(null), + ) + const [leg4] = useBox( + () => ({ args: [0.25, 2, 0.25], position: [10.8, -3, -1.8], type: 'Static' }), + useRef(null), + ) return ( <> @@ -248,15 +278,18 @@ function Table() { } const Lamp = () => { - const light = useRef() - const [fixed] = useSphere(() => ({ args: [1], position: [0, 16, 0], type: 'Static' })) - const [lamp] = useBox(() => ({ - angulardamping: 1.99, - args: [1, 0, 5], - linearDamping: 0.9, - mass: 1, - position: [0, 16, 0], - })) + const light = useRef(null) + const [fixed] = useSphere(() => ({ args: [1], position: [0, 16, 0], type: 'Static' }), useRef(null)) + const [lamp] = useBox( + () => ({ + angulardamping: 1.99, + args: [1, 0, 5], + linearDamping: 0.9, + mass: 1, + position: [0, 16, 0], + }), + useRef(null), + ) usePointToPointConstraint(fixed, lamp, { pivotA: [0, 0, 0], pivotB: [0, 2, 0] }) const bind = useDragConstraint(lamp) return ( diff --git a/packages/react-three-cannon-examples/src/demos/Pingpong/Text.tsx b/packages/react-three-cannon-examples/src/demos/Pingpong/Text.tsx index 0aaa6e41..27d0a49d 100644 --- a/packages/react-three-cannon-examples/src/demos/Pingpong/Text.tsx +++ b/packages/react-three-cannon-examples/src/demos/Pingpong/Text.tsx @@ -1,6 +1,5 @@ import type { GroupProps } from '@react-three/fiber' -import { forwardRef, useMemo } from 'react' -import type { Object3D } from 'three' +import { useMemo } from 'react' import { TextGeometry } from 'three/examples/jsm/geometries/TextGeometry' import { FontLoader } from 'three/examples/jsm/loaders/FontLoader' @@ -16,10 +15,10 @@ type TextProps = GroupProps & { count: string } -const Text = forwardRef(({ color = 'white', count, ...props }, ref) => { +export default function Text({ color = 'white', count, ...props }: TextProps): JSX.Element { const array = useMemo(() => [...count], [count]) return ( - + {array.map((char, index) => ( (({ color = 'white', count, ...props ))} ) -}) - -export default Text +} diff --git a/packages/react-three-cannon-examples/src/demos/Pingpong/index.tsx b/packages/react-three-cannon-examples/src/demos/Pingpong/index.tsx index 8ea44de2..a5760d1f 100644 --- a/packages/react-three-cannon-examples/src/demos/Pingpong/index.tsx +++ b/packages/react-three-cannon-examples/src/demos/Pingpong/index.tsx @@ -3,7 +3,7 @@ import { Canvas, useFrame, useLoader } from '@react-three/fiber' import lerp from 'lerp' import clamp from 'lodash-es/clamp' import { Suspense, useRef } from 'react' -import type { Loader, Material, Mesh, Object3D, Skeleton } from 'three' +import type { Group, Loader, Material, Mesh, Object3D, Skeleton } from 'three' import { TextureLoader } from 'three' import { DRACOLoader } from 'three-stdlib/loaders/DRACOLoader' import type { GLTF } from 'three-stdlib/loaders/GLTFLoader' @@ -61,12 +61,15 @@ function Paddle() { const { pong } = useStore((state) => state.api) const welcome = useStore((state) => state.welcome) const count = useStore((state) => state.count) - const model = useRef(null) - const [ref, api] = useBox(() => ({ - args: [3.4, 1, 3], - onCollide: (e) => pong(e.contact.impactVelocity), - type: 'Kinematic', - })) + const model = useRef(null) + const [ref, api] = useBox( + () => ({ + args: [3.4, 1, 3], + onCollide: (e) => pong(e.contact.impactVelocity), + type: 'Kinematic', + }), + useRef(null), + ) const values = useRef([0, 0]) useFrame((state) => { values.current[0] = lerp(values.current[0], (state.mouse.x * Math.PI) / 5, 0.2) @@ -110,7 +113,7 @@ function Paddle() { function Ball() { const map = useLoader(TextureLoader, earthImg) - const [ref] = useSphere(() => ({ args: [0.5], mass: 1, position: [0, 5, 0] })) + const [ref] = useSphere(() => ({ args: [0.5], mass: 1, position: [0, 5, 0] }), useRef(null)) return ( @@ -121,12 +124,15 @@ function Ball() { function ContactGround() { const { reset } = useStore((state) => state.api) - const [ref] = usePlane(() => ({ - onCollide: () => reset(true), - position: [0, -10, 0], - rotation: [-Math.PI / 2, 0, 0], - type: 'Static', - })) + const [ref] = usePlane( + () => ({ + onCollide: () => reset(true), + position: [0, -10, 0], + rotation: [-Math.PI / 2, 0, 0], + type: 'Static', + }), + useRef(null), + ) return } diff --git a/packages/react-three-cannon-examples/src/demos/Raycast/index.tsx b/packages/react-three-cannon-examples/src/demos/Raycast/index.tsx index 69dec668..aa2f7f24 100644 --- a/packages/react-three-cannon-examples/src/demos/Raycast/index.tsx +++ b/packages/react-three-cannon-examples/src/demos/Raycast/index.tsx @@ -4,7 +4,7 @@ import { Html } from '@react-three/drei' import type { GroupProps, Node, Object3DNode } from '@react-three/fiber' import { Canvas, extend, useFrame, useThree } from '@react-three/fiber' import { Suspense, useLayoutEffect, useMemo, useRef, useState } from 'react' -import type { PerspectiveCamera } from 'three' +import type { Mesh, PerspectiveCamera } from 'three' import { BufferGeometry, Line as ThreeLine, Vector3 } from 'three' import { OrbitControls } from 'three-stdlib/controls/OrbitControls' @@ -43,7 +43,7 @@ type SphereProps = { } function Sphere({ radius, position }: SphereProps) { - const [ref, api] = useSphere(() => ({ args: [radius], position, type: 'Static' })) + const [ref, api] = useSphere(() => ({ args: [radius], position, type: 'Static' }), useRef(null)) useFrame(({ clock: { elapsedTime } }) => { api.position.set(position[0], position[1], Math.sin(elapsedTime / 3) * 2) }) @@ -61,7 +61,7 @@ type CubeProps = { } function Cube({ size, position }: CubeProps) { - const [ref, api] = useBox(() => ({ args: size, position, type: 'Static' })) + const [ref, api] = useBox(() => ({ args: size, position, type: 'Static' }), useRef(null)) useFrame(({ clock: { elapsedTime } }) => { api.position.set(Math.sin(elapsedTime / 2) * 2, position[1], position[2]) }) diff --git a/packages/react-three-cannon-examples/src/demos/RaycastVehicle/Chassis.tsx b/packages/react-three-cannon-examples/src/demos/RaycastVehicle/Chassis.tsx index 58a877c7..5610eb3e 100644 --- a/packages/react-three-cannon-examples/src/demos/RaycastVehicle/Chassis.tsx +++ b/packages/react-three-cannon-examples/src/demos/RaycastVehicle/Chassis.tsx @@ -1,6 +1,6 @@ import { useGLTF } from '@react-three/drei' import { forwardRef } from 'react' -import type { Material, Mesh, Object3D } from 'three' +import type { Material, Mesh } from 'three' import type { GLTF } from 'three-stdlib/loaders/GLTFLoader' useGLTF.preload('/Beetle.glb') @@ -54,7 +54,7 @@ type BeetleGLTF = GLTF & { nodes: Record } -export const Chassis = forwardRef((_, ref) => { +export const Chassis = forwardRef((_, ref) => { const { nodes, materials } = useGLTF('/Beetle.glb') as BeetleGLTF return ( diff --git a/packages/react-three-cannon-examples/src/demos/RaycastVehicle/Vehicle.tsx b/packages/react-three-cannon-examples/src/demos/RaycastVehicle/Vehicle.tsx index ee20a3b8..2325accc 100644 --- a/packages/react-three-cannon-examples/src/demos/RaycastVehicle/Vehicle.tsx +++ b/packages/react-three-cannon-examples/src/demos/RaycastVehicle/Vehicle.tsx @@ -2,7 +2,7 @@ import type { BoxProps, WheelInfoOptions } from '@react-three/cannon' import { useBox, useRaycastVehicle } from '@react-three/cannon' import { useFrame } from '@react-three/fiber' import { useEffect, useRef } from 'react' -import type { Object3D } from 'three' +import type { Group, Mesh } from 'three' import { Chassis } from './Chassis' import { useControls } from './use-controls' @@ -32,13 +32,7 @@ function Vehicle({ steer = 0.5, width = 1.2, }: VehicleProps) { - const chassisBody = useRef(null) - const wheels = [ - useRef(null), - useRef(null), - useRef(null), - useRef(null), - ] + const wheels = [useRef(null), useRef(null), useRef(null), useRef(null)] const controls = useControls() @@ -78,7 +72,7 @@ function Vehicle({ isFrontWheel: false, } - const [, chassisApi] = useBox( + const [chassisBody, chassisApi] = useBox( () => ({ allowSleep: false, angularVelocity, @@ -88,14 +82,17 @@ function Vehicle({ position, rotation, }), - chassisBody, + useRef(null), ) - const [vehicle, vehicleApi] = useRaycastVehicle(() => ({ - chassisBody, - wheelInfos: [wheelInfo1, wheelInfo2, wheelInfo3, wheelInfo4], - wheels, - })) + const [vehicle, vehicleApi] = useRaycastVehicle( + () => ({ + chassisBody, + wheelInfos: [wheelInfo1, wheelInfo2, wheelInfo3, wheelInfo4], + wheels, + }), + useRef(null), + ) useEffect(() => vehicleApi.sliding.subscribe((v) => console.log('sliding', v)), []) diff --git a/packages/react-three-cannon-examples/src/demos/RaycastVehicle/Wheel.tsx b/packages/react-three-cannon-examples/src/demos/RaycastVehicle/Wheel.tsx index a9ba0a85..58e902e1 100644 --- a/packages/react-three-cannon-examples/src/demos/RaycastVehicle/Wheel.tsx +++ b/packages/react-three-cannon-examples/src/demos/RaycastVehicle/Wheel.tsx @@ -2,7 +2,7 @@ import type { CylinderProps } from '@react-three/cannon' import { useCompoundBody } from '@react-three/cannon' import { useGLTF } from '@react-three/drei' import { forwardRef } from 'react' -import type { Material, Mesh, Object3D } from 'three' +import type { Group, Material, Mesh } from 'three' import type { GLTF } from 'three-stdlib/loaders/GLTFLoader' useGLTF.preload('/wheel.glb') @@ -19,7 +19,7 @@ type WheelProps = CylinderProps & { radius: number } -export const Wheel = forwardRef(({ leftSide, radius = 0.7, ...props }, ref) => { +export const Wheel = forwardRef(({ leftSide, radius = 0.7, ...props }, ref) => { const { materials: { Chrom, Rubber, Steel }, nodes, diff --git a/packages/react-three-cannon-examples/src/demos/RaycastVehicle/index.tsx b/packages/react-three-cannon-examples/src/demos/RaycastVehicle/index.tsx index 7e24ccf1..fed423d7 100644 --- a/packages/react-three-cannon-examples/src/demos/RaycastVehicle/index.tsx +++ b/packages/react-three-cannon-examples/src/demos/RaycastVehicle/index.tsx @@ -5,13 +5,14 @@ import type { CylinderArgs, CylinderProps, PlaneProps } from '@react-three/canno import { Debug, Physics, useCylinder, usePlane } from '@react-three/cannon' import { Environment, OrbitControls } from '@react-three/drei' import { Canvas } from '@react-three/fiber' -import { Suspense } from 'react' +import { Suspense, useRef } from 'react' +import type { Group, Mesh } from 'three' import { useToggledControl } from '../../use-toggled-control' import Vehicle from './Vehicle' function Plane(props: PlaneProps) { - const [ref] = usePlane(() => ({ material: 'ground', type: 'Static', ...props })) + const [ref] = usePlane(() => ({ material: 'ground', type: 'Static', ...props }), useRef(null)) return ( @@ -24,11 +25,14 @@ function Plane(props: PlaneProps) { function Pillar(props: CylinderProps) { const args: CylinderArgs = [0.7, 0.7, 5, 16] - const [ref] = useCylinder(() => ({ - args, - mass: 10, - ...props, - })) + const [ref] = useCylinder( + () => ({ + args, + mass: 10, + ...props, + }), + useRef(null), + ) return ( diff --git a/packages/react-three-cannon-examples/src/demos/demo-Chain.tsx b/packages/react-three-cannon-examples/src/demos/demo-Chain.tsx index 3b8df316..885ac505 100644 --- a/packages/react-three-cannon-examples/src/demos/demo-Chain.tsx +++ b/packages/react-three-cannon-examples/src/demos/demo-Chain.tsx @@ -1,9 +1,9 @@ import type { CylinderArgs, Triplet } from '@react-three/cannon' import { Physics, useBox, useConeTwistConstraint, useCylinder, useSphere } from '@react-three/cannon' import { Canvas, useFrame } from '@react-three/fiber' -import type { FC } from 'react' -import { createContext, createRef, useCallback, useContext, useMemo, useState } from 'react' -import type { Object3D } from 'three' +import type { PropsWithChildren } from 'react' +import { createContext, createRef, useCallback, useContext, useMemo, useRef, useState } from 'react' +import type { Mesh, Object3D } from 'three' import { Color } from 'three' const maxMultiplierExamples = [0, 500, 1000, 1500, undefined] as const @@ -23,12 +23,12 @@ type ChainLinkProps = { maxMultiplier?: number } -const ChainLink: FC = ({ +function ChainLink({ args = [0.5, 0.5, 2, 16], children, color = 'white', maxMultiplier, -}) => { +}: PropsWithChildren): JSX.Element { const { position: [x, y, z], ref: parentRef, @@ -37,12 +37,15 @@ const ChainLink: FC = ({ const [, , height = 2] = args const position: Triplet = [x, y - height, z] - const [ref] = useCylinder(() => ({ - args, - linearDamping: 0.8, - mass: 1, - position, - })) + const [ref] = useCylinder( + () => ({ + args, + linearDamping: 0.8, + mass: 1, + position, + }), + useRef(null), + ) useConeTwistConstraint(parentRef, ref, { angle: Math.PI / 8, @@ -70,7 +73,7 @@ type ChainProps = { maxMultiplier?: number } -const Chain: FC = ({ children, length, maxMultiplier }) => { +function Chain({ children, length, maxMultiplier }: PropsWithChildren): JSX.Element { const color = useMemo(() => { if (maxMultiplier === undefined) return 'white' @@ -93,11 +96,11 @@ const Chain: FC = ({ children, length, maxMultiplier }) => { ) } -const PointerHandle: FC<{ size: number }> = ({ children, size }) => { +function PointerHandle({ children, size }: PropsWithChildren<{ size: number }>): JSX.Element { const position: Triplet = [0, 0, 0] const args: Triplet = [size, size, size * 2] - const [ref, api] = useBox(() => ({ args, position, type: 'Kinematic' })) + const [ref, api] = useBox(() => ({ args, position, type: 'Kinematic' }), useRef(null)) useFrame(({ mouse: { x, y }, viewport: { height, width } }) => { api.position.set((x * width) / 2, (y * height) / 2, 0) @@ -119,8 +122,8 @@ type StaticHandleProps = { radius: number } -const StaticHandle: FC = ({ children, position, radius }) => { - const [ref] = useSphere(() => ({ args: [radius], position, type: 'Static' })) +function StaticHandle({ children, position, radius }: PropsWithChildren): JSX.Element { + const [ref] = useSphere(() => ({ args: [radius], position, type: 'Static' }), useRef(null)) return ( @@ -140,7 +143,7 @@ const style = { top: 20, } as const -const ChainScene = () => { +function ChainScene(): JSX.Element { const [resetCount, setResetCount] = useState(0) const reset = useCallback(() => { diff --git a/packages/react-three-cannon-examples/src/demos/demo-CompoundBody.tsx b/packages/react-three-cannon-examples/src/demos/demo-CompoundBody.tsx index ee5e3839..655455a8 100644 --- a/packages/react-three-cannon-examples/src/demos/demo-CompoundBody.tsx +++ b/packages/react-three-cannon-examples/src/demos/demo-CompoundBody.tsx @@ -2,9 +2,10 @@ import type { CompoundBodyProps, PlaneProps, Triplet } from '@react-three/cannon import { Debug, Physics, useCompoundBody, usePlane } from '@react-three/cannon' import { Canvas } from '@react-three/fiber' import { useEffect, useRef, useState } from 'react' +import type { Group } from 'three' -function Plane(props: PlaneProps) { - const [ref] = usePlane(() => ({ type: 'Static', ...props })) +function Plane(props: PlaneProps): JSX.Element { + const [ref] = usePlane(() => ({ type: 'Static', ...props }), useRef(null)) return ( @@ -26,18 +27,27 @@ type OurCompoundBodyProps = Pick & { setRotation?: (rotation: Triplet) => void } -function CompoundBody({ isTrigger, mass = 12, setPosition, setRotation, ...props }: OurCompoundBodyProps) { +function CompoundBody({ + isTrigger, + mass = 12, + setPosition, + setRotation, + ...props +}: OurCompoundBodyProps): JSX.Element { const boxSize: Triplet = [1, 1, 1] const sphereRadius = 0.65 - const [ref, api] = useCompoundBody(() => ({ - isTrigger, - mass, - ...props, - shapes: [ - { args: boxSize, position: [0, 0, 0], rotation: [0, 0, 0], type: 'Box' }, - { args: [sphereRadius], position: [1, 0, 0], rotation: [0, 0, 0], type: 'Sphere' }, - ], - })) + const [ref, api] = useCompoundBody( + () => ({ + isTrigger, + mass, + ...props, + shapes: [ + { args: boxSize, position: [0, 0, 0], rotation: [0, 0, 0], type: 'Box' }, + { args: [sphereRadius], position: [1, 0, 0], rotation: [0, 0, 0], type: 'Sphere' }, + ], + }), + useRef(null), + ) useEffect(() => { if (setPosition) { @@ -65,7 +75,7 @@ function CompoundBody({ isTrigger, mass = 12, setPosition, setRotation, ...props ) } -export default function () { +export default function (): JSX.Element { const [ready, set] = useState(false) useEffect(() => { const timeout = setTimeout(() => set(true), 2000) diff --git a/packages/react-three-cannon-examples/src/demos/demo-Constraints.tsx b/packages/react-three-cannon-examples/src/demos/demo-Constraints.tsx index 68cf7e76..f7ecc5d7 100644 --- a/packages/react-three-cannon-examples/src/demos/demo-Constraints.tsx +++ b/packages/react-three-cannon-examples/src/demos/demo-Constraints.tsx @@ -2,18 +2,18 @@ import type { BoxProps, SphereProps, Triplet } from '@react-three/cannon' import { Physics, useBox, useSphere, useSpring } from '@react-three/cannon' import { Canvas, useFrame } from '@react-three/fiber' import { forwardRef, useEffect, useRef, useState } from 'react' -import type { Object3D } from 'three' +import type { Mesh } from 'three' -const Box = forwardRef((props, ref) => { +const Box = forwardRef((props, fwdRef) => { const args: Triplet = [1, 1, 1] - useBox( + const [ref] = useBox( () => ({ args, linearDamping: 0.7, mass: 1, ...props, }), - ref, + fwdRef, ) return ( @@ -23,8 +23,8 @@ const Box = forwardRef((props, ref) => { ) }) -const Ball = forwardRef((props, ref) => { - const [, { position }] = useSphere(() => ({ args: [0.5], type: 'Kinematic', ...props }), ref) +const Ball = forwardRef((props, fwdRef) => { + const [ref, { position }] = useSphere(() => ({ args: [0.5], type: 'Kinematic', ...props }), fwdRef) useFrame(({ mouse: { x, y }, viewport: { height, width } }) => position.set((x * width) / 2, (y * height) / 2, 0), ) @@ -37,9 +37,11 @@ const Ball = forwardRef((props, ref) => { }) const BoxAndBall = () => { - const box = useRef(null) - const ball = useRef(null) - const [, , api] = useSpring(box, ball, { damping: 1, restLength: 2, stiffness: 100 }) + const [box, ball, api] = useSpring(useRef(null), useRef(null), { + damping: 1, + restLength: 2, + stiffness: 100, + }) const [isDown, setIsDown] = useState(false) useEffect(() => api.setRestLength(isDown ? 0 : 2), [isDown]) diff --git a/packages/react-three-cannon-examples/src/demos/demo-ConvexPolyhedron.tsx b/packages/react-three-cannon-examples/src/demos/demo-ConvexPolyhedron.tsx index ea81d63b..5f65944a 100644 --- a/packages/react-three-cannon-examples/src/demos/demo-ConvexPolyhedron.tsx +++ b/packages/react-three-cannon-examples/src/demos/demo-ConvexPolyhedron.tsx @@ -1,7 +1,7 @@ import type { ConvexPolyhedronProps, PlaneProps } from '@react-three/cannon' import { Physics, useConvexPolyhedron, usePlane } from '@react-three/cannon' import { Canvas, useLoader } from '@react-three/fiber' -import { Suspense, useMemo, useState } from 'react' +import { Suspense, useMemo, useRef, useState } from 'react' import type { BufferGeometry, Mesh } from 'three' import { BoxGeometry, ConeGeometry } from 'three' import { Geometry } from 'three-stdlib/deprecated/Geometry' @@ -29,7 +29,7 @@ function Diamond({ position, rotation }: ConvexPolyhedronProps) { }, } = useLoader(GLTFLoader, '/diamond.glb') as DiamondGLTF const args = useMemo(() => toConvexProps(geometry), [geometry]) - const [ref] = useConvexPolyhedron(() => ({ args, mass: 100, position, rotation })) + const [ref] = useConvexPolyhedron(() => ({ args, mass: 100, position, rotation }), useRef(null)) return ( @@ -45,7 +45,7 @@ type ConeProps = Pick & { function Cone({ position, rotation, sides }: ConeProps) { const geometry = new ConeGeometry(0.7, 0.7, sides, 1) const args = useMemo(() => toConvexProps(geometry), [geometry]) - const [ref] = useConvexPolyhedron(() => ({ args, mass: 100, position, rotation })) + const [ref] = useConvexPolyhedron(() => ({ args, mass: 100, position, rotation }), useRef(null)) return ( @@ -63,7 +63,7 @@ function Cube({ position, rotation, size }: CubeProps) { // note, this is wildly inefficient vs useBox const geometry = new BoxGeometry(size, size, size) const args = useMemo(() => toConvexProps(geometry), [geometry]) - const [ref] = useConvexPolyhedron(() => ({ args, mass: 100, position, rotation })) + const [ref] = useConvexPolyhedron(() => ({ args, mass: 100, position, rotation }), useRef(null)) return ( @@ -73,7 +73,7 @@ function Cube({ position, rotation, size }: CubeProps) { } 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-CubeHeap.tsx b/packages/react-three-cannon-examples/src/demos/demo-CubeHeap.tsx index e06a0fc1..2414861f 100644 --- a/packages/react-three-cannon-examples/src/demos/demo-CubeHeap.tsx +++ b/packages/react-three-cannon-examples/src/demos/demo-CubeHeap.tsx @@ -2,11 +2,12 @@ import type { PlaneProps, Triplet } from '@react-three/cannon' import { Physics, useBox, usePlane, useSphere } from '@react-three/cannon' import { Canvas, useFrame } from '@react-three/fiber' import niceColors from 'nice-color-palettes' -import { useMemo, useState } from 'react' +import { useMemo, useRef, useState } from 'react' +import type { InstancedMesh, Mesh } from 'three' import { Color } from 'three' function Plane(props: PlaneProps) { - const [ref] = usePlane(() => ({ ...props })) + const [ref] = usePlane(() => ({ ...props }), useRef(null)) return ( @@ -22,11 +23,14 @@ type InstancedGeometryProps = { } const Spheres = ({ colors, number, size }: InstancedGeometryProps) => { - const [ref, { at }] = useSphere(() => ({ - args: [size], - mass: 1, - position: [Math.random() - 0.5, Math.random() * 2, Math.random() - 0.5], - })) + const [ref, { at }] = useSphere( + () => ({ + args: [size], + mass: 1, + position: [Math.random() - 0.5, Math.random() * 2, Math.random() - 0.5], + }), + useRef(null), + ) useFrame(() => at(Math.floor(Math.random() * number)).position.set(0, Math.random() * 2, 0)) return ( @@ -40,11 +44,14 @@ const Spheres = ({ colors, number, size }: InstancedGeometryProps) => { const Boxes = ({ colors, number, size }: InstancedGeometryProps) => { const args: Triplet = [size, size, size] - const [ref, { at }] = useBox(() => ({ - args, - mass: 1, - position: [Math.random() - 0.5, Math.random() * 2, Math.random() - 0.5], - })) + const [ref, { at }] = useBox( + () => ({ + args, + mass: 1, + position: [Math.random() - 0.5, Math.random() * 2, Math.random() - 0.5], + }), + useRef(null), + ) useFrame(() => at(Math.floor(Math.random() * number)).position.set(0, Math.random() * 2, 0)) return ( diff --git a/packages/react-three-cannon-examples/src/demos/demo-Friction.tsx b/packages/react-three-cannon-examples/src/demos/demo-Friction.tsx index 6778875f..4dfe1b12 100644 --- a/packages/react-three-cannon-examples/src/demos/demo-Friction.tsx +++ b/packages/react-three-cannon-examples/src/demos/demo-Friction.tsx @@ -2,7 +2,8 @@ import type { BoxProps, PlaneProps } from '@react-three/cannon' import { Physics, useBox, useContactMaterial, usePlane } 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' const materialColors = { bouncy: 'yellow', @@ -54,11 +55,14 @@ const slipperyMaterial = { } const Box = ({ args, color = 'white', ...props }: BoxProps & { color?: string }) => { - const [ref] = useBox(() => ({ - args, - mass: 10, - ...props, - })) + const [ref] = useBox( + () => ({ + args, + mass: 10, + ...props, + }), + useRef(null), + ) return ( @@ -68,7 +72,7 @@ const Box = ({ args, color = 'white', ...props }: BoxProps & { color?: string }) } const Plane = (props: PlaneProps) => { - const [ref] = usePlane(() => ({ ...props })) + const [ref] = usePlane(() => ({ ...props }), useRef(null)) return ( diff --git a/packages/react-three-cannon-examples/src/demos/demo-Heightfield.tsx b/packages/react-three-cannon-examples/src/demos/demo-Heightfield.tsx index e314bd70..7b65eeba 100644 --- a/packages/react-three-cannon-examples/src/demos/demo-Heightfield.tsx +++ b/packages/react-three-cannon-examples/src/demos/demo-Heightfield.tsx @@ -3,9 +3,8 @@ import { Physics, useHeightfield, useSphere } from '@react-three/cannon' import type { Node } from '@react-three/fiber' import { Canvas, extend, useFrame, useThree } from '@react-three/fiber' import niceColors from 'nice-color-palettes' -import type { FC } from 'react' import { useEffect, useLayoutEffect, useMemo, useRef } from 'react' -import type { BufferGeometry, PerspectiveCamera } from 'three' +import type { BufferGeometry, InstancedMesh, Mesh, PerspectiveCamera } from 'three' import { Color, Float32BufferAttribute } from 'three' import { OrbitControls } from 'three-stdlib/controls/OrbitControls' @@ -64,10 +63,13 @@ function generateHeightmap({ width, height, number, scale }: GenerateHeightmapAr return data } -const HeightmapGeometry: FC<{ +function HeightmapGeometry({ + elementSize, + heights, +}: { elementSize: number heights: number[][] -}> = ({ elementSize, heights }) => { +}): JSX.Element { const ref = useRef(null) useEffect(() => { @@ -99,22 +101,30 @@ const HeightmapGeometry: FC<{ return } -const Heightfield: FC<{ +function Heightfield({ + elementSize, + heights, + position, + rotation, +}: { elementSize: number heights: number[][] position: Triplet rotation: Triplet -}> = ({ elementSize, heights, position, rotation }) => { - const [ref] = useHeightfield(() => ({ - args: [ - heights, - { - elementSize, - }, - ], - position, - rotation, - })) +}): JSX.Element { + const [ref] = useHeightfield( + () => ({ + args: [ + heights, + { + elementSize, + }, + ], + position, + rotation, + }), + useRef(null), + ) return ( @@ -124,21 +134,20 @@ const Heightfield: FC<{ ) } -const Spheres: FC<{ - columns: number - rows: number - spread: number -}> = ({ columns, rows, spread }) => { +function Spheres({ columns, rows, spread }: { columns: number; rows: number; spread: number }): JSX.Element { const number = rows * columns - const [ref] = useSphere((index) => ({ - args: [0.2], - mass: 1, - position: [ - ((index % columns) - (columns - 1) / 2) * spread, - 2.0, - (Math.floor(index / columns) - (rows - 1) / 2) * spread, - ], - })) + const [ref] = useSphere( + (index) => ({ + args: [0.2], + mass: 1, + position: [ + ((index % columns) - (columns - 1) / 2) * spread, + 2.0, + (Math.floor(index / columns) - (rows - 1) / 2) * spread, + ], + }), + useRef(null), + ) const colors = useMemo(() => { const array = new Float32Array(number * 3) const color = new Color() @@ -160,7 +169,7 @@ const Spheres: FC<{ ) } -const Camera: FC = () => { +function Camera(): JSX.Element { const cameraRef = useRef(null) const controlsRef = useRef(null) const { gl, camera } = useThree() diff --git a/packages/react-three-cannon-examples/src/demos/demo-HingeMotor.tsx b/packages/react-three-cannon-examples/src/demos/demo-HingeMotor.tsx index f2278b0b..788020ed 100644 --- a/packages/react-three-cannon-examples/src/demos/demo-HingeMotor.tsx +++ b/packages/react-three-cannon-examples/src/demos/demo-HingeMotor.tsx @@ -14,7 +14,7 @@ import { useRef, useState, } from 'react' -import type { Object3D, PerspectiveCamera as Cam } from 'three' +import type { Group, Mesh, Object3D, PerspectiveCamera as Cam } from 'three' import { Vector3 } from 'three' function normalizeSize([px = 0, py = 0, pz = 0]): (scale: Triplet) => Triplet { @@ -27,7 +27,10 @@ const GROUP_BODY = 2 ** 1 type OurPlaneProps = Pick & Pick function Plane({ args, ...props }: OurPlaneProps) { - const [ref] = usePlane(() => ({ collisionFilterGroup: GROUP_GROUND, type: 'Static', ...props })) + const [ref] = usePlane( + () => ({ collisionFilterGroup: GROUP_GROUND, type: 'Static', ...props }), + useRef(null), + ) return ( @@ -54,7 +57,7 @@ type ConstraintPartProps = { } & BoxProps & BoxShapeProps -const ConstraintPart = forwardRef>( +const ConstraintPart = forwardRef>( ( { config = {}, @@ -116,7 +119,7 @@ const ConstraintPart = forwardRef & Pick -const BoxShape = forwardRef( +const BoxShape = forwardRef>( ({ args = [1, 1, 1], children, color = 'white', opacity = 1, transparent = false, ...props }, ref) => ( @@ -126,10 +129,10 @@ const BoxShape = forwardRef( ), ) -const Robot = forwardRef((_, legsLeftRef) => { +const Robot = forwardRef((_, legsLeftRef) => { const [motorSpeed, setMotorSpeed] = useState(7) - const legsRightRef = useRef(null) + const legsRightRef = useRef(null) useLockConstraint(legsRightRef, legsLeftRef, {}) @@ -146,11 +149,11 @@ type LegsProps = { delay?: number } & Pick -const Legs = forwardRef(({ bodyDepth = 0, delay = 0, motorSpeed = 7 }, bodyRef) => { - const horizontalRef = useRef(null) - const frontLegRef = useRef(null) - const frontUpperLegRef = useRef(null) - const backLegRef = useRef(null) +const Legs = forwardRef(({ bodyDepth = 0, delay = 0, motorSpeed = 7 }, bodyRef) => { + const horizontalRef = useRef(null) + const frontLegRef = useRef(null) + const frontUpperLegRef = useRef(null) + const backLegRef = useRef(null) const partDepth = 0.3 const bodyWidth = 10 const bodyHeight = 2 @@ -292,7 +295,7 @@ const v = new Vector3() function Scene() { const cameraRef = useRef(null) - const robotRef = useRef(null) + const robotRef = useRef(null) useFrame(() => { if (!cameraRef.current || !robotRef.current) return diff --git a/packages/react-three-cannon-examples/src/demos/demo-KinematicCube.tsx b/packages/react-three-cannon-examples/src/demos/demo-KinematicCube.tsx index 647dfac4..0fb95d11 100644 --- a/packages/react-three-cannon-examples/src/demos/demo-KinematicCube.tsx +++ b/packages/react-three-cannon-examples/src/demos/demo-KinematicCube.tsx @@ -3,13 +3,14 @@ import { Physics, useBox, usePlane, useSphere } from '@react-three/cannon' import type { MeshPhongMaterialProps } from '@react-three/fiber' import { Canvas, useFrame } from '@react-three/fiber' import niceColors from 'nice-color-palettes' -import { useMemo } from 'react' +import { useMemo, useRef } from 'react' +import type { InstancedMesh, Mesh } from 'three' import { Color } from 'three' type OurPlaneProps = Pick & Pick function Plane({ color, ...props }: OurPlaneProps) { - const [ref] = usePlane(() => ({ ...props })) + const [ref] = usePlane(() => ({ ...props }), useRef(null)) return ( @@ -20,7 +21,7 @@ function Plane({ color, ...props }: OurPlaneProps) { function Box() { const boxSize: Triplet = [4, 4, 4] - const [ref, api] = useBox(() => ({ args: boxSize, mass: 1, type: 'Kinematic' })) + const [ref, api] = useBox(() => ({ args: boxSize, mass: 1, type: 'Kinematic' }), useRef(null)) useFrame((state) => { const t = state.clock.getElapsedTime() api.position.set(Math.sin(t * 2) * 5, Math.cos(t * 2) * 5, 3) @@ -35,11 +36,14 @@ function Box() { } function InstancedSpheres({ number = 100 }) { - const [ref] = useSphere((index) => ({ - args: [1], - mass: 1, - position: [Math.random() - 0.5, Math.random() - 0.5, index * 2], - })) + const [ref] = useSphere( + (index) => ({ + args: [1], + mass: 1, + position: [Math.random() - 0.5, Math.random() - 0.5, index * 2], + }), + useRef(null), + ) const colors = useMemo(() => { const array = new Float32Array(number * 3) const color = new Color() diff --git a/packages/react-three-cannon-examples/src/demos/demo-Paused.tsx b/packages/react-three-cannon-examples/src/demos/demo-Paused.tsx index f238b07f..2caa6867 100644 --- a/packages/react-three-cannon-examples/src/demos/demo-Paused.tsx +++ b/packages/react-three-cannon-examples/src/demos/demo-Paused.tsx @@ -3,13 +3,13 @@ import { Debug, Physics, useBox, usePlane } from '@react-three/cannon' import { Box, OrbitControls, Plane } from '@react-three/drei' import type { MeshStandardMaterialProps } from '@react-three/fiber' import { Canvas } from '@react-three/fiber' -import type { FC } from 'react' -import { useState } from 'react' +import { useRef, useState } from 'react' +import type { Mesh } from 'three' type GroundProps = Pick & PlaneProps -const Ground: FC = ({ color, ...props }) => { - const [ref] = usePlane(() => ({ ...props })) +function Ground({ color, ...props }: GroundProps): JSX.Element { + const [ref] = usePlane(() => ({ ...props }), useRef(null)) return ( @@ -18,8 +18,8 @@ const Ground: FC = ({ color, ...props }) => { ) } -const Crate = (props: BoxProps) => { - const [ref, api] = useBox(() => ({ args: [2, 1, 1], mass: 1, ...props })) +function Crate(props: BoxProps): JSX.Element { + const [ref, api] = useBox(() => ({ args: [2, 1, 1], mass: 1, ...props }), useRef(null)) return ( { ) } -const Scene = ({ isPaused = false }) => ( - <> - +function Scene({ isPaused = false }): JSX.Element { + return ( + <> + - - - + + + - - - + + + - - - + + + - - - - - + + + + + - - -) + + + ) +} -export default () => { +export default function Paused() { const [isPaused, togglePaused] = useState(false) return (
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, { setDamping: (value: number) => void setRestLength: (value: number) => void @@ -472,17 +481,19 @@ type SpringApi = [ }, ] -type ConstraintORHingeApi = T extends ConstraintTypes - ? ConstraintApi - : HingeConstraintApi +type ConstraintORHingeApi< + T extends 'Hinge' | ConstraintTypes, + A extends Object3D, + B extends Object3D, +> = T extends ConstraintTypes ? ConstraintApi : HingeConstraintApi -function useConstraint( +function useConstraint( type: T, - bodyA: Ref, - bodyB: Ref, + bodyA: Ref, + bodyB: Ref, optns: ConstraintOptns | HingeConstraintOpts = {}, deps: DependencyList = [], -): ConstraintORHingeApi { +): ConstraintORHingeApi { const { worker } = usePhysicsContext() const uuid = MathUtils.generateUUID() @@ -519,56 +530,56 @@ function useConstraint( return enableDisable }, deps) - return [refA, refB, api] as ConstraintORHingeApi + return [refA, refB, api] as ConstraintORHingeApi } -export function usePointToPointConstraint( - bodyA: Ref = null, - bodyB: Ref = null, +export function usePointToPointConstraint( + bodyA: Ref = null, + bodyB: Ref = null, optns: PointToPointConstraintOpts, deps: DependencyList = [], ) { return useConstraint('PointToPoint', bodyA, bodyB, optns, deps) } -export function useConeTwistConstraint( - bodyA: Ref = null, - bodyB: Ref = null, +export function useConeTwistConstraint( + bodyA: Ref = null, + bodyB: Ref = null, optns: ConeTwistConstraintOpts, deps: DependencyList = [], ) { return useConstraint('ConeTwist', bodyA, bodyB, optns, deps) } -export function useDistanceConstraint( - bodyA: Ref = null, - bodyB: Ref = null, +export function useDistanceConstraint( + bodyA: Ref = null, + bodyB: Ref = null, optns: DistanceConstraintOpts, deps: DependencyList = [], ) { return useConstraint('Distance', bodyA, bodyB, optns, deps) } -export function useHingeConstraint( - bodyA: Ref = null, - bodyB: Ref = null, +export function useHingeConstraint( + bodyA: Ref = null, + bodyB: Ref = null, optns: HingeConstraintOpts, deps: DependencyList = [], ) { return useConstraint('Hinge', bodyA, bodyB, optns, deps) } -export function useLockConstraint( - bodyA: Ref = null, - bodyB: Ref = null, +export function useLockConstraint( + bodyA: Ref = null, + bodyB: Ref = null, optns: LockConstraintOpts, deps: DependencyList = [], ) { return useConstraint('Lock', bodyA, bodyB, optns, deps) } -export function useSpring( - bodyA: Ref = null, - bodyB: Ref = null, +export function useSpring( + bodyA: Ref = null, + bodyB: Ref = null, optns: SpringOptns, deps: DependencyList = [], -): SpringApi { +): SpringApi { const { worker } = usePhysicsContext() const [uuid] = useState(() => MathUtils.generateUUID()) @@ -663,11 +674,11 @@ export interface RaycastVehicleProps { wheels: Ref[] } -export function useRaycastVehicle( +export function useRaycastVehicle( fn: () => RaycastVehicleProps, - fwdRef: Ref = null, + fwdRef: Ref = null, deps: DependencyList = [], -): [RefObject, RaycastVehiclePublicApi] { +): [RefObject, RaycastVehiclePublicApi] { const ref = useForwardedRef(fwdRef) const { worker, subscriptions } = usePhysicsContext() @@ -675,7 +686,8 @@ export function useRaycastVehicle( 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 currentWorker = worker diff --git a/packages/react-three-cannon/src/physics-provider.tsx b/packages/react-three-cannon/src/physics-provider.tsx index 5fdb3a86..48071f89 100644 --- a/packages/react-three-cannon/src/physics-provider.tsx +++ b/packages/react-three-cannon/src/physics-provider.tsx @@ -9,7 +9,7 @@ import type { import { CannonWorkerAPI } from '@pmndrs/cannon-worker-api' import type { RenderCallback } from '@react-three/fiber' import { useFrame, useThree } from '@react-three/fiber' -import type { FC, PropsWithChildren } from 'react' +import type { PropsWithChildren } from 'react' import { useCallback, useEffect, useMemo, useState } from 'react' import type { Object3D } from 'three' import { InstancedMesh, Matrix4, Quaternion, Vector3 } from 'three' @@ -17,14 +17,12 @@ import { InstancedMesh, Matrix4, Quaternion, Vector3 } from 'three' import type { PhysicsContext } from './physics-context' import { physicsContext } from './physics-context' -export type PhysicsProviderProps = PropsWithChildren< - CannonWorkerProps & { - isPaused?: boolean - maxSubSteps?: number - shouldInvalidate?: boolean - stepSize?: number - } -> +export type PhysicsProviderProps = CannonWorkerProps & { + isPaused?: boolean + maxSubSteps?: number + shouldInvalidate?: boolean + stepSize?: number +} const v = new Vector3() const s = new Vector3(1, 1, 1) @@ -49,7 +47,7 @@ function apply( return m.identity() } -export const PhysicsProvider: FC = ({ +export function PhysicsProvider({ allowSleep = false, axisIndex = 0, broadphase = 'Naive', @@ -66,7 +64,7 @@ export const PhysicsProvider: FC = ({ solver = 'GS', stepSize = 1 / 60, tolerance = 0.001, -}) => { +}: PropsWithChildren): JSX.Element { const { invalidate } = useThree() const [{ bodies, events, refs, scaleOverrides, subscriptions, worker }] = useState(() => ({ diff --git a/yarn.lock b/yarn.lock index 77ea40fe..cf89e663 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1161,10 +1161,10 @@ resolved "https://registry.npmjs.org/@react-spring/types/-/types-9.4.4.tgz#97c69881788e624d7cc68d4385fdaa9b5fd20642" integrity sha512-KpxKt/D//q/t/6FBcde/RE36LKp8PpWu7kFEMLwpzMGl9RpcexunmYOQJWwmJWtkQjgE1YRr7DzBMryz6La1cQ== -"@react-three/drei@^9.0.1": - version "9.0.1" - resolved "https://registry.npmjs.org/@react-three/drei/-/drei-9.0.1.tgz#b92ddef3713269f83c20e644d5939a1cbbcd7a27" - integrity sha512-sVZP7BGiPoydihj3H2jukV3LKRHfmRjifFbQf7fxcRADy5IuCtqP+doFtIQNzaGGQT9uPS6dCSxK3t9AQ+OVtQ== +"@react-three/drei@^9.4.3": + version "9.4.3" + resolved "https://registry.npmjs.org/@react-three/drei/-/drei-9.4.3.tgz#a01fed740c9170783148e24532295ce6ae51beb6" + integrity sha512-1IQ1oSVUJ9GAQKOE1G2gzR8wo/PkkpMliE4+TVHboIUta02m8sGpDXS0ZsMu/xpA/P0hLDGOkJ4rc9sboQcSlw== dependencies: "@babel/runtime" "^7.11.2" "@react-spring/three" "^9.3.1" @@ -1184,10 +1184,10 @@ utility-types "^3.10.0" zustand "^3.5.13" -"@react-three/fiber@^8.0.4": - version "8.0.6" - resolved "https://registry.npmjs.org/@react-three/fiber/-/fiber-8.0.6.tgz#0323cedf8b888646fbd101a78e37d19d868e5979" - integrity sha512-OURPBcTw56FtL0ohmqREpW3cQB9CLzaAsIIjVUItfu4eya/lfs9dU8DJWwVXo1fVLWyRoKg5S33j6Dk589ptvg== +"@react-three/fiber@^8.0.11": + version "8.0.11" + resolved "https://registry.npmjs.org/@react-three/fiber/-/fiber-8.0.11.tgz#3fc140b43d954270da15c2d366ee940e62b43f32" + integrity sha512-plvh1mLDIAa3lJfqXJHBWi0PxTOQVXoPXd03/SIwt+vZFBPSzuQCRnhYY/8Q2Of3S89PWTl8TtFXNfRzTUHNnw== dependencies: "@babel/runtime" "^7.17.8" "@types/react-reconciler" "^0.26.4" @@ -1346,7 +1346,7 @@ "@types/history" "^4.7.11" "@types/react" "*" -"@types/react@*", "@types/react@^17.0.43": +"@types/react@*": version "17.0.43" resolved "https://registry.npmjs.org/@types/react/-/react-17.0.43.tgz#4adc142887dd4a2601ce730bc56c3436fdb07a55" integrity sha512-8Q+LNpdxf057brvPu1lMtC5Vn7J119xrP1aq4qiaefNioQUYANF/CYeK4NsKorSZyUGJ66g0IM+4bbjwx45o2A== @@ -1355,6 +1355,15 @@ "@types/scheduler" "*" csstype "^3.0.2" +"@types/react@^18.0.5": + version "18.0.5" + resolved "https://registry.npmjs.org/@types/react/-/react-18.0.5.tgz#1a4d4b705ae6af5aed369dec22800b20f89f5301" + integrity sha512-UPxNGInDCIKlfqBrm8LDXYWNfLHwIdisWcsH5GpMyGjhEDLFgTtlRBaoWuCua9HcyuE0rMkmAeZ3FXV1pYLIYQ== + dependencies: + "@types/prop-types" "*" + "@types/scheduler" "*" + csstype "^3.0.2" + "@types/resolve@1.17.1": version "1.17.1" resolved "https://registry.npmjs.org/@types/resolve/-/resolve-1.17.1.tgz#3afd6ad8967c77e4376c598a82ddd58f46ec45d6" @@ -1367,10 +1376,10 @@ resolved "https://registry.npmjs.org/@types/scheduler/-/scheduler-0.16.2.tgz#1a62f89525723dde24ba1b01b092bf5df8ad4d39" integrity sha512-hppQEBDmlwhFAXKJX2KnWLYu5yMfi91yazPb2l+lbJiwW+wdo1gNeRA+3RgNSO39WYX2euey41KEwnqesU2Jew== -"@types/styled-components@^5.1.24": - version "5.1.24" - resolved "https://registry.npmjs.org/@types/styled-components/-/styled-components-5.1.24.tgz#b52ae677f03ea8a6018aa34c6c96b7018b7a3571" - integrity sha512-mz0fzq2nez+Lq5IuYammYwWgyLUE6OMAJTQL9D8hFLP4Pkh7gVYJii/VQWxq8/TK34g/OrkehXaFNdcEKcItug== +"@types/styled-components@^5.1.25": + version "5.1.25" + resolved "https://registry.npmjs.org/@types/styled-components/-/styled-components-5.1.25.tgz#0177c4ab5fa7c6ed0565d36f597393dae3f380ad" + integrity sha512-fgwl+0Pa8pdkwXRoVPP9JbqF0Ivo9llnmsm+7TCI330kbPIFd9qv1Lrhr37shf4tnxCOSu+/IgqM7uJXLWZZNQ== dependencies: "@types/hoist-non-react-statics" "*" "@types/react" "*"