@threlte/rapier 0.0.3 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/CHANGELOG.md CHANGED
@@ -1,5 +1,31 @@
1
1
  # @threlte/extras
2
2
 
3
+ ## 0.3.0
4
+
5
+ ### Minor Changes
6
+
7
+ - 1a0f305: removed properties "manifold" and "flipped" from contact force event
8
+
9
+ ### Patch Changes
10
+
11
+ - 291af9b: Exporting rapier event types for easier method typing
12
+
13
+ ## 0.2.0
14
+
15
+ ### Minor Changes
16
+
17
+ - 73b533d: Added contact force events and streamlined event management
18
+
19
+ ### Patch Changes
20
+
21
+ - 7d46de2: sensors need events too!
22
+
23
+ ## 0.1.0
24
+
25
+ ### Minor Changes
26
+
27
+ - c272617: Hooks added to add Joints, Collider and AutoColliders now accepts density, mass or massProperties, documentation for joints hooks added, "Basic Vehicle Controller" Recipe added.
28
+
3
29
  ## 0.0.3
4
30
 
5
31
  ### Patch Changes
@@ -1,26 +1,30 @@
1
1
  <script>import { ActiveCollisionTypes, ActiveEvents, CoefficientCombineRule } from '@dimforge/rapier3d-compat';
2
2
  import { SceneGraphObject } from '@threlte/core';
3
3
  import { createEventDispatcher, onDestroy, onMount } from 'svelte';
4
- import { Object3D, Vector3 } from 'three';
4
+ import { Object3D } from 'three';
5
5
  import { useCollisionGroups } from '../../hooks/useCollisionGroups';
6
+ import { useHasEventListeners } from '../../hooks/useHasEventListener';
6
7
  import { useRapier } from '../../hooks/useRapier';
7
8
  import { useRigidBody } from '../../hooks/useRigidBody';
9
+ import { applyColliderActiveEvents } from '../../lib/applyColliderActiveEvents';
8
10
  import { applyTransforms } from '../../lib/applyTransforms';
9
11
  import { createCollidersFromChildren } from '../../lib/createCollidersFromChildren';
10
12
  import { positionToVector3 } from '../../lib/positionToVector3';
13
+ import { rotationToQuaternion } from '../../lib/rotationToQuaternion';
11
14
  export let shape = 'convexHull';
12
15
  export let position = undefined;
13
16
  export let rotation = undefined;
14
17
  export let scale = undefined;
15
18
  export let lookAt = undefined;
16
- export let mass = undefined;
17
- export let centerOfMass = undefined;
18
- export let principalAngularInertia = undefined;
19
19
  export let restitution = undefined;
20
20
  export let restitutionCombineRule = undefined;
21
21
  export let friction = undefined;
22
22
  export let frictionCombineRule = undefined;
23
23
  export let sensor = undefined;
24
+ export let contactForceEventThreshold = undefined;
25
+ export let density = undefined;
26
+ export let mass = undefined;
27
+ export let massProperties = undefined;
24
28
  const object = new Object3D();
25
29
  /**
26
30
  * Immediately apply transforms
@@ -32,28 +36,29 @@ const { world, addColliderToContext, removeColliderFromContext } = useRapier();
32
36
  export let colliders = [];
33
37
  const collisionGroups = useCollisionGroups();
34
38
  const dispatcher = createEventDispatcher();
39
+ const { hasEventListeners: colliderHasEventListeners } = useHasEventListeners();
35
40
  onMount(() => {
36
- colliders = createCollidersFromChildren(object, shape, world, rigidBody);
41
+ colliders = createCollidersFromChildren(object, shape ?? 'convexHull', world, rigidBody);
37
42
  colliders.forEach((c) => addColliderToContext(c, object, dispatcher));
38
43
  collisionGroups.registerColliders(colliders);
39
44
  });
40
45
  $: {
41
46
  if (colliders.length > 0) {
42
47
  colliders.forEach((collider) => {
43
- collider.setActiveEvents(ActiveEvents.COLLISION_EVENTS);
48
+ applyColliderActiveEvents(collider, colliderHasEventListeners, rigidBody?.userData?.hasEventListeners);
44
49
  collider.setActiveCollisionTypes(ActiveCollisionTypes.ALL);
45
50
  collider.setRestitution(restitution ?? 0);
46
51
  collider.setRestitutionCombineRule(restitutionCombineRule ?? CoefficientCombineRule.Average);
47
52
  collider.setFriction(friction ?? 0.7);
48
53
  collider.setFrictionCombineRule(frictionCombineRule ?? CoefficientCombineRule.Average);
49
54
  collider.setSensor(sensor ?? false);
50
- const { x: cmx, y: cmy, z: cmz } = positionToVector3(centerOfMass) || new Vector3();
51
- const { x: pix, y: piy, z: piz } = positionToVector3(principalAngularInertia) ||
52
- new Vector3(mass ?? 1 * 0.2, mass ?? 1 * 0.2, mass ?? 1 * 0.2);
53
- if (mass || centerOfMass || principalAngularInertia) {
54
- collider.setDensity(0);
55
- collider.setMassProperties(mass ?? 1, { x: cmx, y: cmy, z: cmz }, { x: pix, y: piy, z: piz }, { x: 0, y: 0, z: 0, w: 1 });
56
- }
55
+ collider.setContactForceEventThreshold(contactForceEventThreshold ?? 0);
56
+ if (density)
57
+ collider.setDensity(density);
58
+ if (mass)
59
+ collider.setMass(mass);
60
+ if (massProperties)
61
+ collider.setMassProperties(massProperties.mass, positionToVector3(massProperties.centerOfMass), positionToVector3(massProperties.principalAngularInertia), rotationToQuaternion(massProperties.angularInertiaLocalFrame));
57
62
  });
58
63
  }
59
64
  }
@@ -1,13 +1,16 @@
1
1
  <script>import { ActiveCollisionTypes, ActiveEvents, CoefficientCombineRule, Collider, ColliderDesc } from '@dimforge/rapier3d-compat';
2
2
  import { SceneGraphObject, TransformableObject, useFrame } from '@threlte/core';
3
- import { createEventDispatcher, onDestroy, onMount } from 'svelte';
3
+ import { createEventDispatcher, onDestroy, onMount, tick } from 'svelte';
4
4
  import { Object3D, Quaternion, Vector3 } from 'three';
5
5
  import { useCollisionGroups } from '../../hooks/useCollisionGroups';
6
+ import { useHasEventListeners } from '../../hooks/useHasEventListener';
6
7
  import { useRapier } from '../../hooks/useRapier';
7
8
  import { useRigidBody } from '../../hooks/useRigidBody';
9
+ import { applyColliderActiveEvents } from '../../lib/applyColliderActiveEvents';
8
10
  import { applyTransforms } from '../../lib/applyTransforms';
9
11
  import { getWorldPosition, getWorldQuaternion } from '../../lib/getWorldTransforms';
10
12
  import { positionToVector3 } from '../../lib/positionToVector3';
13
+ import { rotationToQuaternion } from '../../lib/rotationToQuaternion';
11
14
  import { scaleColliderArgs } from '../../lib/scaleColliderArgs';
12
15
  export let shape;
13
16
  export let args;
@@ -15,14 +18,15 @@ export let position = undefined;
15
18
  export let rotation = undefined;
16
19
  export let scale = undefined;
17
20
  export let lookAt = undefined;
18
- export let mass = undefined;
19
- export let centerOfMass = undefined;
20
- export let principalAngularInertia = undefined;
21
21
  export let restitution = undefined;
22
22
  export let restitutionCombineRule = undefined;
23
23
  export let friction = undefined;
24
24
  export let frictionCombineRule = undefined;
25
25
  export let sensor = undefined;
26
+ export let contactForceEventThreshold = undefined;
27
+ export let density = undefined;
28
+ export let mass = undefined;
29
+ export let massProperties = undefined;
26
30
  const object = new Object3D();
27
31
  /**
28
32
  * Immediately apply transforms
@@ -40,7 +44,8 @@ const dispatcher = createEventDispatcher();
40
44
  * Actual collider setup happens onMount as only then
41
45
  * the transforms are finished.
42
46
  */
