@react-three/p2
Version:
2D physics based hooks for react-three-fiber
400 lines (399 loc) • 14.9 kB
TypeScript
import type { ContactMaterialOptions, MaterialOptions, RayOptions as RayOptionsImpl, Shape } from 'p2-es';
import type { MutableRefObject } from 'react';
import type { Object3D } from 'three';
import type { CannonWorkerAPI } from 'cannon-worker-api';
import type { AtomicProps, BodyProps, BodyShapeType } from './hooks';
export declare type Duplet = [number, number];
export declare type Broadphase = 'Naive' | 'SAP';
export declare type Solver = 'GS' | 'Split';
export declare type Buffers = {
positions: Float32Array;
quaternions: Float32Array;
};
export declare type Refs = {
[uuid: string]: Object3D;
};
export declare type ConstraintTypes = 'Distance' | 'Gear' | 'Lock' | 'Prismatic' | 'Revolute';
export interface ConstraintOptns {
collideConnected?: boolean;
}
export interface DistanceConstraintOpts extends ConstraintOptns {
distance?: number;
localAnchorA?: Duplet;
localAnchorB?: Duplet;
maxForce?: number;
}
export interface GearConstraintOpts extends ConstraintOptns {
angle?: number;
maxTorque?: number;
ratio?: number;
}
export interface LockConstraintOpts extends ConstraintOptns {
localAngleB?: number;
localOffsetB?: Duplet;
maxForce?: number;
}
export interface PrismaticConstraintOpts extends ConstraintOptns {
disableRotationalLock?: boolean;
localAnchorA?: Duplet;
localAnchorB?: Duplet;
localAxisA?: Duplet;
lowerLimit?: number;
maxForce?: number;
upperLimit?: number;
}
export interface RevoluteConstraintOpts extends ConstraintOptns {
localPivotA?: Duplet;
localPivotB?: Duplet;
maxForce?: number;
worldPivot?: Duplet;
}
export interface SpringOptns {
damping?: number;
localAnchorA?: Duplet;
localAnchorB?: Duplet;
restLength?: number;
stiffness?: number;
worldAnchorA?: Duplet;
worldAnchorB?: Duplet;
}
export interface WheelInfoOptions {
localPosition?: Duplet;
sideFriction?: number;
}
declare type WorkerContact = WorkerCollideEvent['data']['contact'];
export declare type CollideEvent = Omit<WorkerCollideEvent['data'], 'body' | 'target' | 'contact'> & {
body: Object3D;
contact: Omit<WorkerContact, 'bi' | 'bj'> & {
bi: Object3D;
bj: Object3D;
};
target: Object3D;
};
export declare type CollideBeginEvent = {
body: Object3D;
op: 'event';
target: Object3D;
type: 'collideBegin';
};
export declare type CollideEndEvent = {
body: Object3D;
op: 'event';
target: Object3D;
type: 'collideEnd';
};
export declare type RayhitEvent = Omit<WorkerRayhitEvent['data'], 'body'> & {
body: Object3D | null;
};
declare type CannonEvent = CollideBeginEvent | CollideEndEvent | CollideEvent | RayhitEvent;
declare type CallbackByType<T extends {
type: string;
}> = {
[K in T['type']]?: T extends {
type: K;
} ? (e: T) => void : never;
};
declare type CannonEvents = {
[uuid: string]: Partial<CallbackByType<CannonEvent>>;
};
export declare type Subscription = Partial<{
[K in SubscriptionName]: (value: PropValue<K>) => void;
}>;
export declare type Subscriptions = Partial<{
[id: number]: Subscription;
}>;
export declare type PropValue<T extends SubscriptionName = SubscriptionName> = T extends AtomicName ? AtomicProps[T] : T extends VectorName ? Duplet : never;
export declare const atomicNames: readonly ["allowSleep", "angle", "angularDamping", "angularVelocity", "collisionFilterGroup", "collisionFilterMask", "collisionResponse", "fixedRotation", "isTrigger", "linearDamping", "mass", "material", "sleepSpeedLimit", "sleepTimeLimit", "userData"];
export declare type AtomicName = typeof atomicNames[number];
export declare const vectorNames: readonly ["position", "velocity"];
export declare type VectorName = typeof vectorNames[number];
export declare const subscriptionNames: readonly ["allowSleep", "angle", "angularDamping", "angularVelocity", "collisionFilterGroup", "collisionFilterMask", "collisionResponse", "fixedRotation", "isTrigger", "linearDamping", "mass", "material", "sleepSpeedLimit", "sleepTimeLimit", "userData", "position", "velocity", "collisions", "raysData"];
export declare type SubscriptionName = typeof subscriptionNames[number];
export declare type SetOpName<T extends AtomicName | VectorName | WorldPropName> = `set${Capitalize<T>}`;
declare type Operation<T extends OpName, P> = {
op: T;
} & (P extends symbol ? {} : {
props: P;
});
declare type WithUUID<T extends OpName, P = symbol> = Operation<T, P> & {
uuid: string;
};
declare type WithUUIDs<T extends OpName, P = symbol> = Operation<T, P> & {
uuid: string[];
};
declare type AddConstraintProps = [
uuidA: string,
uuidB: string,
options: {
angle?: number;
collideConnected?: boolean;
disableRotationalLock?: boolean;
distance?: number;
localAnchorA?: Duplet;
localAnchorB?: Duplet;
localAngleB?: number;
localAxisA?: Duplet;
localOffsetB?: Duplet;
localPivotA?: Duplet;
localPivotB?: Duplet;
lowerLimit?: number;
maxForce?: number;
maxTorque?: number;
ratio?: number;
upperLimit?: number;
worldPivot?: Duplet;
}
];
declare type AddContactMaterialProps = [
materialA: MaterialOptions,
materialB: MaterialOptions,
options: ContactMaterialOptions
];
export declare type RayMode = 'Closest' | 'Any' | 'All';
declare type AddRayProps = {
from: Duplet;
mode: RayMode;
to: Duplet;
} & Pick<RayOptionsImpl, 'checkCollisionResponse' | 'collisionGroup' | 'collisionMask' | 'skipBackfaces'>;
export declare type RayOptions = Omit<AddRayProps, 'mode'>;
declare type AtomicMessage<T extends AtomicName> = WithUUID<SetOpName<T>, AtomicProps[T]>;
declare type VectorMessage = WithUUID<SetOpName<VectorName>, Duplet>;
declare type SerializableBodyProps = {
onCollide: boolean;
};
export declare type SubscriptionTarget = 'bodies' | 'vehicles' | 'controllers';
declare type SubscribeMessageProps = {
id: number;
target: SubscriptionTarget;
type: SubscriptionName;
};
export declare type Observation = {
[K in AtomicName]: [id: number, value: PropValue<K>, type: K];
}[AtomicName];
export declare type WorkerFrameMessage = {
data: Buffers & {
active: boolean;
bodies?: string[];
observations: Observation[];
op: 'frame';
};
};
export declare type WorkerCollideEvent = {
data: {
body: string;
collisionFilters: {
bodyFilterGroup: number;
bodyFilterMask: number;
targetFilterGroup: number;
targetFilterMask: number;
};
contact: {
bi: string;
bj: string;
contactNormal: number[];
contactPoint: number[];
id: number;
impactVelocity: number;
ni: number[];
ri: number[];
rj: number[];
};
op: 'event';
target: string;
type: 'collide';
};
};
export declare type WorkerRayhitEvent = {
data: {
body: string | null;
distance: number;
hasHit: boolean;
hitFaceIndex: number;
hitNormalWorld: number[];
hitPointWorld: number[];
op: 'event';
ray: {
collisionFilterGroup: number;
collisionFilterMask: number;
direction: number[];
from: number[];
to: number[];
uuid: string;
};
rayFromWorld: number[];
rayToWorld: number[];
shape: (Omit<Shape, 'body'> & {
body: string;
}) | null;
shouldStop: boolean;
type: 'rayhit';
};
};
export declare type WorkerCollideBeginEvent = {
data: {
bodyA: string;
bodyB: string;
op: 'event';
type: 'collideBegin';
};
};
export declare type WorkerCollideEndEvent = {
data: {
bodyA: string;
bodyB: string;
op: 'event';
type: 'collideEnd';
};
};
export declare type WorkerEventMessage = WorkerCollideBeginEvent | WorkerCollideEndEvent | WorkerCollideEvent | WorkerRayhitEvent;
export declare type IncomingWorkerMessage = WorkerEventMessage | WorkerFrameMessage;
export declare type WorldPropName = 'axisIndex' | 'broadphase' | 'gravity' | 'iterations' | 'tolerance';
export declare type StepProps = {
maxSubSteps?: number;
stepSize: number;
timeSinceLastCalled?: number;
};
export declare type WorldProps = {
allowSleep: boolean;
axisIndex: 0 | 1 | 2;
broadphase: Broadphase;
defaultContactMaterial: ContactMaterialOptions;
gravity: Duplet;
iterations: number;
normalIndex: 0 | 1 | 2;
quatNormalizeFast: boolean;
quatNormalizeSkip: number;
solver: Solver;
tolerance: number;
};
declare type WorldMessage<T extends WorldPropName> = Operation<SetOpName<T>, WorldProps[T]>;
export declare type CannonMessageMap = {
addBodies: WithUUIDs<'addBodies', SerializableBodyProps[]> & {
type: BodyShapeType;
};
addConstraint: WithUUID<'addConstraint', AddConstraintProps> & {
type: 'Prismatic' | 'Revolute' | ConstraintTypes;
};
addContactMaterial: WithUUID<'addContactMaterial', AddContactMaterialProps>;
addKinematicCharacterController: WithUUID<'addKinematicCharacterController', [
bodyUUID: string,
collisionMask: number,
accelerationTimeAirborne?: number,
accelerationTimeGrounded?: number,
moveSpeed?: number,
wallSlideSpeedMax?: number,
wallStickTime?: number,
wallJumpClimb?: Duplet,
wallJumpOff?: Duplet,
wallLeap?: Duplet,
timeToJumpApex?: number,
maxJumpHeight?: number,
minJumpHeight?: number,
velocityXSmoothing?: number,
velocityXMin?: number,
maxClimbAngle?: number,
maxDescendAngle?: number,
skinWidth?: number,
dstBetweenRays?: number
]>;
addPlatformController: WithUUID<'addPlatformController', [
bodyUUID: string,
passengerMask: number,
localWaypoints: Duplet[],
speed?: number,
skinWidth?: number,
dstBetweenRays?: number
]>;
addRay: WithUUID<'addRay', AddRayProps>;
addSpring: WithUUID<'addSpring', [uuidA: string, uuidB: string, options: SpringOptns]>;
addTopDownVehicle: WithUUID<'addTopDownVehicle', [chassisBodyUUID: string, wheelInfos: WheelInfoOptions[]]>;
applyForce: WithUUID<'applyForce', [force: Duplet, worldPoint: Duplet]>;
applyImpulse: WithUUID<'applyImpulse', [impulse: Duplet, worldPoint: Duplet]>;
applyLocalForce: WithUUID<'applyLocalForce', [force: Duplet, localPoint: Duplet]>;
applyLocalImpulse: WithUUID<'applyLocalImpulse', [impulse: Duplet, localPoint: Duplet]>;
applyTopDownVehicleEngineForce: WithUUID<'applyTopDownVehicleEngineForce', [
value: number,
wheelIndex: number
]>;
applyTorque: WithUUID<'applyTorque', [torque: Duplet]>;
disableConstraintMotor: WithUUID<'disableConstraintMotor'>;
enableConstraintMotor: WithUUID<'enableConstraintMotor'>;
init: Operation<'init', WorldProps>;
removeBodies: WithUUIDs<'removeBodies'>;
removeConstraint: WithUUID<'removeConstraint'>;
removeContactMaterial: WithUUID<'removeContactMaterial'>;
removeKinematicCharacterController: WithUUID<'removeKinematicCharacterController'>;
removePlatformController: WithUUID<'removePlatformController'>;
removeRay: WithUUID<'removeRay'>;
removeSpring: WithUUID<'removeSpring'>;
removeTopDownVehicle: WithUUID<'removeTopDownVehicle'>;
setAllowSleep: AtomicMessage<'allowSleep'>;
setAngle: WithUUID<SetOpName<'angle'>, number>;
setAngularDamping: AtomicMessage<'angularDamping'>;
setAngularVelocity: AtomicMessage<'angularVelocity'>;
setAxisIndex: WorldMessage<'axisIndex'>;
setBroadphase: WorldMessage<'broadphase'>;
setCollisionFilterGroup: AtomicMessage<'collisionFilterGroup'>;
setCollisionFilterMask: AtomicMessage<'collisionFilterMask'>;
setCollisionResponse: AtomicMessage<'collisionResponse'>;
setConstraintMotorSpeed: WithUUID<'setConstraintMotorSpeed', number>;
setFixedRotation: AtomicMessage<'fixedRotation'>;
setGravity: WorldMessage<'gravity'>;
setIsTrigger: AtomicMessage<'isTrigger'>;
setIterations: WorldMessage<'iterations'>;
setKinematicCharacterControllerInput: WithUUID<'setKinematicCharacterControllerInput', Duplet>;
setKinematicCharacterControllerJump: WithUUID<'setKinematicCharacterControllerJump', boolean>;
setLinearDamping: AtomicMessage<'linearDamping'>;
setMass: AtomicMessage<'mass'>;
setMaterial: AtomicMessage<'material'>;
setPosition: VectorMessage;
setSleepSpeedLimit: AtomicMessage<'sleepSpeedLimit'>;
setSleepTimeLimit: AtomicMessage<'sleepTimeLimit'>;
setSpringDamping: WithUUID<'setSpringDamping', number>;
setSpringRestLength: WithUUID<'setSpringRestLength', number>;
setSpringStiffness: WithUUID<'setSpringStiffness', number>;
setTolerance: WorldMessage<'tolerance'>;
setTopDownVehicleBrake: WithUUID<'setTopDownVehicleBrake', [brake: number, wheelIndex: number]>;
setTopDownVehicleSteeringValue: WithUUID<'setTopDownVehicleSteeringValue', [
value: number,
wheelIndex: number
]>;
setUserData: AtomicMessage<'userData'>;
setVelocity: VectorMessage;
sleep: WithUUID<'sleep'>;
step: Operation<'step', StepProps> & {
positions: Float32Array;
quaternions: Float32Array;
};
subscribe: WithUUID<'subscribe', SubscribeMessageProps>;
unsubscribe: Operation<'unsubscribe', number>;
wakeUp: WithUUID<'wakeUp'>;
};
declare type OpName = keyof CannonMessageMap;
export declare type CannonMessageBody<T extends OpName> = Omit<CannonMessageMap[T], 'op'>;
export declare type CannonMessageProps<T extends OpName> = CannonMessageMap[T] extends {
props: unknown;
} ? CannonMessageMap[T]['props'] : never;
export declare type CannonMessage = CannonMessageMap[OpName];
export interface CannonWebWorker extends Worker {
onmessage: (e: IncomingWorkerMessage) => void;
postMessage(message: CannonMessage, transfer: Transferable[]): void;
postMessage(message: CannonMessage, options?: StructuredSerializeOptions): void;
terminate: () => void;
}
export declare type ProviderContext = {
bodies: MutableRefObject<{
[uuid: string]: number;
}>;
events: CannonEvents;
refs: Refs;
subscriptions: Subscriptions;
worker: CannonWorkerAPI;
};
export declare type DebugApi = {
add(id: string, props: BodyProps, type: BodyShapeType): void;
remove(id: string): void;
};
export declare const context: import("react").Context<ProviderContext>;
export declare const debugContext: import("react").Context<DebugApi>;
export {};