UNPKG

@react-three/p2

Version:

2D physics based hooks for react-three-fiber

476 lines (396 loc) 13.4 kB
import EventEmitter from 'events' import Worker from 'web-worker:./worker/index.ts' import type { Broadphase, CannonMessageBody, CannonWebWorker, Duplet, IncomingWorkerMessage, StepProps, WorldProps, } from './setup' export type CannonWorkerProps = Partial<WorldProps> & { size?: number } export class CannonWorkerAPI extends EventEmitter { get axisIndex(): 0 | 1 | 2 { return this.config.axisIndex } set axisIndex(value: 0 | 1 | 2) { this.config.axisIndex = value this.worker.postMessage({ op: 'setAxisIndex', props: value }) } get broadphase(): Broadphase { return this.config.broadphase } set broadphase(value: Broadphase) { this.config.broadphase = value this.worker.postMessage({ op: 'setBroadphase', props: value }) } get gravity(): Duplet { return this.config.gravity } set gravity(value: Duplet) { this.config.gravity = value this.worker.postMessage({ op: 'setGravity', props: value }) } get iterations(): number { return this.config.iterations } set iterations(value: number) { this.config.iterations = value this.worker.postMessage({ op: 'setIterations', props: value }) } get tolerance(): number { return this.config.tolerance } set tolerance(value: number) { this.config.tolerance = value this.worker.postMessage({ op: 'setTolerance', props: value }) } private buffers: { positions: Float32Array quaternions: Float32Array } private config: Required<CannonWorkerProps> private worker = new Worker() as CannonWebWorker constructor({ allowSleep = false, axisIndex = 0, broadphase = 'Naive', defaultContactMaterial = { friction: 0.3, restitution: 0 }, gravity = [0, -9.81], iterations = 5, normalIndex = 0, quatNormalizeFast = false, quatNormalizeSkip = 0, size = 1000, solver = 'GS', tolerance = 0.001, }: CannonWorkerProps) { super() this.config = { allowSleep, axisIndex, broadphase, defaultContactMaterial, gravity, iterations, normalIndex, quatNormalizeFast, quatNormalizeSkip, size, solver, tolerance, } this.buffers = { positions: new Float32Array(size * 3), quaternions: new Float32Array(size * 4), } this.worker.onmessage = (message: IncomingWorkerMessage) => { if (message.data.op === 'frame') { this.buffers.positions = message.data.positions this.buffers.quaternions = message.data.quaternions this.emit(message.data.op, message.data) return } this.emit(message.data.type, message.data) } } addBodies({ props, type, uuid }: CannonMessageBody<'addBodies'>): void { this.worker.postMessage({ op: 'addBodies', props, type, uuid, }) } addConstraint({ props: [refA, refB, optns], type, uuid }: CannonMessageBody<'addConstraint'>): void { this.worker.postMessage({ op: 'addConstraint', props: [refA, refB, optns], type, uuid, }) } addContactMaterial({ props, uuid }: CannonMessageBody<'addContactMaterial'>): void { this.worker.postMessage({ op: 'addContactMaterial', props, uuid, }) } addKinematicCharacterController({ props: [ accelerationTimeAirborne, accelerationTimeGrounded, body, collisionMask, dstBetweenRays, maxClimbAngle, maxDescendAngle, maxJumpHeight, minJumpHeight, moveSpeed, skinWidth, timeToJumpApex, velocityXMin, velocityXSmoothing, wallJumpClimb, wallJumpOff, wallLeap, wallSlideSpeedMax, wallStickTime, ], uuid, }: CannonMessageBody<'addKinematicCharacterController'>): void { this.worker.postMessage({ op: 'addKinematicCharacterController', props: [ accelerationTimeAirborne, accelerationTimeGrounded, body, collisionMask, dstBetweenRays, maxClimbAngle, maxDescendAngle, maxJumpHeight, minJumpHeight, moveSpeed, skinWidth, timeToJumpApex, velocityXMin, velocityXSmoothing, wallJumpClimb, wallJumpOff, wallLeap, wallSlideSpeedMax, wallStickTime, ], uuid, }) } addPlatformController({ props: [body, passengerMask, localWaypoints, speed, skinWidth, dstBetweenRays], uuid, }: CannonMessageBody<'addPlatformController'>): void { this.worker.postMessage({ op: 'addPlatformController', props: [body, passengerMask, localWaypoints, speed, skinWidth, dstBetweenRays], uuid, }) } addRay({ props, uuid }: CannonMessageBody<'addRay'>): void { this.worker.postMessage({ op: 'addRay', props, uuid }) } addSpring({ props: [refA, refB, optns], uuid }: CannonMessageBody<'addSpring'>): void { this.worker.postMessage({ op: 'addSpring', props: [refA, refB, optns], uuid, }) } addTopDownVehicle({ props: [chassisBodyUUID, wheelInfos], uuid, }: CannonMessageBody<'addTopDownVehicle'>): void { this.worker.postMessage({ op: 'addTopDownVehicle', props: [chassisBodyUUID, wheelInfos], uuid, }) } applyForce({ props, uuid }: CannonMessageBody<'applyForce'>): void { this.worker.postMessage({ op: 'applyForce', props, uuid }) } applyImpulse({ props, uuid }: CannonMessageBody<'applyImpulse'>): void { this.worker.postMessage({ op: 'applyImpulse', props, uuid }) } applyLocalForce({ props, uuid }: CannonMessageBody<'applyLocalForce'>): void { this.worker.postMessage({ op: 'applyLocalForce', props, uuid }) } applyLocalImpulse({ props, uuid }: CannonMessageBody<'applyLocalImpulse'>): void { this.worker.postMessage({ op: 'applyLocalImpulse', props, uuid }) } applyTopDownVehicleEngineForce({ props, uuid }: CannonMessageBody<'applyTopDownVehicleEngineForce'>): void { this.worker.postMessage({ op: 'applyTopDownVehicleEngineForce', props, uuid, }) } applyTorque({ props, uuid }: CannonMessageBody<'applyTorque'>): void { this.worker.postMessage({ op: 'applyTorque', props, uuid }) } disableConstraintMotor({ uuid }: CannonMessageBody<'disableConstraintMotor'>): void { this.worker.postMessage({ op: 'disableConstraintMotor', uuid }) } enableConstraintMotor({ uuid }: CannonMessageBody<'enableConstraintMotor'>): void { this.worker.postMessage({ op: 'enableConstraintMotor', uuid }) } init(): void { const { allowSleep, axisIndex, broadphase, defaultContactMaterial, gravity, iterations, normalIndex, quatNormalizeFast, quatNormalizeSkip, solver, tolerance, } = this.config this.worker.postMessage({ op: 'init', props: { allowSleep, axisIndex, broadphase, defaultContactMaterial, gravity, iterations, normalIndex, quatNormalizeFast, quatNormalizeSkip, solver, tolerance, }, }) } removeBodies({ uuid }: CannonMessageBody<'removeBodies'>): void { this.worker.postMessage({ op: 'removeBodies', uuid }) } removeConstraint({ uuid }: CannonMessageBody<'removeConstraint'>): void { this.worker.postMessage({ op: 'removeConstraint', uuid }) } removeContactMaterial({ uuid }: CannonMessageBody<'removeContactMaterial'>): void { this.worker.postMessage({ op: 'removeContactMaterial', uuid }) } removeKinematicCharacterController({ uuid, }: CannonMessageBody<'removeKinematicCharacterController'>): void { this.worker.postMessage({ op: 'removeKinematicCharacterController', uuid }) } removePlatformController({ uuid }: CannonMessageBody<'removePlatformController'>): void { this.worker.postMessage({ op: 'removePlatformController', uuid }) } removeRay({ uuid }: CannonMessageBody<'removeRay'>): void { this.worker.postMessage({ op: 'removeRay', uuid }) } removeSpring({ uuid }: CannonMessageBody<'removeSpring'>): void { this.worker.postMessage({ op: 'removeSpring', uuid }) } removeTopDownVehicle({ uuid }: CannonMessageBody<'removeTopDownVehicle'>): void { this.worker.postMessage({ op: 'removeTopDownVehicle', uuid }) } setAllowSleep({ props, uuid }: CannonMessageBody<'setAllowSleep'>): void { this.worker.postMessage({ op: 'setAllowSleep', props, uuid }) } setAngle({ props, uuid }: CannonMessageBody<'setAngle'>): void { this.worker.postMessage({ op: 'setAngle', props, uuid }) } setAngularDamping({ props, uuid }: CannonMessageBody<'setAngularDamping'>): void { this.worker.postMessage({ op: 'setAngularDamping', props, uuid }) } setAngularVelocity({ props, uuid }: CannonMessageBody<'setAngularVelocity'>): void { this.worker.postMessage({ op: 'setAngularVelocity', props, uuid }) } setCollisionFilterGroup({ props, uuid }: CannonMessageBody<'setCollisionFilterGroup'>): void { this.worker.postMessage({ op: 'setCollisionFilterGroup', props, uuid }) } setCollisionFilterMask({ props, uuid }: CannonMessageBody<'setCollisionFilterMask'>): void { this.worker.postMessage({ op: 'setCollisionFilterMask', props, uuid }) } setCollisionResponse({ props, uuid }: CannonMessageBody<'setCollisionResponse'>): void { this.worker.postMessage({ op: 'setCollisionResponse', props, uuid }) } setConstraintMotorSpeed({ props, uuid }: CannonMessageBody<'setConstraintMotorSpeed'>): void { this.worker.postMessage({ op: 'setConstraintMotorSpeed', props, uuid }) } setFixedRotation({ props, uuid }: CannonMessageBody<'setFixedRotation'>): void { this.worker.postMessage({ op: 'setFixedRotation', props, uuid }) } setIsTrigger({ props, uuid }: CannonMessageBody<'setIsTrigger'>): void { this.worker.postMessage({ op: 'setIsTrigger', props, uuid }) } setKinematicCharacterControllerInput({ props, uuid, }: CannonMessageBody<'setKinematicCharacterControllerInput'>): void { this.worker.postMessage({ op: 'setKinematicCharacterControllerInput', props, uuid }) } setKinematicCharacterControllerJump({ props, uuid, }: CannonMessageBody<'setKinematicCharacterControllerJump'>): void { this.worker.postMessage({ op: 'setKinematicCharacterControllerJump', props, uuid }) } setLinearDamping({ props, uuid }: CannonMessageBody<'setLinearDamping'>): void { this.worker.postMessage({ op: 'setLinearDamping', props, uuid }) } setMass({ props, uuid }: CannonMessageBody<'setMass'>): void { this.worker.postMessage({ op: 'setMass', props, uuid }) } setMaterial({ props, uuid }: CannonMessageBody<'setMaterial'>): void { this.worker.postMessage({ op: 'setMaterial', props, uuid }) } setPosition({ props, uuid }: CannonMessageBody<'setPosition'>): void { this.worker.postMessage({ op: 'setPosition', props, uuid }) } setSleepSpeedLimit({ props, uuid }: CannonMessageBody<'setSleepSpeedLimit'>): void { this.worker.postMessage({ op: 'setSleepSpeedLimit', props, uuid }) } setSleepTimeLimit({ props, uuid }: CannonMessageBody<'setSleepTimeLimit'>): void { this.worker.postMessage({ op: 'setSleepTimeLimit', props, uuid }) } setSpringDamping({ props, uuid }: CannonMessageBody<'setSpringDamping'>): void { this.worker.postMessage({ op: 'setSpringDamping', props, uuid }) } setSpringRestLength({ props, uuid }: CannonMessageBody<'setSpringRestLength'>): void { this.worker.postMessage({ op: 'setSpringRestLength', props, uuid }) } setSpringStiffness({ props, uuid }: CannonMessageBody<'setSpringStiffness'>): void { this.worker.postMessage({ op: 'setSpringStiffness', props, uuid }) } setTopDownVehicleBrake({ props, uuid }: CannonMessageBody<'setTopDownVehicleBrake'>): void { this.worker.postMessage({ op: 'setTopDownVehicleBrake', props, uuid }) } setTopDownVehicleSteeringValue({ props, uuid }: CannonMessageBody<'setTopDownVehicleSteeringValue'>): void { this.worker.postMessage({ op: 'setTopDownVehicleSteeringValue', props, uuid, }) } setUserData({ props, uuid }: CannonMessageBody<'setUserData'>): void { this.worker.postMessage({ op: 'setUserData', props, uuid }) } setVelocity({ props, uuid }: CannonMessageBody<'setVelocity'>): void { this.worker.postMessage({ op: 'setVelocity', props, uuid }) } sleep({ uuid }: CannonMessageBody<'sleep'>): void { this.worker.postMessage({ op: 'sleep', uuid }) } step(props: StepProps): void { const { buffers: { positions, quaternions }, } = this if (!positions.byteLength && !quaternions.byteLength) return this.worker.postMessage({ op: 'step', positions, props, quaternions }, [ positions.buffer, quaternions.buffer, ]) } subscribe({ props: { id, target, type }, uuid }: CannonMessageBody<'subscribe'>): void { this.worker.postMessage({ op: 'subscribe', props: { id, target, type }, uuid }) } terminate(): void { this.worker.terminate() } unsubscribe({ props }: CannonMessageBody<'unsubscribe'>): void { this.worker.postMessage({ op: 'unsubscribe', props }) } wakeUp({ uuid }: CannonMessageBody<'wakeUp'>): void { this.worker.postMessage({ op: 'wakeUp', uuid }) } }