43
- onMount(() => {
47
+ onMount(async () => {
48
+ await tick();
44
49
  const scale = object.getWorldScale(new Vector3());
45
50
  const scaledArgs = scaleColliderArgs(shape, args, scale);
46
51
  // @ts-ignore
@@ -64,30 +69,36 @@ onMount(() => {
64
69
  rigidBodyWorldQuatInversed.invert();
65
70
  }
66
71
  });
67
- collider.setTranslationWrtParent(object.getWorldPosition(new Vector3()).sub(rigidBodyWorldPos));
68
- collider.setRotationWrtParent(object.getWorldQuaternion(new Quaternion()).premultiply(rigidBodyWorldQuatInversed));
72
+ const worldPosition = object.getWorldPosition(new Vector3()).sub(rigidBodyWorldPos);
73
+ const worldRotation = object
74
+ .getWorldQuaternion(new Quaternion())
75
+ .premultiply(rigidBodyWorldQuatInversed);
76
+ collider.setTranslationWrtParent(worldPosition);
77
+ collider.setRotationWrtParent(worldRotation);
69
78
  }
70
79
  else {
71
80
  collider.setTranslation(object.getWorldPosition(new Vector3()));
72
81
  collider.setRotation(object.getWorldQuaternion(new Quaternion()));
73
82
  }
74
83
  });
84
+ const { hasEventListeners: colliderHasEventListeners } = useHasEventListeners();
75
85
  $: {
76
86
  if (collider) {
77
- collider.setActiveEvents(ActiveEvents.COLLISION_EVENTS);
87
+ applyColliderActiveEvents(collider, colliderHasEventListeners, rigidBody?.userData?.hasEventListeners);
78
88
  collider.setActiveCollisionTypes(ActiveCollisionTypes.ALL);
79
89
  collider.setRestitution(restitution ?? 0);
90
+ collider.setContactForceEventThreshold(1);
80
91
  collider.setRestitutionCombineRule(restitutionCombineRule ?? CoefficientCombineRule.Average);
81
92
  collider.setFriction(friction ?? 0.7);
82
93
  collider.setFrictionCombineRule(frictionCombineRule ?? CoefficientCombineRule.Average);
83
94
  collider.setSensor(sensor ?? false);
84
- const { x: cmx, y: cmy, z: cmz } = positionToVector3(centerOfMass) || new Vector3();
85
- const { x: pix, y: piy, z: piz } = positionToVector3(principalAngularInertia) ||
86
- new Vector3(mass ?? 1 * 0.2, mass ?? 1 * 0.2, mass ?? 1 * 0.2);
87
- if (mass || centerOfMass || principalAngularInertia) {
88
- collider.setDensity(0);
89
- collider.setMassProperties(mass ?? 1, { x: cmx, y: cmy, z: cmz }, { x: pix, y: piy, z: piz }, { x: 0, y: 0, z: 0, w: 1 });
90
- }
95
+ collider.setContactForceEventThreshold(contactForceEventThreshold ?? 0);
96
+ if (density)
97
+ collider.setDensity(density);
98
+ if (mass)
99
+ collider.setMass(mass);
100
+ if (massProperties)
101
+ collider.setMassProperties(massProperties.mass, positionToVector3(massProperties.centerOfMass), positionToVector3(massProperties.principalAngularInertia), rotationToQuaternion(massProperties.angularInertiaLocalFrame));
91
102
  }
92
103
  }
