# API This is a work in progress. # Engine Important: must be placed within the `Canvas` element provided by react-three-fiber. ```tsx ``` #### config _optional_ ```tsx type config = { maxNumberOfDynamicObjects: number // default 100 updateRate: number // default 1000 / 30 (i.e. physics updates 30 times a second) } ``` #### worldParams _optional_ See the [planck.js documentation](https://github.com/shakiba/planck.js/blob/master/docs/interfaces/worlddef.md) for details regarding `worldDef` ```tsx type worldParams = { allowSleep: boolean // default to true gravity: Vec2 // default to Vec2(0, 0) (i.e. no gravity) ...worldDef } ``` #### logicWorker _optional_ A Web Worker that will be run as the logic worker, synchronized with the physics app. [Read more here.](../../README.md#react-logic-app-worker) #### logicMappedComponents _optional_ Facilitates synchronising components from the logic app with the main app. [Read more here.](../../README.md#synchronising-logic-app-with-main-app) ```tsx type logicMappedComponents = { [key: string]: ReactComponent } ``` See [useSyncWithMainComponent](#useSyncWithMainComponent) for further details. ## useFixedUpdate Inspired by Unity's `OnFixedUpDate`, `useFixedUpdate` is a hook that enables you to call a function after each physics update. For Unity this is the recommended way to apply physics effects. ```tsx import { useFixedUpdate } from "react-three-game-engine" useFixedUpdate((delta: number) => { // do something }) ``` # Physics ## Bodies #### BodyApi ```tsx type BodyApi = { // planck.js methods applyForceToCenter: (vec: Vec2, uuid?: string) => void; applyLinearImpulse: (vec: Vec2, pos: Vec2, uuid?: string) => void; setPosition: (vec: Vec2, uuid?: string) => void; setLinearVelocity: (vec: Vec2, uuid?: string) => void; setAngle: (angle: number, uuid?: string) => void; // custom updateBody: (data: UpdateBodyData, uuid?: string) => void; } type UpdateBodyData = { fixtureUpdate?: { groupIndex?: number, categoryBits?: number, maskBits?: number, } } ``` For detail on what the planck.js methods do, see the [documentation for planck.js](https://github.com/shakiba/planck.js/blob/master/docs/api/classes/body.md#methods). #### useBody ```tsx useBody(PropsFn, Config): [ref: MutableRefObject, api: BodyApi, uuid: string] ``` ```tsx type PropsFn = () => AddBodyDef type AddBodyDef = { bodyType: BodyType, fixtures: Fixture[], ...BodyDef, } type Fixture = BoxFixture | CircleFixture type BoxFixture = FixtureBase & { hx: number, hy: number, center?: [number, number], } type CircleFixture = FixtureBase & { radius: number, } type FixtureBase = { shape: BodyShape, fixtureOptions?: Partial, } enum BodyShape { box = 'box', circle = 'circle', } enum BodyType { static = 'static', kinematic = 'kinematic', dynamic = 'dynamic' } ``` ```tsx type Config = { listenForCollisions?: boolean; applyAngle?: boolean; cacheKey?: string; uuid?: string; fwdRef?: MutableRefObject; } ``` Note: for `BodyDef` [see the planck.js documentation](https://github.com/shakiba/planck.js/blob/master/docs/api/interfaces/bodydef.md). Note: for `FixtureOpt` [see the planck.js documentation](https://github.com/shakiba/planck.js/blob/master/docs/api/interfaces/fixtureopt.md). ```tsx import { useBody, BodyType, BodyShape } from "react-three-game-engine" import { Vec2 } from "planck-js" const [ref, api, uuid] = useBody(() => ({ type: BodyType.dynamic, position: Vec2(0, 0), linearDamping: 4, fixtures: [{ shape: BodyShape.circle, radius: 0.55, fixtureOptions: { density: 20, } }], })) ``` Note: if you set `bodyType` to `static` it will not be synchronised with either the main app or logic app. #### createBoxFixture ```tsx createBoxFixture = ({ width = 1, height = 1, center, fixtureOptions = {} }: { width?: number, height?: number, center?: [number, number], fixtureOptions?: Partial }) => BoxFixture ``` ```tsx useBody(() => ({ type: BodyType.dynamic, position: Vec2(0, 0), linearDamping: 4, fixtures: [ createBoxFixture({ width: 2, height: 2, }) ], })) ``` #### createCircleFixture ```tsx createCircleFixture = ({ radius = 1, fixtureOptions = {} }: { radius?: number, fixtureOptions?: Partial }) => CircleFixture ``` ```tsx useBody(() => ({ type: BodyType.dynamic, position: Vec2(0, 0), linearDamping: 4, fixtures: [ createCircleFixture({ radius: 2, }) ], })) ``` #### useBodyApi ```tsx useBodyApi: (uuid: string) => BodyApi ``` ```tsx const api = useBodyApi('player') // ... api.setLinearVelocity(Vec2(1, 1)) ``` #### useSubscribeMesh ```tsx useSubscribeMesh: ( uuid: string, object: Object3D, applyAngle: boolean = true, isDynamic: boolean = true ) ``` ```tsx const ref = useRef(new Object3D()) useSubscribeMesh('player', ref.current, false) ``` # Logic ## Logic Worker #### logicWorkerHandler ```tsx logicWorkerHandler: (worker: Worker, appComponent: ReactComponent) ``` ```jsx /* eslint-disable no-restricted-globals */ import { logicWorkerHandler } from "react-three-game-engine"; // because of some weird react/dev/webpack/something quirk (self).$RefreshReg$ = () => {}; (self).$RefreshSig$ = () => () => {}; logicWorkerHandler(self, require("../path/to/logic/app/component").LgApp) ``` ## Logic App #### withLogicWrapper ```tsx withLogicWrapper: (appComponent: ReactComponent) => ReactComponent ``` ```jsx import { withLogicWrapper } from "react-three-game-engine"; const App = () => { // ... your new logic app goes here } export const LgApp = withLogicWrapper(App) ``` #### useSyncWithMainComponent ``` useSyncWithMainComponent: (componentKey: string, uniqueKey: string, props: {}) => UpdateProps type UpdateProps = (props: {}) => void ``` ```tsx const updateProps = useSyncWithMainComponent("player", "uniqueKey", { foo: "bar", blah: "blah", }) // ... updateProps({ foo: "updated" }) ``` See [logicMappedComponents](#logicMappedComponents) for implementation details. ## Communication #### useSendMessage ```tsx useSendMessage: () => (messageKey: string, data: any) => void ``` ```jsx import { useSendMessage } from "react-three-game-engine" // ... const sendMessage = useSendMessage() // ... sendMessage('messageKey', "any-data") ``` #### useOnMessage ```tsx useOnMessage: () => (messageKey: string, callback: (data: any) => void) => UnsubscribeFn ``` ```jsx import { useOnMessage } from "react-three-game-engine" // ... const onMessage = useOnMessage() // ... const unsubscribe = onMessage('messageKey', (data) => { // data -> "any-data" }) // ... unsubscribe() ``` ## Misc ### Mesh Storage #### useStoreMesh ```tsx useStoreMesh: (uuid: string, mesh: Object3D) ``` #### useStoredMesh ```tsx useStoredMesh: (uuid: string) => Object3D | null ``` ### Mesh Instancing You'll need to install `@react-three/drei` #### InstancesProvider Place inside of `` ```tsx {/*...*/} ``` #### InstancedMesh ```tsx for r3f, e.g. castShadow /> type Props = { meshKey: string, maxInstances: number, gltfPath: string, meshProps?: JSX.IntrinsicElements['instancedMesh'] } ``` gltfPath is passed to `useGltf` from `@react-three/drei` Place inside of `` You need to wrap it with React's `` ```tsx ``` #### Instance ```tsx type Props = { meshKey: string, position?: [number, number, number], rotation?: [number, number, number], scale?: [number, number, number] } ``` #### useInstancedMesh todo... #### useAddInstance todo...