93
104
  useFrame(() => {
@@ -1,32 +1,114 @@
1
1
  import { SvelteComponentTyped } from "svelte";
2
- import { CoefficientCombineRule, Collider, ColliderDesc } from '@dimforge/rapier3d-compat';
3
- import type { ColliderEventMap } from '../../types/types';
4
- declare class __sveltets_Render<Shape extends 'ball' | 'capsule' | 'segment' | 'triangle' | 'roundTriangle' | 'polyline' | 'trimesh' | 'cuboid' | 'roundCuboid' | 'heightfield' | 'cylinder' | 'roundCylinder' | 'cone' | 'roundCone' | 'convexHull' | 'convexMesh' | 'roundConvexHull' | 'roundConvexMesh', Args extends Parameters<typeof ColliderDesc[Shape]>> {
2
+ import { CoefficientCombineRule, Collider, ColliderDesc, type RigidBody } from '@dimforge/rapier3d-compat';
3
+ import { type Position, type Rotation } from '@threlte/core';
4
+ declare class __sveltets_Render<Shape extends 'ball' | 'capsule' | 'segment' | 'triangle' | 'roundTriangle' | 'polyline' | 'trimesh' | 'cuboid' | 'roundCuboid' | 'heightfield' | 'cylinder' | 'roundCylinder' | 'cone' | 'roundCone' | 'convexHull' | 'convexMesh' | 'roundConvexHull' | 'roundConvexMesh', Args extends Parameters<typeof ColliderDesc[Shape]>, Density extends number | undefined, Mass extends Density extends undefined ? number | undefined : undefined, MassProperties extends Density extends undefined ? Mass extends undefined ? {
5
+ mass: number;
6
+ centerOfMass: Position;
7
+ principalAngularInertia: Position;
8
+ angularInertiaLocalFrame: Rotation;
9
+ } : undefined : undefined> {
5
10
  props(): {
6
11
  shape: Shape;
7
12
  args: Args;
8
- position?: import("@threlte/core").Position | undefined;
9
- rotation?: import("@threlte/core").Rotation | undefined;
13
+ position?: Position | undefined;
14
+ rotation?: Rotation | undefined;
10
15
  scale?: import("@threlte/core").Scale | undefined;
11
16
  lookAt?: import("@threlte/core").LookAt | undefined;
12
- mass?: number | undefined;
13
- centerOfMass?: import("@threlte/core").Position | undefined;
14
- principalAngularInertia?: import("@threlte/core").Position | undefined;
15
17
  restitution?: number | undefined;
16
18
  restitutionCombineRule?: CoefficientCombineRule | undefined;
17
19
  friction?: number | undefined;
18
20
  frictionCombineRule?: CoefficientCombineRule | undefined;
19
21
  sensor?: boolean | undefined;
20
22
  collider?: Collider | undefined;
23
+ contactForceEventThreshold?: number | undefined;
24
+ density?: Density | undefined;
25
+ } | {
26
+ shape: Shape;
27
+ args: Args;
28
+ position?: Position | undefined;
29
+ rotation?: Rotation | undefined;
30
+ scale?: import("@threlte/core").Scale | undefined;
31
+ lookAt?: import("@threlte/core").LookAt | undefined;
32
+ restitution?: number | undefined;
33
+ restitutionCombineRule?: CoefficientCombineRule | undefined;
34
+ friction?: number | undefined;
35
+ frictionCombineRule?: CoefficientCombineRule | undefined;
36
+ sensor?: boolean | undefined;
37
+ collider?: Collider | undefined;
38
+ contactForceEventThreshold?: number | undefined;
39
+ mass?: Mass | undefined;
40
+ } | {
41
+ shape: Shape;
42
+ args: Args;
43
+ position?: Position | undefined;
44
+ rotation?: Rotation | undefined;
45
+ scale?: import("@threlte/core").Scale | undefined;
46
+ lookAt?: import("@threlte/core").LookAt | undefined;
47
+ restitution?: number | undefined;
48
+ restitutionCombineRule?: CoefficientCombineRule | undefined;
49
+ friction?: number | undefined;
50
+ frictionCombineRule?: CoefficientCombineRule | undefined;
51
+ sensor?: boolean | undefined;
52
+ collider?: Collider | undefined;
53
+ contactForceEventThreshold?: number | undefined;
54
+ mass?: Mass | undefined;
55
+ massProperties?: MassProperties | undefined;
56
+ };
57
+ events(): {
58
+ collisionenter: CustomEvent<{
59
+ targetCollider: Collider;
60
+ targetRigidBody: RigidBody | null;
61
+ manifold: import("@dimforge/rapier3d-compat").TempContactManifold;
62
+ flipped: boolean;
63
+ }>;
64
+ collisionexit: CustomEvent<{
65
+ targetCollider: Collider;
66
+ targetRigidBody: RigidBody | null;
67
+ }>;
68
+ sensorenter: CustomEvent<{
69
+ targetCollider: Collider;
70
+ targetRigidBody: RigidBody | null;
71
+ }>;
72
+ sensorexit: CustomEvent<{
73
+ targetCollider: Collider;
74
+ targetRigidBody: RigidBody | null;
75
+ }>;
76
+ contact: CustomEvent<{
77
+ targetCollider: Collider;
78
+ targetRigidBody: RigidBody | null;
79
+ maxForceDirection: import("@dimforge/rapier3d-compat").Vector;
80
+ maxForceMagnitude: number;
81
+ totalForce: import("@dimforge/rapier3d-compat").Vector;
82
+ totalForceMagnitude: number;
83
+ }>;
21
84
  };
22
- events(): ColliderEventMap;
23
85
  slots(): {
24
86
  default: {};
25
87
  };
26
88
  }
27
- export declare type ColliderProps<Shape extends 'ball' | 'capsule' | 'segment' | 'triangle' | 'roundTriangle' | 'polyline' | 'trimesh' | 'cuboid' | 'roundCuboid' | 'heightfield' | 'cylinder' | 'roundCylinder' | 'cone' | 'roundCone' | 'convexHull' | 'convexMesh' | 'roundConvexHull' | 'roundConvexMesh', Args extends Parameters<typeof ColliderDesc[Shape]>> = ReturnType<__sveltets_Render<Shape, Args>['props']>;
28
- export declare type ColliderEvents<Shape extends 'ball' | 'capsule' | 'segment' | 'triangle' | 'roundTriangle' | 'polyline' | 'trimesh' | 'cuboid' | 'roundCuboid' | 'heightfield' | 'cylinder' | 'roundCylinder' | 'cone' | 'roundCone' | 'convexHull' | 'convexMesh' | 'roundConvexHull' | 'roundConvexMesh', Args extends Parameters<typeof ColliderDesc[Shape]>> = ReturnType<__sveltets_Render<Shape, Args>['events']>;
29
- export declare type ColliderSlots<Shape extends 'ball' | 'capsule' | 'segment' | 'triangle' | 'roundTriangle' | 'polyline' | 'trimesh' | 'cuboid' | 'roundCuboid' | 'heightfield' | 'cylinder' | 'roundCylinder' | 'cone' | 'roundCone' | 'convexHull' | 'convexMesh' | 'roundConvexHull' | 'roundConvexMesh', Args extends Parameters<typeof ColliderDesc[Shape]>> = ReturnType<__sveltets_Render<Shape, Args>['slots']>;
30
- export default class Collider<Shape extends 'ball' | 'capsule' | 'segment' | 'triangle' | 'roundTriangle' | 'polyline' | 'trimesh' | 'cuboid' | 'roundCuboid' | 'heightfield' | 'cylinder' | 'roundCylinder' | 'cone' | 'roundCone' | 'convexHull' | 'convexMesh' | 'roundConvexHull' | 'roundConvexMesh', Args extends Parameters<typeof ColliderDesc[Shape]>> extends SvelteComponentTyped<ColliderProps<Shape, Args>, ColliderEvents<Shape, Args>, ColliderSlots<Shape, Args>> {
89
+ export declare type ColliderProps<Shape extends 'ball' | 'capsule' | 'segment' | 'triangle' | 'roundTriangle' | 'polyline' | 'trimesh' | 'cuboid' | 'roundCuboid' | 'heightfield' | 'cylinder' | 'roundCylinder' | 'cone' | 'roundCone' | 'convexHull' | 'convexMesh' | 'roundConvexHull' | 'roundConvexMesh', Args extends Parameters<typeof ColliderDesc[Shape]>, Density extends number | undefined, Mass extends Density extends undefined ? number | undefined : undefined, MassProperties extends Density extends undefined ? Mass extends undefined ? {
90
+ mass: number;
91
+ centerOfMass: Position;
92
+ principalAngularInertia: Position;
93
+ angularInertiaLocalFrame: Rotation;
94
+ } : undefined : undefined> = ReturnType<__sveltets_Render<Shape, Args, Density, Mass, MassProperties>['props']>;
95
+ export declare type ColliderEvents<Shape extends 'ball' | 'capsule' | 'segment' | 'triangle' | 'roundTriangle' | 'polyline' | 'trimesh' | 'cuboid' | 'roundCuboid' | 'heightfield' | 'cylinder' | 'roundCylinder' | 'cone' | 'roundCone' | 'convexHull' | 'convexMesh' | 'roundConvexHull' | 'roundConvexMesh', Args extends Parameters<typeof ColliderDesc[Shape]>, Density extends number | undefined, Mass extends Density extends undefined ? number | undefined : undefined, MassProperties extends Density extends undefined ? Mass extends undefined ? {
96
+ mass: number;
97
+ centerOfMass: Position;
98
+ principalAngularInertia: Position;
99
+ angularInertiaLocalFrame: Rotation;
100
+ } : undefined : undefined> = ReturnType<__sveltets_Render<Shape, Args, Density, Mass, MassProperties>['events']>;
101
+ export declare type ColliderSlots<Shape extends 'ball' | 'capsule' | 'segment' | 'triangle' | 'roundTriangle' | 'polyline' | 'trimesh' | 'cuboid' | 'roundCuboid' | 'heightfield' | 'cylinder' | 'roundCylinder' | 'cone' | 'roundCone' | 'convexHull' | 'convexMesh' | 'roundConvexHull' | 'roundConvexMesh', Args extends Parameters<typeof ColliderDesc[Shape]>, Density extends number | undefined, Mass extends Density extends undefined ? number | undefined : undefined, MassProperties extends Density extends undefined ? Mass extends undefined ? {
102
+ mass: number;
103
+ centerOfMass: Position;
104
+ principalAngularInertia: Position;
105
+ angularInertiaLocalFrame: Rotation;
106
+ } : undefined : undefined> = ReturnType<__sveltets_Render<Shape, Args, Density, Mass, MassProperties>['slots']>;
107
+ export default class Collider<Shape extends 'ball' | 'capsule' | 'segment' | 'triangle' | 'roundTriangle' | 'polyline' | 'trimesh' | 'cuboid' | 'roundCuboid' | 'heightfield' | 'cylinder' | 'roundCylinder' | 'cone' | 'roundCone' | 'convexHull' | 'convexMesh' | 'roundConvexHull' | 'roundConvexMesh', Args extends Parameters<typeof ColliderDesc[Shape]>, Density extends number | undefined, Mass extends Density extends undefined ? number | undefined : undefined, MassProperties extends Density extends undefined ? Mass extends undefined ? {
108
+ mass: number;
109
+ centerOfMass: Position;
110
+ principalAngularInertia: Position;
111
+ angularInertiaLocalFrame: Rotation;
112
+ } : undefined : undefined> extends SvelteComponentTyped<ColliderProps<Shape, Args, Density, Mass, MassProperties>, ColliderEvents<Shape, Args, Density, Mass, MassProperties>, ColliderSlots<Shape, Args, Density, Mass, MassProperties>> {
31
113
  }
32
114
  export {};
@@ -0,0 +1,5 @@
1
+ <script>import { useRevoluteJoint } from '../../hooks/useRevoluteJoint';
2
+ export const { joint, rigidBodyA, rigidBodyB } = useRevoluteJoint();
3
+ </script>
4
+
5
+ <slot {rigidBodyA} {rigidBodyB} />
@@ -0,0 +1,23 @@
1
+ import { SvelteComponentTyped } from "svelte";
2
+ declare const __propDef: {
3
+ props: {
4
+ joint?: import("svelte/store").Writable<import("@dimforge/rapier3d-compat").RevoluteImpulseJoint> | undefined;
5
+ rigidBodyA?: import("svelte/store").Writable<import("@dimforge/rapier3d-compat").RigidBody | undefined> | undefined;
6
+ rigidBodyB?: import("svelte/store").Writable<import("@dimforge/rapier3d-compat").RigidBody | undefined> | undefined;
7
+ };
8
+ events: {
9
+ [evt: string]: CustomEvent<any>;
10
+ };
11
+ slots: {
12
+ default: {
13
+ rigidBodyA: import("svelte/store").Writable<import("@dimforge/rapier3d-compat").RigidBody | undefined>;
14
+ rigidBodyB: import("svelte/store").Writable<import("@dimforge/rapier3d-compat").RigidBody | undefined>;
15
+ };
16
+ };
17
+ };
18
+ export declare type RevoluteJointProps = typeof __propDef.props;
19
+ export declare type RevoluteJointEvents = typeof __propDef.events;
20
+ export declare type RevoluteJointSlots = typeof __propDef.slots;
21
+ export default class RevoluteJoint extends SvelteComponentTyped<RevoluteJointProps, RevoluteJointEvents, RevoluteJointSlots> {
22
+ }
23
+ export {};
@@ -1,6 +1,7 @@
1
1
  <script>import { LayerableObject, SceneGraphObject } from '@threlte/core';
2
2
  import { createEventDispatcher, onDestroy, setContext, tick } from 'svelte';
3
3
  import { Object3D, Vector3 } from 'three';
4
+ import { useHasEventListeners } from '../../hooks/useHasEventListener';
4
5
  import { useRapier } from '../../hooks/useRapier';
5
6
  import { applyTransforms } from '../../lib/applyTransforms';
6
7
  import { getWorldPosition, getWorldQuaternion, getWorldScale } from '../../lib/getWorldTransforms';
@@ -8,6 +9,7 @@ import { parseRigidBodyType } from '../../lib/parseRigidBodyType';
8
9
  import { positionToVector3 } from '../../lib/positionToVector3';
9
10
  import { rotationToEuler } from '../../lib/rotationToEuler';
10
11
  const { world, rapier, addRigidBodyToContext, removeRigidBodyFromContext } = useRapier();
12
+ export let debug = false;
11
13
  export let type = 'dynamic';
12
14
  export let canSleep = true;
13
15
  export let linearVelocity = {};
@@ -58,9 +60,13 @@ object.updateWorldMatrix(true, false);
58
60
  */
59
61
  const desc = new rapier.RigidBodyDesc(parseRigidBodyType(type)).setCanSleep(canSleep);
60
62
  /**
61
- * RigidBody init
63
+ * Export the rigidBody only after positional initialization
62
64
  */
63
- export const rigidBody = world.createRigidBody(desc);
65
+ export let rigidBody = undefined;
66
+ /**
67
+ * Temporary RigidBody init
68
+ */
69
+ const rigidBodyTemp = world.createRigidBody(desc);
64
70
  /**
65
71
  * Apply transforms after the parent component added "object" to itself
66
72
  */
@@ -72,44 +78,58 @@ const initPosition = async () => {
72
78
  const parentWorldScale = object.parent ? getWorldScale(object.parent) : new Vector3(1, 1, 1);
73
79
  const worldPosition = getWorldPosition(object).multiply(parentWorldScale);
74
80
  const worldQuaternion = getWorldQuaternion(object);
75
- rigidBody.setTranslation(worldPosition, true);
76
- rigidBody.setRotation(worldQuaternion, true);
81
+ rigidBodyTemp.setTranslation(worldPosition, true);
82
+ rigidBodyTemp.setRotation(worldQuaternion, true);
83
+ if (debug) {
84
+ console.log('worldPosition', worldPosition);
85
+ console.log('worldQuaternion', worldQuaternion);
86
+ }
87
+ if (debug)
88
+ console.log(JSON.stringify(desc, null, 2));
89
+ rigidBody = rigidBodyTemp;
77
90
  };
78
91
  initPosition();
79
92
  /**
80
93
  * Will come in handy in the future for joints
81
94
  */
82
- object.userData.rigidBody = rigidBody;
95
+ object.userData.rigidBody = rigidBodyTemp;
83
96
  /**
84
97
  * Reactive RigidBody properties
85
98
  */
86
99
  $: {
87
- rigidBody.setBodyType(parseRigidBodyType(type));
88
- rigidBody.setLinvel(positionToVector3(linearVelocity), true);
89
- rigidBody.setAngvel(rotationToEuler(angularVelocity), true);
90
- rigidBody.setGravityScale(gravityScale, true);
91
- rigidBody.enableCcd(ccd);
92
- rigidBody.setDominanceGroup(dominance);
93
- rigidBody.lockRotations(lockRotations, true);
94
- rigidBody.lockTranslations(lockTranslations, true);
95
- rigidBody.setEnabledRotations(...enabledRotations, true);
96
- rigidBody.setEnabledTranslations(...enabledTranslations, true);
100
+ rigidBodyTemp.setBodyType(parseRigidBodyType(type));
101
+ rigidBodyTemp.setLinvel(positionToVector3(linearVelocity), true);
102
+ rigidBodyTemp.setAngvel(rotationToEuler(angularVelocity), true);
103
+ rigidBodyTemp.setGravityScale(gravityScale, true);
104
+ rigidBodyTemp.enableCcd(ccd);
105
+ rigidBodyTemp.setDominanceGroup(dominance);
106
+ rigidBodyTemp.lockRotations(lockRotations, true);
107
+ rigidBodyTemp.lockTranslations(lockTranslations, true);
108
+ rigidBodyTemp.setEnabledRotations(...enabledRotations, true);
109
+ rigidBodyTemp.setEnabledTranslations(...enabledTranslations, true);
97
110
  }
111
+ /**
112
+ * Add userData to the rigidBody
113
+ */
114
+ const { hasEventListeners } = useHasEventListeners();
115
+ rigidBodyTemp.userData = {
116
+ hasEventListeners
117
+ };
98
118
  /**
99
119
  * Setting the RigidBody context so that colliders can
100
120
  * hook onto.
101
121
  */
102
- setContext('threlte-rapier-rigidbody', rigidBody);
122
+ setContext('threlte-rapier-rigidbody', rigidBodyTemp);
103
123
  /**
104
124
  * Add the mesh to the context
105
125
  */
106
- addRigidBodyToContext(rigidBody, object, dispatcher);
126
+ addRigidBodyToContext(rigidBodyTemp, object, dispatcher);
107
127
  /**
108
128
  * cleanup
109
129
  */
110
130
  onDestroy(() => {
111
- removeRigidBodyFromContext(rigidBody);
112
- world.removeRigidBody(rigidBody);
131
+ removeRigidBodyFromContext(rigidBodyTemp);
132
+ world.removeRigidBody(rigidBodyTemp);
113
133
  });
114
134
  </script>
115
135
 
@@ -1,8 +1,9 @@
1
1
  import { SvelteComponentTyped } from "svelte";
2
+ import type { RigidBody } from '@dimforge/rapier3d-compat';
2
3
  import type { RigidBodyProperties } from '../../types/components';
3
- import type { RigidBodyEventMap } from '../../types/types';
4
4
  declare const __propDef: {
5
5
  props: {
6
+ debug?: boolean | undefined;
6
7
  type?: import("../../lib/parseRigidBodyType").RigidBodyTypeString | undefined;
7
8
  canSleep?: boolean | undefined;
8
9
  linearVelocity?: import("@threlte/core").Position | undefined;
@@ -19,21 +20,47 @@ declare const __propDef: {
19
20
  enabledTranslations?: import("../../types/components").Boolean3Array | undefined;
20
21
  dominance?: number | undefined;
21
22
  /**
22
- * RigidBody init
23
- */ rigidBody?: import("@dimforge/rapier3d-compat").RigidBody | undefined;
23
+ * Export the rigidBody only after positional initialization
24
+ */ rigidBody?: RigidBody | undefined;
24
25
  };
25
26
  slots: {
26
27
  default: {};
27
28
  };
28
- getters: {
29
- rigidBody: import("@dimforge/rapier3d-compat").RigidBody;
29
+ getters: {};
30
+ events: {
31
+ collisionenter: CustomEvent<{
32
+ targetCollider: import("@dimforge/rapier3d-compat").Collider;
33
+ targetRigidBody: RigidBody | null;
34
+ manifold: import("@dimforge/rapier3d-compat").TempContactManifold;
35
+ flipped: boolean;
36
+ }>;
37
+ collisionexit: CustomEvent<{
38
+ targetCollider: import("@dimforge/rapier3d-compat").Collider;
39
+ targetRigidBody: RigidBody | null;
40
+ }>;
41
+ sensorenter: CustomEvent<{
42
+ targetCollider: import("@dimforge/rapier3d-compat").Collider;
43
+ targetRigidBody: RigidBody | null;
44
+ }>;
45
+ sensorexit: CustomEvent<{
46
+ targetCollider: import("@dimforge/rapier3d-compat").Collider;
47
+ targetRigidBody: RigidBody | null;
48
+ }>;
49
+ contact: CustomEvent<{
50
+ targetCollider: import("@dimforge/rapier3d-compat").Collider;
51
+ targetRigidBody: RigidBody | null;
52
+ maxForceDirection: import("@dimforge/rapier3d-compat").Vector;
53
+ maxForceMagnitude: number;
54
+ totalForce: import("@dimforge/rapier3d-compat").Vector;
55
+ totalForceMagnitude: number;
56
+ }>;
57
+ sleep: CustomEvent<void>;
58
+ wake: CustomEvent<void>;
30
59
  };
31
- events: RigidBodyEventMap;
32
60
  };
33
61
  export declare type RigidBodyProps = typeof __propDef.props;
34
62
  export declare type RigidBodyEvents = typeof __propDef.events;
35
63
  export declare type RigidBodySlots = typeof __propDef.slots;
36
64
  export default class RigidBody extends SvelteComponentTyped<RigidBodyProps, RigidBodyEvents, RigidBodySlots> {
37
- get rigidBody(): import("@dimforge/rapier3d-compat").RigidBody;
38
65
  }
39
66
  export {};
@@ -0,0 +1,7 @@
1
+ import type { FixedImpulseJoint } from '@dimforge/rapier3d-compat';
2
+ import type { Position, Rotation } from '@threlte/core';
3
+ export declare const useFixedJoint: (anchorA: Position, frameA: Rotation, anchorB: Position, frameB: Rotation) => {
4
+ joint: import("svelte/store").Writable<FixedImpulseJoint>;
5
+ rigidBodyA: import("svelte/store").Writable<import("@dimforge/rapier3d-compat").RigidBody | undefined>;
6
+ rigidBodyB: import("svelte/store").Writable<import("@dimforge/rapier3d-compat").RigidBody | undefined>;
7
+ };
@@ -0,0 +1,10 @@
1
+ import { positionToVector3 } from '../lib/positionToVector3';
2
+ import { rotationToQuaternion } from '../lib/rotationToQuaternion';
3
+ import { useJoint } from './useJoint';
4
+ // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
5
+ export const useFixedJoint = (anchorA, frameA, anchorB, frameB) => {
6
+ return useJoint((rbA, rbB, { world, rapier }) => {
7
+ const params = rapier.JointData.fixed(positionToVector3(anchorA), rotationToQuaternion(frameA), positionToVector3(anchorB), rotationToQuaternion(frameB));
8
+ return world.createImpulseJoint(params, rbA, rbB, true);
9
+ });
10
+ };
@@ -1,9 +1,27 @@
1
- import { EventQueue } from '@dimforge/rapier3d-compat';
1
+ import { Collider, EventQueue } from '@dimforge/rapier3d-compat';
2
2
  import { useFrame } from '@threlte/core';
3
3
  import { Object3D, Quaternion, Vector3 } from 'three';
4
4
  const tempObject = new Object3D();
5
5
  const tempVector3 = new Vector3();
6
6
  const tempQuaternion = new Quaternion();
7
+ const getEventDispatchers = (ctx, collider1, collider2) => {
8
+ const colliderDispatcher1 = ctx.colliderEventDispatchers.get(collider1.handle);
9
+ const colliderDispatcher2 = ctx.colliderEventDispatchers.get(collider2.handle);
10
+ const rigidBody1 = collider1.parent();
11
+ const rigidBody2 = collider2.parent();
12
+ const rigidBodyDispatcher1 = rigidBody1
13
+ ? ctx.rigidBodyEventDispatchers.get(rigidBody1.handle)
14
+ : undefined;
15
+ const rigidBodyDispatcher2 = rigidBody2
16
+ ? ctx.rigidBodyEventDispatchers.get(rigidBody2.handle)
17
+ : undefined;
18
+ return {
19
+ colliderDispatcher1,
20
+ colliderDispatcher2,
21
+ rigidBodyDispatcher1,
22
+ rigidBodyDispatcher2
23
+ };
24
+ };
7
25
  export const useFrameHandler = (ctx) => {
8
26
  const eventQueue = new EventQueue(false);
9
27
  let time = performance.now();
@@ -52,6 +70,51 @@ export const useFrameHandler = (ctx) => {
52
70
  mesh.position.setFromMatrixPosition(tempObject.matrix);
53
71
  mesh.rotation.setFromRotationMatrix(tempObject.matrix);
54
72
  });
73
+ eventQueue.drainContactForceEvents((e) => {
74
+ const collider1 = world.getCollider(e.collider1());
75
+ const collider2 = world.getCollider(e.collider2());
76
+ // Sanity check
77
+ if (!collider1 || !collider2) {
78
+ return;
79
+ }
80
+ const { colliderDispatcher1, colliderDispatcher2, rigidBodyDispatcher1, rigidBodyDispatcher2 } = getEventDispatchers(ctx, collider1, collider2);
81
+ const rigidBody1 = collider1.parent();
82
+ const rigidBody2 = collider2.parent();
83
+ // Collider events
84
+ colliderDispatcher1?.('contact', {
85
+ targetCollider: collider2,
86
+ targetRigidBody: rigidBody2,
87
+ maxForceDirection: e.maxForceDirection(),
88
+ maxForceMagnitude: e.maxForceMagnitude(),
89
+ totalForce: e.totalForce(),
90
+ totalForceMagnitude: e.totalForceMagnitude()
91
+ });
92
+ colliderDispatcher2?.('contact', {
93
+ targetCollider: collider1,
94
+ targetRigidBody: rigidBody1,
95
+ maxForceDirection: e.maxForceDirection(),
96
+ maxForceMagnitude: e.maxForceMagnitude(),
97
+ totalForce: e.totalForce(),
98
+ totalForceMagnitude: e.totalForceMagnitude()
99
+ });
100
+ // RigidBody Events
101
+ rigidBodyDispatcher1?.('contact', {
102
+ targetCollider: collider2,
103
+ targetRigidBody: rigidBody2,
104
+ maxForceDirection: e.maxForceDirection(),
105
+ maxForceMagnitude: e.maxForceMagnitude(),
106
+ totalForce: e.totalForce(),
107
+ totalForceMagnitude: e.totalForceMagnitude()
108
+ });
109
+ rigidBodyDispatcher2?.('contact', {
110
+ targetCollider: collider1,
111
+ targetRigidBody: rigidBody1,
112
+ maxForceDirection: e.maxForceDirection(),
113
+ maxForceMagnitude: e.maxForceMagnitude(),
114
+ totalForce: e.totalForce(),
115
+ totalForceMagnitude: e.totalForceMagnitude()
116
+ });
117
+ });
55
118
  // Collision events
56
119
  eventQueue.drainCollisionEvents((handle1, handle2, started) => {
57
120
  const collider1 = world.getCollider(handle1);
@@ -60,16 +123,9 @@ export const useFrameHandler = (ctx) => {
60
123
  if (!collider1 || !collider2) {
61
124
  return;
62
125
  }
63
- const colliderDispatcher1 = ctx.colliderEventDispatchers.get(collider1.handle);
64
- const colliderDispatcher2 = ctx.colliderEventDispatchers.get(collider2.handle);
126
+ const { colliderDispatcher1, colliderDispatcher2, rigidBodyDispatcher1, rigidBodyDispatcher2 } = getEventDispatchers(ctx, collider1, collider2);
65
127
  const rigidBody1 = collider1.parent();
66
128
  const rigidBody2 = collider2.parent();
67
- const rigidBodyDispatcher1 = rigidBody1
68
- ? ctx.rigidBodyEventDispatchers.get(rigidBody1.handle)
69
- : undefined;
70
- const rigidBodyDispatcher2 = rigidBody2
71
- ? ctx.rigidBodyEventDispatchers.get(rigidBody2.handle)
72
- : undefined;
73
129
  if (started) {
74
130
  // intersections are triggered by sensors
75
131
  const isIntersection = world.intersectionPair(collider1, collider2);
@@ -0,0 +1,3 @@
1
+ export declare const useHasEventListeners: <T extends (type: any) => any = any>() => {
2
+ hasEventListeners: (type: Parameters<T>[0]) => boolean;
3
+ };
@@ -0,0 +1,11 @@
1
+ import { get_current_component } from 'svelte/internal';
2
+ export const useHasEventListeners = () => {
3
+ const component = get_current_component();
4
+ const hasEventListeners = (type) => {
5
+ const callbacks = component.$$.callbacks;
6
+ return type in callbacks && callbacks[type].length > 0;
7
+ };
8
+ return {
9
+ hasEventListeners
10
+ };
11
+ };
@@ -0,0 +1,7 @@
1
+ import type { ImpulseJoint, RigidBody } from '@dimforge/rapier3d-compat';
2
+ import type { RapierContext } from '../types/types';
3
+ export declare const useJoint: <T extends ImpulseJoint>(initializeJoint: (rigidBodyA: RigidBody, rigidBodyB: RigidBody, ctx: RapierContext) => T) => {
4
+ joint: import("svelte/store").Writable<T>;
5
+ rigidBodyA: import("svelte/store").Writable<RigidBody | undefined>;
6
+ rigidBodyB: import("svelte/store").Writable<RigidBody | undefined>;
7
+ };
@@ -0,0 +1,31 @@
1
+ import { onDestroy } from 'svelte';
2
+ import { derived, get, writable } from 'svelte/store';
3
+ import { useRapier } from './useRapier';
4
+ // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
5
+ export const useJoint = (initializeJoint) => {
6
+ const rigidBodyA = writable(undefined);
7
+ const rigidBodyB = writable(undefined);
8
+ const ctx = useRapier();
9
+ const bodies = derived([rigidBodyA, rigidBodyB], ([rbA, rbB]) => {
10
+ if (!!rbA && !!rbB) {
11
+ return [rbA, rbB];
12
+ }
13
+ });
14
+ const joint = writable(undefined);
15
+ const unsubscribeBodies = bodies.subscribe((bodies) => {
16
+ if (bodies)
17
+ joint.set(initializeJoint(...bodies, ctx));
18
+ });
19
+ onDestroy(() => {
20
+ unsubscribeBodies();
21
+ const j = get(joint);
22
+ if (!j)
23
+ return;
24
+ ctx.world.removeImpulseJoint(j, true);
25
+ });
26
+ return {
27
+ joint,
28
+ rigidBodyA,
29
+ rigidBodyB
30
+ };
31
+ };
@@ -0,0 +1,7 @@
1
+ import type { PrismaticImpulseJoint } from '@dimforge/rapier3d-compat';
2
+ import type { Position } from '@threlte/core';
3
+ export declare const usePrismaticJoint: (anchorA: Position, anchorB: Position, axis: Position, limits?: [min: number, max: number]) => {
4
+ joint: import("svelte/store").Writable<PrismaticImpulseJoint>;
5
+ rigidBodyA: import("svelte/store").Writable<import("@dimforge/rapier3d-compat").RigidBody | undefined>;
6
+ rigidBodyB: import("svelte/store").Writable<import("@dimforge/rapier3d-compat").RigidBody | undefined>;
7
+ };
@@ -0,0 +1,13 @@
1
+ import { positionToVector3 } from '../lib/positionToVector3';
2
+ import { useJoint } from './useJoint';
3
+ // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
4
+ export const usePrismaticJoint = (anchorA, anchorB, axis, limits) => {
5
+ return useJoint((rbA, rbB, { world, rapier }) => {
6
+ const params = rapier.JointData.prismatic(positionToVector3(anchorA), positionToVector3(anchorB), positionToVector3(axis).normalize());
7
+ if (limits) {
8
+ params.limitsEnabled = true;
9
+ params.limits = limits;
10
+ }
11
+ return world.createImpulseJoint(params, rbA, rbB, true);
12
+ });
13
+ };
@@ -0,0 +1,7 @@
1
+ import type { RevoluteImpulseJoint } from '@dimforge/rapier3d-compat';
2
+ import type { Position } from '@threlte/core';
3
+ export declare const useRevoluteJoint: (anchorA: Position, anchorB: Position, axis: Position, limits?: [min: number, max: number]) => {
4
+ joint: import("svelte/store").Writable<RevoluteImpulseJoint>;
5
+ rigidBodyA: import("svelte/store").Writable<import("@dimforge/rapier3d-compat").RigidBody | undefined>;
6
+ rigidBodyB: import("svelte/store").Writable<import("@dimforge/rapier3d-compat").RigidBody | undefined>;
7
+ };
@@ -0,0 +1,13 @@
1
+ import { positionToVector3 } from '../lib/positionToVector3';
2
+ import { useJoint } from './useJoint';
3
+ // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
4
+ export const useRevoluteJoint = (anchorA, anchorB, axis, limits) => {
5
+ return useJoint((rbA, rbB, { world, rapier }) => {
6
+ const params = rapier.JointData.revolute(positionToVector3(anchorA), positionToVector3(anchorB), positionToVector3(axis).normalize());
7
+ if (limits) {
8
+ params.limitsEnabled = true;
9
+ params.limits = limits;
10
+ }
11
+ return world.createImpulseJoint(params, rbA, rbB, true);
12
+ });
13
+ };
@@ -1,2 +1,2 @@
1
1
  import type { RigidBodyContext } from '../types/types';
2
- export declare const useRigidBody: () => RigidBodyContext;
2
+ export declare const useRigidBody: () => RigidBodyContext | undefined;
@@ -0,0 +1,7 @@
1
+ import type { SphericalImpulseJoint } from '@dimforge/rapier3d-compat';
2
+ import type { Position } from '@threlte/core';
3
+ export declare const useSphericalJoint: (anchorA: Position, anchorB: Position) => {
4
+ joint: import("svelte/store").Writable<SphericalImpulseJoint>;
5
+ rigidBodyA: import("svelte/store").Writable<import("@dimforge/rapier3d-compat").RigidBody | undefined>;
6
+ rigidBodyB: import("svelte/store").Writable<import("@dimforge/rapier3d-compat").RigidBody | undefined>;
7
+ };
@@ -0,0 +1,11 @@
1
+ import { navigating } from '$app/stores';
2
+ import { positionToVector3 } from '../lib/positionToVector3';
3
+ import { useJoint } from './useJoint';
4
+ // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
5
+ export const useSphericalJoint = (anchorA, anchorB) => {
6
+ return useJoint((rbA, rbB, { world, rapier }) => {
7
+ const params = rapier.JointData.spherical(positionToVector3(anchorA), positionToVector3(anchorB));
8
+ return world.createImpulseJoint(params, rbA, rbB, true);
9
+ });
10
+ };
11
+ navigating;
package/dist/index.d.ts CHANGED
@@ -1,6 +1,10 @@
1
1
  export { useRapier } from './hooks/useRapier';
2
2
  export { useCollisionGroups } from './hooks/useCollisionGroups';
3
3
  export { useRigidBody } from './hooks/useRigidBody';
4
+ export { useRevoluteJoint } from './hooks/useRevoluteJoint';
5
+ export { usePrismaticJoint } from './hooks/usePrismaticJoint';
6
+ export { useFixedJoint } from './hooks/useFixedJoint';
7
+ export { useSphericalJoint } from './hooks/useSphericalJoint';
4
8
  export { default as World } from './components/World/World.svelte';
5
9
  export { default as RigidBody } from './components/RigidBody/RigidBody.svelte';
6
10
  export { default as Debug } from './components/Debug/Debug.svelte';
@@ -8,5 +12,5 @@ export { default as Collider } from './components/Colliders/Collider.svelte';
8
12
  export { default as AutoColliders } from './components/Colliders/AutoColliders.svelte';
9
13
  export { default as CollisionGroups } from './components/CollisionGroups/CollisionGroups.svelte';
10
14
  export { default as BasicPlayerController } from './recipes/BasicPlayerController.svelte';
11
- export type { AutoCollidersProperties, ColliderProperties, Boolean3Array, RigidBodyProperties, WorldProperties } from './types/components';
12
- export type { CollisionGroupsBitMask, AutoCollidersShapes, ColliderEventDispatcher, ColliderShapes, RapierContext, RigidBodyEventDispatcher } from './types/types';
15
+ export type { AutoCollidersProperties, Boolean3Array, RigidBodyProperties, WorldProperties } from './types/components';
16
+ export type { CollisionGroupsBitMask, AutoCollidersShapes, ColliderEventDispatcher, ColliderShapes, RapierContext, RigidBodyEventDispatcher, CollisionEnterEvent, CollisionExitEvent, SensorEnterEvent, SensorExitEvent, ContactEvent } from './types/types';
package/dist/index.js CHANGED
@@ -2,6 +2,11 @@
2
2
  export { useRapier } from './hooks/useRapier';
3
3
  export { useCollisionGroups } from './hooks/useCollisionGroups';
4
4
  export { useRigidBody } from './hooks/useRigidBody';
5
+ // Joints
6
+ export { useRevoluteJoint } from './hooks/useRevoluteJoint';
7
+ export { usePrismaticJoint } from './hooks/usePrismaticJoint';
8
+ export { useFixedJoint } from './hooks/useFixedJoint';
9
+ export { useSphericalJoint } from './hooks/useSphericalJoint';
5
10
  // components
6
11
  export { default as World } from './components/World/World.svelte';
7
12
  export { default as RigidBody } from './components/RigidBody/RigidBody.svelte';
@@ -0,0 +1,4 @@
1
+ import { type Collider } from '@dimforge/rapier3d-compat';
2
+ import type { useHasEventListeners } from '../hooks/useHasEventListener';
3
+ import type { ColliderEventDispatcher, RigidBodyEventDispatcher } from '../types/types';
4
+ export declare const applyColliderActiveEvents: (collider: Collider, colliderHasEventListeners: ReturnType<typeof useHasEventListeners<ColliderEventDispatcher>>['hasEventListeners'], rigidBodyHasEventListeners?: ReturnType<typeof useHasEventListeners<RigidBodyEventDispatcher>>['hasEventListeners']) => void;
@@ -0,0 +1,20 @@
1
+ import { ActiveEvents } from '@dimforge/rapier3d-compat';
2
+ export const applyColliderActiveEvents = (collider, colliderHasEventListeners, rigidBodyHasEventListeners) => {
3
+ let events = 0;
4
+ if (colliderHasEventListeners('collisionenter') ||
5
+ colliderHasEventListeners('collisionexit') ||
6
+ rigidBodyHasEventListeners?.('collisionenter') ||
7
+ rigidBodyHasEventListeners?.('collisionexit') ||
8
+ colliderHasEventListeners('sensorenter') ||
9
+ colliderHasEventListeners('sensorexit') ||
10
+ rigidBodyHasEventListeners?.('sensorenter') ||
11
+ rigidBodyHasEventListeners?.('sensorexit')) {
12
+ events = events | ActiveEvents.COLLISION_EVENTS;
13
+ }
14
+ if (colliderHasEventListeners('contact') || rigidBodyHasEventListeners?.('contact')) {
15
+ events = events | ActiveEvents.CONTACT_FORCE_EVENTS;
16
+ }
17
+ if (events > 0) {
18
+ collider.setActiveEvents(events);
19
+ }
20
+ };
@@ -72,6 +72,7 @@ export declare type ColliderProperties<Shape extends ColliderShapes> = Omit<Tran
72
72
  * More info https://rapier.rs/docs/user_guides/javascript/colliders#mass-properties
73
73
  */
74
74
  mass?: number;
75
+ density?: number;
75
76
  /**
76
77
  * The center of mass of this rigid body
77
78
  */
@@ -1,7 +1,8 @@
1
1
  import type { createEventDispatcher } from 'svelte';
2
- import type { RigidBody, RigidBodyHandle, TempContactManifold, ColliderHandle, Collider } from '@dimforge/rapier3d-compat';
2
+ import type { RigidBody, RigidBodyHandle, TempContactManifold, ColliderHandle, Collider, Vector } from '@dimforge/rapier3d-compat';
3
3
  import type { createRapierContext } from '../lib/createRapierContext';
4
4
  import type { Writable } from 'svelte/store';
5
+ import type { useHasEventListeners } from '../hooks/useHasEventListener';
5
6
  export declare type ColliderShapes = 'ball' | 'capsule' | 'segment' | 'triangle' | 'roundTriangle' | 'polyline' | 'trimesh' | 'cuboid' | 'roundCuboid' | 'heightfield' | 'cylinder' | 'roundCylinder' | 'cone' | 'roundCone' | 'convexHull' | 'convexMesh' | 'roundConvexHull' | 'roundConvexMesh';
6
7
  export declare type AutoCollidersShapes = 'cuboid' | 'ball' | 'trimesh' | 'convexHull' | 'capsule';
7
8
  export declare type ColliderEventMap = {
@@ -23,7 +24,20 @@ export declare type ColliderEventMap = {
23
24
  targetCollider: Collider;
24
25
  targetRigidBody: RigidBody | null;
25
26
  };
27
+ contact: {
28
+ targetCollider: Collider;
29
+ targetRigidBody: RigidBody | null;
30
+ maxForceDirection: Vector;
31
+ maxForceMagnitude: number;
32
+ totalForce: Vector;
33
+ totalForceMagnitude: number;
34
+ };
26
35
  };
36
+ export declare type CollisionEnterEvent = CustomEvent<ColliderEventMap['collisionenter']>;
37
+ export declare type CollisionExitEvent = CustomEvent<ColliderEventMap['collisionexit']>;
38
+ export declare type SensorEnterEvent = CustomEvent<ColliderEventMap['sensorenter']>;
39
+ export declare type SensorExitEvent = CustomEvent<ColliderEventMap['sensorexit']>;
40
+ export declare type ContactEvent = CustomEvent<ColliderEventMap['contact']>;
27
41
  export declare type RigidBodyEventMap = ColliderEventMap & {
28
42
  sleep: void;
29
43
  wake: void;
@@ -34,5 +48,11 @@ export declare type RigidBodyEventDispatchers = Map<RigidBodyHandle, RigidBodyEv
34
48
  export declare type ColliderEventDispatchers = Map<ColliderHandle, ColliderEventDispatcher>;
35
49
  export declare type RapierContext = ReturnType<typeof createRapierContext>;
36
50
  export declare type CollisionGroupsContext = Writable<number> | undefined;
37
- export declare type RigidBodyContext = RigidBody;
51
+ export declare type RigidBodyUserData = {
52
+ hasEventListeners?: ReturnType<typeof useHasEventListeners<RigidBodyEventDispatcher>>['hasEventListeners'];
53
+ };
54
+ export declare type ThrelteRigidBody = RigidBody & {
55
+ userData?: RigidBodyUserData;
56
+ };
57
+ export declare type RigidBodyContext = ThrelteRigidBody;
38
58
  export declare type CollisionGroupsBitMask = (0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15)[];
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@threlte/rapier",
3
- "version": "0.0.3",
3
+ "version": "0.3.0",
4
4
  "author": "Grischa Erbe <hello@legrisch.com> (https://legrisch.com)",
5
5
  "license": "MIT",
6
6
  "devDependencies": {
@@ -8,7 +8,7 @@
8
8
  "@sveltejs/adapter-auto": "next",
9
9
  "@sveltejs/adapter-static": "^1.0.0-next.29",
10
10
  "@sveltejs/kit": "next",
11
- "@threlte/core": "4.3.1",
11
+ "@threlte/core": "4.3.2",
12
12
  "@types/node": "^18.0.3",
13
13
  "@types/three": "^0.140.0",
14
14
  "@typescript-eslint/eslint-plugin": "^4.31.1",
@@ -1,33 +0,0 @@
1
- import { SvelteComponentTyped } from "svelte";
2
- import { type Collider } from '@dimforge/rapier3d-compat';
3
- import type { AutoCollidersProperties } from '../../types/components';
4
- import type { ColliderEventMap } from '../../types/types';
5
- declare const __propDef: {
6
- props: {
7
- shape?: import("../../types/types").AutoCollidersShapes | undefined;
8
- position?: AutoCollidersProperties['position'];
9
- rotation?: AutoCollidersProperties['rotation'];
10
- scale?: AutoCollidersProperties['scale'];
11
- lookAt?: AutoCollidersProperties['lookAt'];
12
- mass?: AutoCollidersProperties['mass'];
13
- centerOfMass?: AutoCollidersProperties['centerOfMass'];
14
- principalAngularInertia?: AutoCollidersProperties['principalAngularInertia'];
15
- restitution?: AutoCollidersProperties['restitution'];
16
- restitutionCombineRule?: AutoCollidersProperties['restitutionCombineRule'];
17
- friction?: AutoCollidersProperties['friction'];
18
- frictionCombineRule?: AutoCollidersProperties['frictionCombineRule'];
19
- sensor?: AutoCollidersProperties['sensor'];
20
- colliders?: Collider[] | undefined;
21
- };
22
- slots: {
23
- default: {};
24
- };
25
- getters: {};
26
- events: ColliderEventMap;
27
- };
28
- export declare type AutoCollidersProps = typeof __propDef.props;
29
- export declare type AutoCollidersEvents = typeof __propDef.events;
30
- export declare type AutoCollidersSlots = typeof __propDef.slots;
31
- export default class AutoColliders extends SvelteComponentTyped<AutoCollidersProps, AutoCollidersEvents, AutoCollidersSlots> {
32
- }
33
- export {};