@threlte/rapier 1.1.4 → 3.0.0-next.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/components/Attractor/Attractor.svelte +7 -6
- package/dist/components/Attractor/Attractor.svelte.d.ts +2 -2
- package/dist/components/Colliders/AutoColliders.svelte +9 -25
- package/dist/components/Colliders/AutoColliders.svelte.d.ts +4 -4
- package/dist/components/Colliders/Collider.svelte +49 -53
- package/dist/components/Colliders/Collider.svelte.d.ts +4 -4
- package/dist/components/CollisionGroups/CollisionGroups.svelte +1 -1
- package/dist/components/Debug/Debug.svelte +2 -2
- package/dist/components/RigidBody/RigidBody.svelte +41 -57
- package/dist/components/RigidBody/RigidBody.svelte.d.ts +2 -2
- package/dist/components/World/InnerWorld.svelte +4 -4
- package/dist/components/World/InnerWorld.svelte.d.ts +4 -19
- package/dist/components/World/World.svelte +8 -8
- package/dist/components/World/World.svelte.d.ts +4 -3
- package/dist/hooks/useFrameHandler.d.ts +2 -1
- package/dist/hooks/useFrameHandler.js +42 -39
- package/dist/hooks/useHasEventListener.js +4 -4
- package/dist/lib/applyColliderActiveEvents.d.ts +1 -3
- package/dist/lib/applyColliderActiveEvents.js +10 -10
- package/dist/lib/createCollidersFromChildren.js +2 -2
- package/dist/lib/createRapierContext.d.ts +3 -3
- package/dist/lib/createRapierContext.js +4 -4
- package/dist/lib/getWorldTransforms.js +1 -1
- package/dist/lib/useCreateEvent.d.ts +1 -1
- package/dist/lib/useCreateEvent.js +2 -4
- package/dist/recipes/BasicPlayerController.svelte +31 -17
- package/dist/recipes/BasicPlayerController.svelte.d.ts +5 -2
- package/dist/types/types.d.ts +4 -7
- package/package.json +31 -27
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
<script>import { T,
|
|
1
|
+
<script lang="ts">import { T, useTask } from '@threlte/core';
|
|
2
2
|
import { Group, Vector3 } from 'three';
|
|
3
3
|
import { useRapier } from '../../hooks/useRapier';
|
|
4
4
|
export let strength = 1;
|
|
@@ -13,14 +13,15 @@ const calcForceByType = {
|
|
|
13
13
|
linear: (s, m2, r, d, G) => s * (d / r),
|
|
14
14
|
newtonian: (s, m2, r, d, G) => (G * s * m2) / Math.pow(d, 2)
|
|
15
15
|
};
|
|
16
|
+
const impulseVector = new Vector3();
|
|
17
|
+
const bodyV3 = new Vector3();
|
|
16
18
|
function applyImpulseToBodiesInRange() {
|
|
17
|
-
const impulseVector = new Vector3();
|
|
18
19
|
obj.getWorldPosition(gravitySource);
|
|
19
20
|
world.forEachRigidBody((body) => {
|
|
20
21
|
const { x, y, z } = body.translation();
|
|
21
|
-
|
|
22
|
-
const distance = gravitySource.
|
|
23
|
-
if (distance < range) {
|
|
22
|
+
bodyV3.set(x, y, z);
|
|
23
|
+
const distance = gravitySource.distanceToSquared(bodyV3);
|
|
24
|
+
if (distance < range ** 2) {
|
|
24
25
|
let force = calcForceByType[gravityType](strength, body.mass(), range, distance, gravitationalConstant);
|
|
25
26
|
// Prevent wild forces when Attractors collide
|
|
26
27
|
force = force === Infinity ? strength : force;
|
|
@@ -29,7 +30,7 @@ function applyImpulseToBodiesInRange() {
|
|
|
29
30
|
}
|
|
30
31
|
});
|
|
31
32
|
}
|
|
32
|
-
|
|
33
|
+
useTask(() => {
|
|
33
34
|
applyImpulseToBodiesInRange();
|
|
34
35
|
});
|
|
35
36
|
</script>
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Props, type Events, type Slots } from '@threlte/core'
|
|
2
|
-
import {
|
|
2
|
+
import { SvelteComponent } from 'svelte'
|
|
3
3
|
import type { Group } from 'three'
|
|
4
4
|
import type { GravityType } from '../../types/types'
|
|
5
5
|
|
|
@@ -35,7 +35,7 @@ type AttractorEvents = Events<Group>
|
|
|
35
35
|
|
|
36
36
|
type AttractorSlots = Slots<Group>
|
|
37
37
|
|
|
38
|
-
export default class Attractor extends
|
|
38
|
+
export default class Attractor extends SvelteComponent<
|
|
39
39
|
AttractorProps,
|
|
40
40
|
AttractorEvents,
|
|
41
41
|
AttractorSlots
|
|
@@ -1,9 +1,8 @@
|
|
|
1
|
-
<script>import { ActiveCollisionTypes, CoefficientCombineRule } from '@dimforge/rapier3d-compat';
|
|
2
|
-
import {
|
|
1
|
+
<script lang="ts">import { ActiveCollisionTypes, CoefficientCombineRule } from '@dimforge/rapier3d-compat';
|
|
2
|
+
import { SceneGraphObject } from '@threlte/core';
|
|
3
3
|
import { onDestroy, onMount } from 'svelte';
|
|
4
4
|
import { Group } from 'three';
|
|
5
5
|
import { useCollisionGroups } from '../../hooks/useCollisionGroups';
|
|
6
|
-
import { useHasEventListeners } from '../../hooks/useHasEventListener';
|
|
7
6
|
import { useRapier } from '../../hooks/useRapier';
|
|
8
7
|
import { useRigidBody } from '../../hooks/useRigidBody';
|
|
9
8
|
import { useCreateEvent } from '../../lib/useCreateEvent';
|
|
@@ -11,28 +10,16 @@ import { useParentRigidbodyObject } from '../../lib/rigidBodyObjectContext';
|
|
|
11
10
|
import { applyColliderActiveEvents } from '../../lib/applyColliderActiveEvents';
|
|
12
11
|
import { createCollidersFromChildren } from '../../lib/createCollidersFromChildren';
|
|
13
12
|
import { eulerToQuaternion } from '../../lib/eulerToQuaternion';
|
|
14
|
-
|
|
15
|
-
export let restitution = undefined;
|
|
16
|
-
export let restitutionCombineRule = undefined;
|
|
17
|
-
export let friction = undefined;
|
|
18
|
-
export let frictionCombineRule = undefined;
|
|
19
|
-
export let sensor = undefined;
|
|
20
|
-
export let contactForceEventThreshold = undefined;
|
|
21
|
-
export let density = undefined;
|
|
22
|
-
export let mass = undefined;
|
|
23
|
-
export let centerOfMass = undefined;
|
|
24
|
-
export let principalAngularInertia = undefined;
|
|
25
|
-
export let angularInertiaLocalFrame = undefined;
|
|
13
|
+
let { shape = 'convexHull', restitution, restitutionCombineRule, friction, frictionCombineRule, sensor, contactForceEventThreshold, density, mass, centerOfMass, principalAngularInertia, angularInertiaLocalFrame, refresh = $bindable(() => create()), colliders = $bindable(), ...props } = $props();
|
|
26
14
|
const group = new Group();
|
|
27
|
-
const { updateRef } = useCreateEvent();
|
|
15
|
+
const { updateRef } = useCreateEvent(props.$$events);
|
|
28
16
|
const rigidBody = useRigidBody();
|
|
29
17
|
const rigidBodyParentObject = useParentRigidbodyObject();
|
|
30
18
|
const { world, addColliderToContext, removeColliderFromContext } = useRapier();
|
|
31
|
-
export let colliders = [];
|
|
32
19
|
const collisionGroups = useCollisionGroups();
|
|
33
|
-
const dispatcher = createRawEventDispatcher();
|
|
34
|
-
const { hasEventListeners: colliderHasEventListeners } = useHasEventListeners();
|
|
35
20
|
const cleanup = () => {
|
|
21
|
+
if (colliders === undefined)
|
|
22
|
+
return;
|
|
36
23
|
collisionGroups.removeColliders(colliders);
|
|
37
24
|
colliders.forEach((c) => {
|
|
38
25
|
removeColliderFromContext(c);
|
|
@@ -40,13 +27,13 @@ const cleanup = () => {
|
|
|
40
27
|
});
|
|
41
28
|
colliders.length = 0;
|
|
42
29
|
};
|
|
43
|
-
|
|
30
|
+
const create = () => {
|
|
44
31
|
cleanup();
|
|
45
32
|
colliders = createCollidersFromChildren(group, shape ?? 'convexHull', world, rigidBody, rigidBodyParentObject);
|
|
46
|
-
colliders.forEach((c) => addColliderToContext(c, group,
|
|
33
|
+
colliders.forEach((c) => addColliderToContext(c, group, props.$$events));
|
|
47
34
|
collisionGroups.registerColliders(colliders);
|
|
48
35
|
colliders.forEach((collider) => {
|
|
49
|
-
applyColliderActiveEvents(collider,
|
|
36
|
+
applyColliderActiveEvents(collider, props.$$events, rigidBody?.userData?.events);
|
|
50
37
|
collider.setActiveCollisionTypes(ActiveCollisionTypes.ALL);
|
|
51
38
|
collider.setRestitution(restitution ?? 0);
|
|
52
39
|
collider.setRestitutionCombineRule(restitutionCombineRule ?? CoefficientCombineRule.Average);
|
|
@@ -72,9 +59,6 @@ export const create = () => {
|
|
|
72
59
|
onMount(() => {
|
|
73
60
|
create();
|
|
74
61
|
});
|
|
75
|
-
export const refresh = () => {
|
|
76
|
-
create();
|
|
77
|
-
};
|
|
78
62
|
/**
|
|
79
63
|
* Cleanup
|
|
80
64
|
*/
|
|
@@ -57,10 +57,10 @@ export type MassDef = Density | Mass | MassProperties | NoMassProperties
|
|
|
57
57
|
type MassProps<TMassDef extends MassDef> = TMassDef extends Density
|
|
58
58
|
? Density
|
|
59
59
|
: TMassDef extends MassProperties
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
60
|
+
? MassProperties
|
|
61
|
+
: TMassDef extends Mass
|
|
62
|
+
? Mass
|
|
63
|
+
: NoMassProperties
|
|
64
64
|
|
|
65
65
|
// ------------------ COLLIDER ------------------
|
|
66
66
|
|
|
@@ -1,9 +1,8 @@
|
|
|
1
|
-
<script>import { ActiveCollisionTypes, CoefficientCombineRule, Collider, ColliderDesc } from '@dimforge/rapier3d-compat';
|
|
2
|
-
import {
|
|
1
|
+
<script lang="ts">import { ActiveCollisionTypes, CoefficientCombineRule, Collider, ColliderDesc } from '@dimforge/rapier3d-compat';
|
|
2
|
+
import { SceneGraphObject, useTask } from '@threlte/core';
|
|
3
3
|
import { 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';
|
|
7
6
|
import { useRapier } from '../../hooks/useRapier';
|
|
8
7
|
import { useRigidBody } from '../../hooks/useRigidBody';
|
|
9
8
|
import { useParentRigidbodyObject } from '../../lib/rigidBodyObjectContext';
|
|
@@ -12,30 +11,20 @@ import { applyColliderActiveEvents } from '../../lib/applyColliderActiveEvents';
|
|
|
12
11
|
import { eulerToQuaternion } from '../../lib/eulerToQuaternion';
|
|
13
12
|
import { getWorldPosition, getWorldQuaternion } from '../../lib/getWorldTransforms';
|
|
14
13
|
import { scaleColliderArgs } from '../../lib/scaleColliderArgs';
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
export let frictionCombineRule = undefined;
|
|
22
|
-
export let sensor = undefined;
|
|
23
|
-
export let contactForceEventThreshold = undefined;
|
|
24
|
-
export let density = undefined;
|
|
25
|
-
export let mass = undefined;
|
|
26
|
-
export let centerOfMass = undefined;
|
|
27
|
-
export let principalAngularInertia = undefined;
|
|
28
|
-
export let angularInertiaLocalFrame = undefined;
|
|
14
|
+
let { shape, args, type, restitution, restitutionCombineRule, friction, frictionCombineRule, sensor, contactForceEventThreshold, density, mass, centerOfMass, principalAngularInertia, angularInertiaLocalFrame, collider = $bindable(), refresh = $bindable(() => {
|
|
15
|
+
if (!collider)
|
|
16
|
+
return;
|
|
17
|
+
collider.setTranslation(getWorldPosition(object));
|
|
18
|
+
collider.setRotation(getWorldQuaternion(object));
|
|
19
|
+
}), ...props } = $props();
|
|
29
20
|
const object = new Object3D();
|
|
30
|
-
const { updateRef } = useCreateEvent();
|
|
21
|
+
const { updateRef } = useCreateEvent(props.$$events);
|
|
31
22
|
const rigidBody = useRigidBody();
|
|
32
23
|
const parentRigidBodyObject = useParentRigidbodyObject();
|
|
33
24
|
const hasRigidBodyParent = !!rigidBody;
|
|
34
25
|
const rapierContext = useRapier();
|
|
35
26
|
const { world } = rapierContext;
|
|
36
|
-
export let collider = undefined;
|
|
37
27
|
const collisionGroups = useCollisionGroups();
|
|
38
|
-
const dispatcher = createRawEventDispatcher();
|
|
39
28
|
/**
|
|
40
29
|
* Actual collider setup happens onMount as only then
|
|
41
30
|
* the transforms are finished.
|
|
@@ -52,7 +41,7 @@ onMount(async () => {
|
|
|
52
41
|
/**
|
|
53
42
|
* Add collider to context
|
|
54
43
|
*/
|
|
55
|
-
rapierContext.addColliderToContext(collider, object,
|
|
44
|
+
rapierContext.addColliderToContext(collider, object, props.$$events);
|
|
56
45
|
/**
|
|
57
46
|
* For use in conjunction with component <CollisionGroups>
|
|
58
47
|
*/
|
|
@@ -75,51 +64,58 @@ onMount(async () => {
|
|
|
75
64
|
collider.setRotation(object.getWorldQuaternion(new Quaternion()));
|
|
76
65
|
}
|
|
77
66
|
});
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
67
|
+
$effect.pre(() => {
|
|
68
|
+
collider?.setRestitution(restitution ?? 0);
|
|
69
|
+
});
|
|
70
|
+
$effect.pre(() => {
|
|
71
|
+
collider?.setRestitutionCombineRule(restitutionCombineRule ?? CoefficientCombineRule.Average);
|
|
72
|
+
});
|
|
73
|
+
$effect.pre(() => {
|
|
74
|
+
collider?.setFriction(friction ?? 0.7);
|
|
75
|
+
});
|
|
76
|
+
$effect.pre(() => {
|
|
77
|
+
collider?.setFrictionCombineRule(frictionCombineRule ?? CoefficientCombineRule.Average);
|
|
78
|
+
});
|
|
79
|
+
$effect.pre(() => collider?.setSensor(sensor ?? false));
|
|
80
|
+
$effect.pre(() => collider?.setContactForceEventThreshold(contactForceEventThreshold ?? 0));
|
|
81
|
+
$effect.pre(() => {
|
|
82
|
+
if (density !== undefined)
|
|
83
|
+
collider?.setDensity(density);
|
|
84
|
+
});
|
|
85
|
+
$effect.pre(() => {
|
|
86
|
+
if (collider && mass) {
|
|
87
|
+
if (centerOfMass && principalAngularInertia && angularInertiaLocalFrame) {
|
|
88
|
+
collider.setMassProperties(mass, { x: centerOfMass[0], y: centerOfMass[1], z: centerOfMass[2] }, {
|
|
89
|
+
x: principalAngularInertia[0],
|
|
90
|
+
y: principalAngularInertia[1],
|
|
91
|
+
z: principalAngularInertia[2]
|
|
92
|
+
}, eulerToQuaternion(angularInertiaLocalFrame));
|
|
93
|
+
}
|
|
94
|
+
else {
|
|
95
|
+
collider.setMass(mass);
|
|
96
|
+
}
|
|
94
97
|
}
|
|
95
|
-
|
|
96
|
-
|
|
98
|
+
});
|
|
99
|
+
$effect.pre(() => {
|
|
100
|
+
if (collider) {
|
|
101
|
+
applyColliderActiveEvents(collider, props.$$events, rigidBody?.userData?.events);
|
|
97
102
|
}
|
|
98
|
-
}
|
|
99
|
-
$: if (collider) {
|
|
100
|
-
applyColliderActiveEvents(collider, colliderHasEventListeners, rigidBody?.userData?.hasEventListeners);
|
|
101
|
-
}
|
|
102
|
-
export const refresh = () => {
|
|
103
|
-
if (!collider)
|
|
104
|
-
return;
|
|
105
|
-
collider.setTranslation(getWorldPosition(object));
|
|
106
|
-
collider.setRotation(getWorldQuaternion(object));
|
|
107
|
-
};
|
|
103
|
+
});
|
|
108
104
|
/**
|
|
109
105
|
* If the Collider isAttached (i.e. NOT child of a RigidBody), update the
|
|
110
106
|
* transforms on every frame.
|
|
111
107
|
*/
|
|
112
|
-
const { start, stop } =
|
|
108
|
+
const { start, stop } = useTask(() => {
|
|
113
109
|
refresh();
|
|
114
110
|
}, {
|
|
115
|
-
|
|
111
|
+
autoStart: !hasRigidBodyParent && type === 'dynamic'
|
|
116
112
|
});
|
|
117
|
-
|
|
113
|
+
$effect.pre(() => {
|
|
118
114
|
if (!hasRigidBodyParent && type === 'dynamic')
|
|
119
115
|
start();
|
|
120
116
|
else
|
|
121
117
|
stop();
|
|
122
|
-
}
|
|
118
|
+
});
|
|
123
119
|
/**
|
|
124
120
|
* Cleanup
|
|
125
121
|
*/
|
|
@@ -89,10 +89,10 @@ export type MassDef = Density | Mass | MassProperties | NoMassProperties
|
|
|
89
89
|
type MassProps<TMassDef extends MassDef> = TMassDef extends Density
|
|
90
90
|
? Density
|
|
91
91
|
: TMassDef extends MassProperties
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
92
|
+
? MassProperties
|
|
93
|
+
: TMassDef extends Mass
|
|
94
|
+
? Mass
|
|
95
|
+
: NoMassProperties
|
|
96
96
|
|
|
97
97
|
// ------------------ COLLIDER ------------------
|
|
98
98
|
|
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
<script>import { T,
|
|
1
|
+
<script lang="ts">import { T, useTask } from '@threlte/core';
|
|
2
2
|
import { onDestroy } from 'svelte';
|
|
3
3
|
import { BufferAttribute, BufferGeometry } from 'three';
|
|
4
4
|
import { useRapier } from '../../hooks/useRapier';
|
|
5
5
|
const { world, debug } = useRapier();
|
|
6
6
|
const geometry = new BufferGeometry();
|
|
7
7
|
debug.set(true);
|
|
8
|
-
|
|
8
|
+
useTask(() => {
|
|
9
9
|
const buffers = world.debugRender();
|
|
10
10
|
const vertices = new BufferAttribute(buffers.vertices, 3);
|
|
11
11
|
const colors = new BufferAttribute(buffers.colors, 4);
|
|
@@ -1,30 +1,14 @@
|
|
|
1
|
-
<script>import {
|
|
1
|
+
<script lang="ts">import { SceneGraphObject } from '@threlte/core';
|
|
2
2
|
import { onDestroy, setContext, tick } from 'svelte';
|
|
3
3
|
import { Object3D, Vector3 } from 'three';
|
|
4
|
-
import { useHasEventListeners } from '../../hooks/useHasEventListener';
|
|
5
4
|
import { useRapier } from '../../hooks/useRapier';
|
|
6
5
|
import { getWorldPosition, getWorldQuaternion, getWorldScale } from '../../lib/getWorldTransforms';
|
|
7
6
|
import { parseRigidBodyType } from '../../lib/parseRigidBodyType';
|
|
8
7
|
import { setParentRigidbodyObject } from '../../lib/rigidBodyObjectContext';
|
|
9
8
|
import { useCreateEvent } from '../../lib/useCreateEvent';
|
|
10
9
|
const { world, rapier, addRigidBodyToContext, removeRigidBodyFromContext } = useRapier();
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
export let type = 'dynamic';
|
|
14
|
-
export let canSleep = true;
|
|
15
|
-
export let gravityScale = 1;
|
|
16
|
-
export let ccd = false;
|
|
17
|
-
export let angularDamping = 0;
|
|
18
|
-
export let linearDamping = 0;
|
|
19
|
-
export let lockRotations = false;
|
|
20
|
-
export let lockTranslations = false;
|
|
21
|
-
export let enabledRotations = [true, true, true];
|
|
22
|
-
export let enabledTranslations = [true, true, true];
|
|
23
|
-
export let dominance = 0;
|
|
24
|
-
export let enabled = true;
|
|
25
|
-
export let userData = {};
|
|
26
|
-
const dispatcher = createRawEventDispatcher();
|
|
27
|
-
const { updateRef } = useCreateEvent();
|
|
10
|
+
let { linearVelocity, angularVelocity, type = 'dynamic', canSleep = true, gravityScale = 1, ccd = false, angularDamping = 0, linearDamping = 0, lockRotations = false, lockTranslations = false, enabledRotations = [true, true, true], enabledTranslations = [true, true, true], dominance = 0, enabled = true, userData = {}, rigidBody = $bindable(), ...props } = $props();
|
|
11
|
+
const { updateRef } = useCreateEvent(props.$$events);
|
|
28
12
|
const object = new Object3D();
|
|
29
13
|
/**
|
|
30
14
|
* isSleeping used for events "sleep" and "wake" in `useFrameHandler`
|
|
@@ -34,14 +18,11 @@ object.userData.isSleeping = false;
|
|
|
34
18
|
* RigidBody Description
|
|
35
19
|
*/
|
|
36
20
|
const desc = new rapier.RigidBodyDesc(parseRigidBodyType(type)).setCanSleep(canSleep);
|
|
37
|
-
/**
|
|
38
|
-
* Export the rigidBody only after positional initialization
|
|
39
|
-
*/
|
|
40
|
-
export let rigidBody = undefined;
|
|
41
21
|
/**
|
|
42
22
|
* Temporary RigidBody init
|
|
43
23
|
*/
|
|
44
|
-
|
|
24
|
+
let rigidBodyInternal = world.createRigidBody(desc);
|
|
25
|
+
rigidBody = rigidBodyInternal;
|
|
45
26
|
/**
|
|
46
27
|
* Apply transforms after the parent component added "object" to itself
|
|
47
28
|
*/
|
|
@@ -52,47 +33,50 @@ const initPosition = async () => {
|
|
|
52
33
|
const parentWorldScale = object.parent ? getWorldScale(object.parent) : new Vector3(1, 1, 1);
|
|
53
34
|
const worldPosition = getWorldPosition(object).multiply(parentWorldScale);
|
|
54
35
|
const worldQuaternion = getWorldQuaternion(object);
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
updateRef(rigidBody);
|
|
36
|
+
rigidBodyInternal.setTranslation(worldPosition, true);
|
|
37
|
+
rigidBodyInternal.setRotation(worldQuaternion, true);
|
|
38
|
+
updateRef(rigidBodyInternal);
|
|
59
39
|
};
|
|
60
40
|
initPosition();
|
|
61
41
|
/**
|
|
62
42
|
* Will come in handy in the future for joints
|
|
63
43
|
*/
|
|
64
|
-
object.userData.rigidBody =
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
44
|
+
object.userData.rigidBody = rigidBodyInternal;
|
|
45
|
+
$effect.pre(() => rigidBodyInternal.setBodyType(parseRigidBodyType(type), true));
|
|
46
|
+
$effect.pre(() => {
|
|
47
|
+
if (linearVelocity) {
|
|
48
|
+
rigidBodyInternal.setLinvel({ x: linearVelocity[0], y: linearVelocity[1], z: linearVelocity[2] }, true);
|
|
49
|
+
}
|
|
50
|
+
});
|
|
51
|
+
$effect.pre(() => {
|
|
52
|
+
if (angularVelocity) {
|
|
53
|
+
rigidBodyInternal.setAngvel({ x: angularVelocity[0], y: angularVelocity[1], z: angularVelocity[2] }, true);
|
|
54
|
+
}
|
|
55
|
+
});
|
|
56
|
+
$effect.pre(() => rigidBodyInternal.setGravityScale(gravityScale, true));
|
|
57
|
+
$effect.pre(() => rigidBodyInternal.enableCcd(ccd));
|
|
58
|
+
$effect.pre(() => rigidBodyInternal.setDominanceGroup(dominance));
|
|
59
|
+
$effect.pre(() => rigidBodyInternal.lockRotations(lockRotations, true));
|
|
60
|
+
$effect.pre(() => rigidBodyInternal.lockTranslations(lockTranslations, true));
|
|
61
|
+
$effect.pre(() => rigidBodyInternal.setEnabledRotations(...enabledRotations, true));
|
|
62
|
+
$effect.pre(() => rigidBodyInternal.setEnabledTranslations(...enabledTranslations, true));
|
|
63
|
+
$effect.pre(() => rigidBodyInternal.setAngularDamping(angularDamping));
|
|
64
|
+
$effect.pre(() => rigidBodyInternal.setLinearDamping(linearDamping));
|
|
65
|
+
$effect.pre(() => rigidBodyInternal.setEnabled(enabled));
|
|
83
66
|
/**
|
|
84
67
|
* Add userData to the rigidBody
|
|
85
68
|
*/
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
};
|
|
69
|
+
$effect.pre(() => {
|
|
70
|
+
rigidBodyInternal.userData = {
|
|
71
|
+
events: props.$$events,
|
|
72
|
+
...userData
|
|
73
|
+
};
|
|
74
|
+
});
|
|
91
75
|
/**
|
|
92
76
|
* Setting the RigidBody context so that colliders can
|
|
93
77
|
* hook onto.
|
|
94
78
|
*/
|
|
95
|
-
setContext('threlte-rapier-rigidbody',
|
|
79
|
+
setContext('threlte-rapier-rigidbody', rigidBodyInternal);
|
|
96
80
|
/**
|
|
97
81
|
* Used by child colliders to restore transform
|
|
98
82
|
*/
|
|
@@ -100,16 +84,16 @@ setParentRigidbodyObject(object);
|
|
|
100
84
|
/**
|
|
101
85
|
* Add the mesh to the context
|
|
102
86
|
*/
|
|
103
|
-
addRigidBodyToContext(
|
|
87
|
+
addRigidBodyToContext(rigidBodyInternal, object, props.$$events);
|
|
104
88
|
/**
|
|
105
89
|
* cleanup
|
|
106
90
|
*/
|
|
107
91
|
onDestroy(() => {
|
|
108
|
-
removeRigidBodyFromContext(
|
|
109
|
-
world.removeRigidBody(
|
|
92
|
+
removeRigidBodyFromContext(rigidBodyInternal);
|
|
93
|
+
world.removeRigidBody(rigidBodyInternal);
|
|
110
94
|
});
|
|
111
95
|
</script>
|
|
112
96
|
|
|
113
97
|
<SceneGraphObject {object}>
|
|
114
|
-
<slot {
|
|
98
|
+
<slot rigidBody={rigidBodyInternal} />
|
|
115
99
|
</SceneGraphObject>
|
|
@@ -7,7 +7,7 @@ import type { RigidBodyEventMap } from '../../types/types'
|
|
|
7
7
|
export type Boolean3Array = [x: boolean, y: boolean, z: boolean]
|
|
8
8
|
|
|
9
9
|
export type RigidBodyProps = {
|
|
10
|
-
rigidBody
|
|
10
|
+
rigidBody: RapierRigidBody
|
|
11
11
|
|
|
12
12
|
/**
|
|
13
13
|
* Specify the type of this rigid body
|
|
@@ -58,7 +58,7 @@ export type RigidBodyProps = {
|
|
|
58
58
|
enabledRotations?: Boolean3Array
|
|
59
59
|
|
|
60
60
|
/**
|
|
61
|
-
* Allow
|
|
61
|
+
* Allow translations of this rigid-body only along specific axes.
|
|
62
62
|
*/
|
|
63
63
|
enabledTranslations?: Boolean3Array
|
|
64
64
|
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
<script
|
|
2
2
|
context="module"
|
|
3
|
-
|
|
3
|
+
lang="ts"
|
|
4
4
|
>import { onDestroy, setContext, tick } from 'svelte';
|
|
5
5
|
import { useFrameHandler } from '../../hooks/useFrameHandler';
|
|
6
6
|
import { createRapierContext } from '../../lib/createRapierContext';
|
|
7
7
|
</script>
|
|
8
8
|
|
|
9
|
-
<script>export let gravity = [0, -9.81, 0];
|
|
9
|
+
<script lang="ts">export let gravity = [0, -9.81, 0];
|
|
10
10
|
export let rawIntegrationParameters = undefined;
|
|
11
11
|
export let rawIslands = undefined;
|
|
12
12
|
export let rawBroadPhase = undefined;
|
|
@@ -20,13 +20,13 @@ export let rawQueryPipeline = undefined;
|
|
|
20
20
|
export let rawPhysicsPipeline = undefined;
|
|
21
21
|
export let rawSerializationPipeline = undefined;
|
|
22
22
|
export let rawDebugRenderPipeline = undefined;
|
|
23
|
-
export let
|
|
23
|
+
export let stage = undefined;
|
|
24
24
|
const rapierContext = createRapierContext({ x: gravity[0], y: gravity[1], z: gravity[2] }, rawIntegrationParameters, rawIslands, rawBroadPhase, rawNarrowPhase, rawBodies, rawColliders, rawImpulseJoints, rawMultibodyJoints, rawCCDSolver, rawQueryPipeline, rawPhysicsPipeline, rawSerializationPipeline, rawDebugRenderPipeline);
|
|
25
25
|
setContext('threlte-rapier-context', rapierContext);
|
|
26
26
|
$: if (gravity !== undefined) {
|
|
27
27
|
rapierContext.world.gravity = { x: gravity[0], y: gravity[1], z: gravity[2] };
|
|
28
28
|
}
|
|
29
|
-
useFrameHandler(rapierContext,
|
|
29
|
+
useFrameHandler(rapierContext, stage);
|
|
30
30
|
onDestroy(async () => {
|
|
31
31
|
await tick();
|
|
32
32
|
rapierContext.world.free();
|
|
@@ -1,22 +1,7 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { SvelteComponent } from "svelte";
|
|
2
|
+
import type { WorldProps } from './World.svelte';
|
|
2
3
|
declare const __propDef: {
|
|
3
|
-
props:
|
|
4
|
-
gravity?: [x: number, y: number, z: number] | undefined;
|
|
5
|
-
rawIntegrationParameters?: import("@dimforge/rapier3d-compat/rapier_wasm3d").RawIntegrationParameters | undefined;
|
|
6
|
-
rawIslands?: import("@dimforge/rapier3d-compat/rapier_wasm3d").RawIslandManager | undefined;
|
|
7
|
-
rawBroadPhase?: import("@dimforge/rapier3d-compat/rapier_wasm3d").RawBroadPhase | undefined;
|
|
8
|
-
rawNarrowPhase?: import("@dimforge/rapier3d-compat/rapier_wasm3d").RawNarrowPhase | undefined;
|
|
9
|
-
rawBodies?: import("@dimforge/rapier3d-compat/rapier_wasm3d").RawRigidBodySet | undefined;
|
|
10
|
-
rawColliders?: import("@dimforge/rapier3d-compat/rapier_wasm3d").RawColliderSet | undefined;
|
|
11
|
-
rawImpulseJoints?: import("@dimforge/rapier3d-compat/rapier_wasm3d").RawImpulseJointSet | undefined;
|
|
12
|
-
rawMultibodyJoints?: import("@dimforge/rapier3d-compat/rapier_wasm3d").RawMultibodyJointSet | undefined;
|
|
13
|
-
rawCCDSolver?: import("@dimforge/rapier3d-compat/rapier_wasm3d").RawCCDSolver | undefined;
|
|
14
|
-
rawQueryPipeline?: import("@dimforge/rapier3d-compat/rapier_wasm3d").RawQueryPipeline | undefined;
|
|
15
|
-
rawPhysicsPipeline?: import("@dimforge/rapier3d-compat/rapier_wasm3d").RawPhysicsPipeline | undefined;
|
|
16
|
-
rawSerializationPipeline?: import("@dimforge/rapier3d-compat/rapier_wasm3d").RawSerializationPipeline | undefined;
|
|
17
|
-
rawDebugRenderPipeline?: import("@dimforge/rapier3d-compat/rapier_wasm3d").RawDebugRenderPipeline | undefined;
|
|
18
|
-
order?: number | undefined;
|
|
19
|
-
};
|
|
4
|
+
props: WorldProps;
|
|
20
5
|
events: {
|
|
21
6
|
[evt: string]: CustomEvent<any>;
|
|
22
7
|
};
|
|
@@ -27,6 +12,6 @@ declare const __propDef: {
|
|
|
27
12
|
export type InnerWorldProps = typeof __propDef.props;
|
|
28
13
|
export type InnerWorldEvents = typeof __propDef.events;
|
|
29
14
|
export type InnerWorldSlots = typeof __propDef.slots;
|
|
30
|
-
export default class InnerWorld extends
|
|
15
|
+
export default class InnerWorld extends SvelteComponent<InnerWorldProps, InnerWorldEvents, InnerWorldSlots> {
|
|
31
16
|
}
|
|
32
17
|
export {};
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
<script
|
|
2
2
|
context="module"
|
|
3
|
-
|
|
3
|
+
lang="ts"
|
|
4
4
|
>import RAPIER from '@dimforge/rapier3d-compat';
|
|
5
5
|
import { onMount } from 'svelte';
|
|
6
6
|
import { writable } from 'svelte/store';
|
|
@@ -10,7 +10,7 @@ import { writable } from 'svelte/store';
|
|
|
10
10
|
const initialized = writable(false);
|
|
11
11
|
</script>
|
|
12
12
|
|
|
13
|
-
<script>import InnerWorld from './InnerWorld.svelte';
|
|
13
|
+
<script lang="ts">import InnerWorld from './InnerWorld.svelte';
|
|
14
14
|
// self
|
|
15
15
|
export let gravity = undefined;
|
|
16
16
|
export let rawIntegrationParameters = undefined;
|
|
@@ -27,11 +27,11 @@ export let rawPhysicsPipeline = undefined;
|
|
|
27
27
|
export let rawSerializationPipeline = undefined;
|
|
28
28
|
export let rawDebugRenderPipeline = undefined;
|
|
29
29
|
/**
|
|
30
|
-
*
|
|
31
|
-
* Use this to control when the rapier physics engine is updating the scene.
|
|
32
|
-
* @default undefined
|
|
33
|
-
*/
|
|
34
|
-
export let
|
|
30
|
+
* This is passed to the useTask handler.
|
|
31
|
+
* Use this to control when the rapier physics engine is updating the scene.
|
|
32
|
+
* @default undefined
|
|
33
|
+
*/
|
|
34
|
+
export let stage = undefined;
|
|
35
35
|
let error = false;
|
|
36
36
|
const init = async () => {
|
|
37
37
|
if ($initialized)
|
|
@@ -63,7 +63,7 @@ onMount(init);
|
|
|
63
63
|
{rawPhysicsPipeline}
|
|
64
64
|
{rawSerializationPipeline}
|
|
65
65
|
{rawDebugRenderPipeline}
|
|
66
|
-
|
|
66
|
+
{stage}
|
|
67
67
|
>
|
|
68
68
|
<slot />
|
|
69
69
|
</InnerWorld>
|
|
@@ -13,8 +13,9 @@ import type {
|
|
|
13
13
|
RawRigidBodySet,
|
|
14
14
|
RawSerializationPipeline
|
|
15
15
|
} from '@dimforge/rapier3d-compat/raw'
|
|
16
|
-
import {
|
|
16
|
+
import { SvelteComponent } from 'svelte'
|
|
17
17
|
import type { Vector3 } from 'three'
|
|
18
|
+
import type { Key, Stage } from '@threlte/core'
|
|
18
19
|
|
|
19
20
|
export type WorldProps = {
|
|
20
21
|
gravity?: Parameters<Vector3['set']>
|
|
@@ -31,7 +32,7 @@ export type WorldProps = {
|
|
|
31
32
|
rawPhysicsPipeline?: RawPhysicsPipeline
|
|
32
33
|
rawSerializationPipeline?: RawSerializationPipeline
|
|
33
34
|
rawDebugRenderPipeline?: RawDebugRenderPipeline
|
|
34
|
-
|
|
35
|
+
stage?: Key | Stage
|
|
35
36
|
}
|
|
36
37
|
|
|
37
|
-
export default class World extends
|
|
38
|
+
export default class World extends SvelteComponent<WorldProps> {}
|
|
@@ -1,2 +1,3 @@
|
|
|
1
|
+
import { type Stage, type Key } from '@threlte/core';
|
|
1
2
|
import type { RapierContext } from '../types/types';
|
|
2
|
-
export declare const useFrameHandler: (ctx: RapierContext,
|
|
3
|
+
export declare const useFrameHandler: (ctx: RapierContext, stage?: Stage | Key) => void;
|
|
@@ -1,31 +1,31 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
1
|
+
import { EventQueue } from '@dimforge/rapier3d-compat';
|
|
2
|
+
import { useTask } from '@threlte/core';
|
|
3
3
|
import { derived } from 'svelte/store';
|
|
4
4
|
import { Object3D, Quaternion, Vector3 } from 'three';
|
|
5
5
|
const tempObject = new Object3D();
|
|
6
6
|
const tempVector3 = new Vector3();
|
|
7
7
|
const tempQuaternion = new Quaternion();
|
|
8
8
|
const getEventDispatchers = (ctx, collider1, collider2) => {
|
|
9
|
-
const
|
|
10
|
-
const
|
|
9
|
+
const collider1Events = ctx.colliderEventDispatchers.get(collider1.handle);
|
|
10
|
+
const collider2Events = ctx.colliderEventDispatchers.get(collider2.handle);
|
|
11
11
|
const rigidBody1 = collider1.parent();
|
|
12
12
|
const rigidBody2 = collider2.parent();
|
|
13
|
-
const
|
|
13
|
+
const rigidBody1Events = rigidBody1
|
|
14
14
|
? ctx.rigidBodyEventDispatchers.get(rigidBody1.handle)
|
|
15
15
|
: undefined;
|
|
16
|
-
const
|
|
16
|
+
const rigidBody2Events = rigidBody2
|
|
17
17
|
? ctx.rigidBodyEventDispatchers.get(rigidBody2.handle)
|
|
18
18
|
: undefined;
|
|
19
19
|
return {
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
20
|
+
collider1Events,
|
|
21
|
+
collider2Events,
|
|
22
|
+
rigidBody1Events,
|
|
23
|
+
rigidBody2Events
|
|
24
24
|
};
|
|
25
25
|
};
|
|
26
|
-
export const useFrameHandler = (ctx,
|
|
26
|
+
export const useFrameHandler = (ctx, stage) => {
|
|
27
27
|
const eventQueue = new EventQueue(false);
|
|
28
|
-
const { start, started, stop } =
|
|
28
|
+
const { start, started, stop } = useTask((delta) => {
|
|
29
29
|
// if (!eventQueue) return
|
|
30
30
|
const { world } = ctx;
|
|
31
31
|
// Set timestep to current delta, to allow for variable frame rates
|
|
@@ -37,15 +37,15 @@ export const useFrameHandler = (ctx, order) => {
|
|
|
37
37
|
const rigidBody = world.getRigidBody(handle);
|
|
38
38
|
if (!rigidBody)
|
|
39
39
|
return;
|
|
40
|
-
const
|
|
40
|
+
const events = ctx.rigidBodyEventDispatchers.get(handle);
|
|
41
41
|
if (!rigidBody || !rigidBody.isValid())
|
|
42
42
|
return;
|
|
43
|
-
if (
|
|
43
|
+
if (events) {
|
|
44
44
|
if (rigidBody.isSleeping() && !mesh.userData.isSleeping) {
|
|
45
|
-
|
|
45
|
+
events.sleep?.();
|
|
46
46
|
}
|
|
47
47
|
if (!rigidBody.isSleeping() && mesh.userData.isSleeping) {
|
|
48
|
-
|
|
48
|
+
events.wake?.();
|
|
49
49
|
}
|
|
50
50
|
mesh.userData.isSleeping = rigidBody.isSleeping();
|
|
51
51
|
}
|
|
@@ -75,11 +75,11 @@ export const useFrameHandler = (ctx, order) => {
|
|
|
75
75
|
if (!collider1 || !collider2) {
|
|
76
76
|
return;
|
|
77
77
|
}
|
|
78
|
-
const {
|
|
78
|
+
const { collider1Events, collider2Events, rigidBody1Events, rigidBody2Events } = getEventDispatchers(ctx, collider1, collider2);
|
|
79
79
|
const rigidBody1 = collider1.parent();
|
|
80
80
|
const rigidBody2 = collider2.parent();
|
|
81
81
|
// Collider events
|
|
82
|
-
|
|
82
|
+
collider1Events?.contact?.({
|
|
83
83
|
targetCollider: collider2,
|
|
84
84
|
targetRigidBody: rigidBody2,
|
|
85
85
|
maxForceDirection: e.maxForceDirection(),
|
|
@@ -87,7 +87,7 @@ export const useFrameHandler = (ctx, order) => {
|
|
|
87
87
|
totalForce: e.totalForce(),
|
|
88
88
|
totalForceMagnitude: e.totalForceMagnitude()
|
|
89
89
|
});
|
|
90
|
-
|
|
90
|
+
collider2Events?.contact?.({
|
|
91
91
|
targetCollider: collider1,
|
|
92
92
|
targetRigidBody: rigidBody1,
|
|
93
93
|
maxForceDirection: e.maxForceDirection(),
|
|
@@ -96,7 +96,7 @@ export const useFrameHandler = (ctx, order) => {
|
|
|
96
96
|
totalForceMagnitude: e.totalForceMagnitude()
|
|
97
97
|
});
|
|
98
98
|
// RigidBody Events
|
|
99
|
-
|
|
99
|
+
rigidBody1Events?.contact?.({
|
|
100
100
|
targetCollider: collider2,
|
|
101
101
|
targetRigidBody: rigidBody2,
|
|
102
102
|
maxForceDirection: e.maxForceDirection(),
|
|
@@ -104,7 +104,7 @@ export const useFrameHandler = (ctx, order) => {
|
|
|
104
104
|
totalForce: e.totalForce(),
|
|
105
105
|
totalForceMagnitude: e.totalForceMagnitude()
|
|
106
106
|
});
|
|
107
|
-
|
|
107
|
+
rigidBody2Events?.contact?.({
|
|
108
108
|
targetCollider: collider1,
|
|
109
109
|
targetRigidBody: rigidBody1,
|
|
110
110
|
maxForceDirection: e.maxForceDirection(),
|
|
@@ -121,7 +121,10 @@ export const useFrameHandler = (ctx, order) => {
|
|
|
121
121
|
if (!collider1 || !collider2) {
|
|
122
122
|
return;
|
|
123
123
|
}
|
|
124
|
-
const {
|
|
124
|
+
const { collider1Events, collider2Events, rigidBody1Events, rigidBody2Events } = getEventDispatchers(ctx, collider1, collider2);
|
|
125
|
+
if (!collider1Events && !collider2Events && !rigidBody1Events && !rigidBody2Events) {
|
|
126
|
+
return;
|
|
127
|
+
}
|
|
125
128
|
const rigidBody1 = collider1.parent();
|
|
126
129
|
const rigidBody2 = collider2.parent();
|
|
127
130
|
if (started) {
|
|
@@ -129,20 +132,20 @@ export const useFrameHandler = (ctx, order) => {
|
|
|
129
132
|
const isIntersection = world.intersectionPair(collider1, collider2);
|
|
130
133
|
if (isIntersection) {
|
|
131
134
|
// Collider Events
|
|
132
|
-
|
|
135
|
+
collider1Events?.sensorenter?.({
|
|
133
136
|
targetCollider: collider2,
|
|
134
137
|
targetRigidBody: rigidBody2
|
|
135
138
|
});
|
|
136
|
-
|
|
139
|
+
collider2Events?.sensorenter?.({
|
|
137
140
|
targetCollider: collider1,
|
|
138
141
|
targetRigidBody: rigidBody1
|
|
139
142
|
});
|
|
140
143
|
// RigidBody Events
|
|
141
|
-
|
|
144
|
+
rigidBody1Events?.sensorenter?.({
|
|
142
145
|
targetCollider: collider2,
|
|
143
146
|
targetRigidBody: rigidBody2
|
|
144
147
|
});
|
|
145
|
-
|
|
148
|
+
rigidBody2Events?.sensorenter?.({
|
|
146
149
|
targetCollider: collider1,
|
|
147
150
|
targetRigidBody: rigidBody1
|
|
148
151
|
});
|
|
@@ -151,26 +154,26 @@ export const useFrameHandler = (ctx, order) => {
|
|
|
151
154
|
}
|
|
152
155
|
world.contactPair(collider1, collider2, (manifold, flipped) => {
|
|
153
156
|
// Collider events
|
|
154
|
-
|
|
157
|
+
collider1Events?.collisionenter?.({
|
|
155
158
|
flipped,
|
|
156
159
|
manifold,
|
|
157
160
|
targetCollider: collider2,
|
|
158
161
|
targetRigidBody: rigidBody2
|
|
159
162
|
});
|
|
160
|
-
|
|
163
|
+
collider2Events?.collisionenter?.({
|
|
161
164
|
flipped,
|
|
162
165
|
manifold,
|
|
163
166
|
targetCollider: collider1,
|
|
164
167
|
targetRigidBody: rigidBody1
|
|
165
168
|
});
|
|
166
169
|
// RigidBody Events
|
|
167
|
-
|
|
170
|
+
rigidBody1Events?.collisionenter?.({
|
|
168
171
|
flipped,
|
|
169
172
|
manifold,
|
|
170
173
|
targetCollider: collider2,
|
|
171
174
|
targetRigidBody: rigidBody2
|
|
172
175
|
});
|
|
173
|
-
|
|
176
|
+
rigidBody2Events?.collisionenter?.({
|
|
174
177
|
flipped,
|
|
175
178
|
manifold,
|
|
176
179
|
targetCollider: collider1,
|
|
@@ -185,20 +188,20 @@ export const useFrameHandler = (ctx, order) => {
|
|
|
185
188
|
collider1.isSensor() ||
|
|
186
189
|
collider2.isSensor();
|
|
187
190
|
if (isIntersection) {
|
|
188
|
-
|
|
191
|
+
collider1Events?.sensorexit?.({
|
|
189
192
|
targetCollider: collider2,
|
|
190
193
|
targetRigidBody: rigidBody2
|
|
191
194
|
});
|
|
192
|
-
|
|
195
|
+
collider2Events?.sensorexit?.({
|
|
193
196
|
targetCollider: collider1,
|
|
194
197
|
targetRigidBody: rigidBody1
|
|
195
198
|
});
|
|
196
199
|
// RigidBody Events
|
|
197
|
-
|
|
200
|
+
rigidBody1Events?.sensorexit?.({
|
|
198
201
|
targetCollider: collider2,
|
|
199
202
|
targetRigidBody: rigidBody2
|
|
200
203
|
});
|
|
201
|
-
|
|
204
|
+
rigidBody2Events?.sensorexit?.({
|
|
202
205
|
targetCollider: collider1,
|
|
203
206
|
targetRigidBody: rigidBody1
|
|
204
207
|
});
|
|
@@ -206,26 +209,26 @@ export const useFrameHandler = (ctx, order) => {
|
|
|
206
209
|
return;
|
|
207
210
|
}
|
|
208
211
|
// Collider events
|
|
209
|
-
|
|
212
|
+
collider1Events?.collisionexit?.({
|
|
210
213
|
targetCollider: collider2,
|
|
211
214
|
targetRigidBody: rigidBody2
|
|
212
215
|
});
|
|
213
|
-
|
|
216
|
+
collider2Events?.collisionexit?.({
|
|
214
217
|
targetCollider: collider1,
|
|
215
218
|
targetRigidBody: rigidBody1
|
|
216
219
|
});
|
|
217
220
|
// RigidBody Events
|
|
218
|
-
|
|
221
|
+
rigidBody1Events?.collisionexit?.({
|
|
219
222
|
targetCollider: collider2,
|
|
220
223
|
targetRigidBody: rigidBody2
|
|
221
224
|
});
|
|
222
|
-
|
|
225
|
+
rigidBody2Events?.collisionexit?.({
|
|
223
226
|
targetCollider: collider1,
|
|
224
227
|
targetRigidBody: rigidBody1
|
|
225
228
|
});
|
|
226
229
|
}
|
|
227
230
|
});
|
|
228
|
-
}, {
|
|
231
|
+
}, { stage });
|
|
229
232
|
// replacing the original pause and resume functions as well as the paused property
|
|
230
233
|
ctx.pause = () => stop();
|
|
231
234
|
ctx.resume = () => start();
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import { get_current_component } from 'svelte/internal';
|
|
2
1
|
export const useHasEventListeners = () => {
|
|
3
|
-
const component = get_current_component()
|
|
2
|
+
// const component = get_current_component()
|
|
4
3
|
const hasEventListeners = (type) => {
|
|
5
|
-
const callbacks = component.$$.callbacks
|
|
6
|
-
return
|
|
4
|
+
// const callbacks = component.$$.callbacks
|
|
5
|
+
return true;
|
|
6
|
+
// return type in callbacks && (callbacks[type] as any[]).length > 0
|
|
7
7
|
};
|
|
8
8
|
return {
|
|
9
9
|
hasEventListeners
|
|
@@ -1,4 +1,2 @@
|
|
|
1
1
|
import { type Collider } from '@dimforge/rapier3d-compat';
|
|
2
|
-
|
|
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;
|
|
2
|
+
export declare const applyColliderActiveEvents: (collider: Collider, colliderEvents?: Record<string, (arg: unknown) => void>, rigidBodyEvents?: Record<string, (arg: unknown) => void>) => void;
|
|
@@ -1,17 +1,17 @@
|
|
|
1
1
|
import { ActiveEvents } from '@dimforge/rapier3d-compat';
|
|
2
|
-
export const applyColliderActiveEvents = (collider,
|
|
2
|
+
export const applyColliderActiveEvents = (collider, colliderEvents = {}, rigidBodyEvents = {}) => {
|
|
3
3
|
let events = 0;
|
|
4
|
-
if (
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
4
|
+
if (colliderEvents.collisionenter ||
|
|
5
|
+
colliderEvents.collisionexit ||
|
|
6
|
+
rigidBodyEvents.collisionenter ||
|
|
7
|
+
rigidBodyEvents.collisionexit ||
|
|
8
|
+
colliderEvents.sensorenter ||
|
|
9
|
+
colliderEvents.sensorexit ||
|
|
10
|
+
rigidBodyEvents.sensorenter ||
|
|
11
|
+
rigidBodyEvents.sensorexit) {
|
|
12
12
|
events = events | ActiveEvents.COLLISION_EVENTS;
|
|
13
13
|
}
|
|
14
|
-
if (
|
|
14
|
+
if (colliderEvents.contact || rigidBodyEvents.contact) {
|
|
15
15
|
events = events | ActiveEvents.CONTACT_FORCE_EVENTS;
|
|
16
16
|
}
|
|
17
17
|
if (events > 0) {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { ActiveEvents,
|
|
2
|
-
import {
|
|
1
|
+
import { ActiveEvents, ColliderDesc } from '@dimforge/rapier3d-compat';
|
|
2
|
+
import { Quaternion, Vector3 } from 'three';
|
|
3
3
|
const offset = new Vector3();
|
|
4
4
|
const worldPosition = new Vector3();
|
|
5
5
|
const worldQuaternion = new Quaternion();
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
import type { Collider, RigidBody } from '@dimforge/rapier3d-compat';
|
|
3
3
|
import RAPIER from '@dimforge/rapier3d-compat';
|
|
4
4
|
import type { Object3D } from 'three';
|
|
5
|
-
import type {
|
|
5
|
+
import type { ColliderEventDispatchers, RigidBodyEventDispatchers } from '../types/types';
|
|
6
6
|
export declare const createRapierContext: (gravity: RAPIER.Vector, rawIntegrationParameters?: import("@dimforge/rapier3d-compat/rapier_wasm3d").RawIntegrationParameters | undefined, rawIslands?: import("@dimforge/rapier3d-compat/rapier_wasm3d").RawIslandManager | undefined, rawBroadPhase?: import("@dimforge/rapier3d-compat/rapier_wasm3d").RawBroadPhase | undefined, rawNarrowPhase?: import("@dimforge/rapier3d-compat/rapier_wasm3d").RawNarrowPhase | undefined, rawBodies?: import("@dimforge/rapier3d-compat/rapier_wasm3d").RawRigidBodySet | undefined, rawColliders?: import("@dimforge/rapier3d-compat/rapier_wasm3d").RawColliderSet | undefined, rawImpulseJoints?: import("@dimforge/rapier3d-compat/rapier_wasm3d").RawImpulseJointSet | undefined, rawMultibodyJoints?: import("@dimforge/rapier3d-compat/rapier_wasm3d").RawMultibodyJointSet | undefined, rawCCDSolver?: import("@dimforge/rapier3d-compat/rapier_wasm3d").RawCCDSolver | undefined, rawQueryPipeline?: import("@dimforge/rapier3d-compat/rapier_wasm3d").RawQueryPipeline | undefined, rawPhysicsPipeline?: import("@dimforge/rapier3d-compat/rapier_wasm3d").RawPhysicsPipeline | undefined, rawSerializationPipeline?: import("@dimforge/rapier3d-compat/rapier_wasm3d").RawSerializationPipeline | undefined, rawDebugRenderPipeline?: import("@dimforge/rapier3d-compat/rapier_wasm3d").RawDebugRenderPipeline | undefined) => {
|
|
7
7
|
rapier: typeof RAPIER;
|
|
8
8
|
world: RAPIER.World;
|
|
@@ -10,9 +10,9 @@ export declare const createRapierContext: (gravity: RAPIER.Vector, rawIntegratio
|
|
|
10
10
|
rigidBodyObjects: Map<number, Object3D<import("three").Object3DEventMap>>;
|
|
11
11
|
rigidBodyEventDispatchers: RigidBodyEventDispatchers;
|
|
12
12
|
colliderEventDispatchers: ColliderEventDispatchers;
|
|
13
|
-
addColliderToContext: (collider: Collider, object: Object3D,
|
|
13
|
+
addColliderToContext: (collider: Collider, object: Object3D, events: Record<string, (arg: unknown) => void>) => void;
|
|
14
14
|
removeColliderFromContext: (collider: Collider) => void;
|
|
15
|
-
addRigidBodyToContext: (rigidBody: RigidBody, object: Object3D,
|
|
15
|
+
addRigidBodyToContext: (rigidBody: RigidBody, object: Object3D, events: Record<string, (arg: unknown) => void>) => void;
|
|
16
16
|
removeRigidBodyFromContext: (rigidBody: RigidBody) => void;
|
|
17
17
|
debug: import("svelte/store").Writable<boolean>;
|
|
18
18
|
pause: () => void;
|
|
@@ -12,9 +12,9 @@ export const createRapierContext = (...args) => {
|
|
|
12
12
|
* @param object
|
|
13
13
|
* @param eventDispatcher
|
|
14
14
|
*/
|
|
15
|
-
const addColliderToContext = (collider, object,
|
|
15
|
+
const addColliderToContext = (collider, object, events) => {
|
|
16
16
|
colliderObjects.set(collider.handle, object);
|
|
17
|
-
colliderEventDispatchers.set(collider.handle,
|
|
17
|
+
colliderEventDispatchers.set(collider.handle, events);
|
|
18
18
|
};
|
|
19
19
|
/**
|
|
20
20
|
* Removes the collider from the context
|
|
@@ -30,9 +30,9 @@ export const createRapierContext = (...args) => {
|
|
|
30
30
|
* @param object
|
|
31
31
|
* @param eventDispatcher
|
|
32
32
|
*/
|
|
33
|
-
const addRigidBodyToContext = (rigidBody, object,
|
|
33
|
+
const addRigidBodyToContext = (rigidBody, object, events) => {
|
|
34
34
|
rigidBodyObjects.set(rigidBody.handle, object);
|
|
35
|
-
rigidBodyEventDispatchers.set(rigidBody.handle,
|
|
35
|
+
rigidBodyEventDispatchers.set(rigidBody.handle, events);
|
|
36
36
|
};
|
|
37
37
|
/**
|
|
38
38
|
* Removes the RigidBody from the context
|
|
@@ -1,7 +1,5 @@
|
|
|
1
1
|
import { onDestroy } from 'svelte';
|
|
2
|
-
|
|
3
|
-
export const useCreateEvent = () => {
|
|
4
|
-
const dispatchRaw = createRawEventDispatcher();
|
|
2
|
+
export const useCreateEvent = (events) => {
|
|
5
3
|
const cleanupFunctions = [];
|
|
6
4
|
let ref = undefined;
|
|
7
5
|
const dispatchCreateEvent = () => {
|
|
@@ -15,7 +13,7 @@ export const useCreateEvent = () => {
|
|
|
15
13
|
};
|
|
16
14
|
if (ref === undefined)
|
|
17
15
|
return;
|
|
18
|
-
|
|
16
|
+
events?.create?.({ ref, cleanup });
|
|
19
17
|
};
|
|
20
18
|
const updateRef = (newRef) => {
|
|
21
19
|
ref = newRef;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
<script>import { createRawEventDispatcher, T,
|
|
1
|
+
<script lang="ts">import { createRawEventDispatcher, T, useTask } from '@threlte/core';
|
|
2
2
|
import { Vector2, Vector3 } from 'three';
|
|
3
3
|
import Collider from '../components/Colliders/Collider.svelte';
|
|
4
4
|
import CollisionGroups from '../components/CollisionGroups/CollisionGroups.svelte';
|
|
@@ -29,10 +29,8 @@ $: {
|
|
|
29
29
|
grounded = true;
|
|
30
30
|
}
|
|
31
31
|
$: grounded ? dispatch('groundenter') : dispatch('groundexit');
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
return;
|
|
35
|
-
t.fromArray([0, 0, 0]);
|
|
32
|
+
const { start } = useTask(() => {
|
|
33
|
+
t.set(0, 0, 0);
|
|
36
34
|
if (keys.down)
|
|
37
35
|
t.x += 1;
|
|
38
36
|
if (keys.up)
|
|
@@ -53,18 +51,24 @@ useFrame(() => {
|
|
|
53
51
|
t.y = linVel.y;
|
|
54
52
|
rigidBody.setLinvel(t, true);
|
|
55
53
|
});
|
|
54
|
+
$: if (rigidBody)
|
|
55
|
+
start();
|
|
56
56
|
const onKeyDown = (e) => {
|
|
57
|
-
switch (e.key) {
|
|
58
|
-
case '
|
|
57
|
+
switch (e.key.toLowerCase()) {
|
|
58
|
+
case 's':
|
|
59
|
+
case 'arrowdown':
|
|
59
60
|
keys.down = true;
|
|
60
61
|
break;
|
|
61
|
-
case '
|
|
62
|
+
case 'w':
|
|
63
|
+
case 'arrowup':
|
|
62
64
|
keys.up = true;
|
|
63
65
|
break;
|
|
64
|
-
case '
|
|
66
|
+
case 'a':
|
|
67
|
+
case 'arrowleft':
|
|
65
68
|
keys.left = true;
|
|
66
69
|
break;
|
|
67
|
-
case '
|
|
70
|
+
case 'd':
|
|
71
|
+
case 'arrowright':
|
|
68
72
|
keys.right = true;
|
|
69
73
|
break;
|
|
70
74
|
case ' ':
|
|
@@ -76,17 +80,21 @@ const onKeyDown = (e) => {
|
|
|
76
80
|
}
|
|
77
81
|
};
|
|
78
82
|
const onKeyUp = (e) => {
|
|
79
|
-
switch (e.key) {
|
|
80
|
-
case '
|
|
83
|
+
switch (e.key.toLowerCase()) {
|
|
84
|
+
case 's':
|
|
85
|
+
case 'arrowdown':
|
|
81
86
|
keys.down = false;
|
|
82
87
|
break;
|
|
83
|
-
case '
|
|
88
|
+
case 'w':
|
|
89
|
+
case 'arrowup':
|
|
84
90
|
keys.up = false;
|
|
85
91
|
break;
|
|
86
|
-
case '
|
|
92
|
+
case 'a':
|
|
93
|
+
case 'arrowleft':
|
|
87
94
|
keys.left = false;
|
|
88
95
|
break;
|
|
89
|
-
case '
|
|
96
|
+
case 'd':
|
|
97
|
+
case 'arrowright':
|
|
90
98
|
keys.right = false;
|
|
91
99
|
break;
|
|
92
100
|
default:
|
|
@@ -95,7 +103,10 @@ const onKeyUp = (e) => {
|
|
|
95
103
|
};
|
|
96
104
|
</script>
|
|
97
105
|
|
|
98
|
-
<svelte:window
|
|
106
|
+
<svelte:window
|
|
107
|
+
on:keydown|preventDefault={onKeyDown}
|
|
108
|
+
on:keyup|preventDefault={onKeyUp}
|
|
109
|
+
/>
|
|
99
110
|
|
|
100
111
|
<T.Group {position}>
|
|
101
112
|
<RigidBody
|
|
@@ -105,7 +116,10 @@ const onKeyUp = (e) => {
|
|
|
105
116
|
type={'dynamic'}
|
|
106
117
|
>
|
|
107
118
|
<CollisionGroups groups={playerCollisionGroups}>
|
|
108
|
-
<Collider
|
|
119
|
+
<Collider
|
|
120
|
+
shape={'capsule'}
|
|
121
|
+
args={[height / 2 - radius, radius]}
|
|
122
|
+
/>
|
|
109
123
|
</CollisionGroups>
|
|
110
124
|
|
|
111
125
|
<CollisionGroups groups={groundCollisionGroups}>
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { SvelteComponent } from "svelte";
|
|
2
2
|
import { Vector3 } from 'three';
|
|
3
3
|
import type { CollisionGroupsBitMask } from '../types/types';
|
|
4
4
|
declare const __propDef: {
|
|
@@ -10,6 +10,9 @@ declare const __propDef: {
|
|
|
10
10
|
jumpStrength?: number | undefined;
|
|
11
11
|
playerCollisionGroups?: CollisionGroupsBitMask | undefined;
|
|
12
12
|
groundCollisionGroups?: CollisionGroupsBitMask | undefined;
|
|
13
|
+
children?: ((this: void) => typeof import("svelte").SnippetReturn & {
|
|
14
|
+
_: "functions passed to {@render ...} tags must use the `Snippet` type imported from \"svelte\"";
|
|
15
|
+
}) | undefined;
|
|
13
16
|
};
|
|
14
17
|
events: {
|
|
15
18
|
[evt: string]: CustomEvent<any>;
|
|
@@ -21,6 +24,6 @@ declare const __propDef: {
|
|
|
21
24
|
export type BasicPlayerControllerProps = typeof __propDef.props;
|
|
22
25
|
export type BasicPlayerControllerEvents = typeof __propDef.events;
|
|
23
26
|
export type BasicPlayerControllerSlots = typeof __propDef.slots;
|
|
24
|
-
export default class BasicPlayerController extends
|
|
27
|
+
export default class BasicPlayerController extends SvelteComponent<BasicPlayerControllerProps, BasicPlayerControllerEvents, BasicPlayerControllerSlots> {
|
|
25
28
|
}
|
|
26
29
|
export {};
|
package/dist/types/types.d.ts
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
|
+
/// <reference types="svelte" />
|
|
1
2
|
import type { Collider, ColliderHandle, RigidBody, RigidBodyHandle, TempContactManifold, Vector } from '@dimforge/rapier3d-compat';
|
|
2
|
-
import type { createRawEventDispatcher } from '@threlte/core';
|
|
3
3
|
import type { Writable } from 'svelte/store';
|
|
4
|
-
import type { useHasEventListeners } from '../hooks/useHasEventListener';
|
|
5
4
|
import type { createRapierContext } from '../lib/createRapierContext';
|
|
6
5
|
export type ColliderShapes = 'ball' | 'capsule' | 'segment' | 'triangle' | 'roundTriangle' | 'polyline' | 'trimesh' | 'cuboid' | 'roundCuboid' | 'heightfield' | 'cylinder' | 'roundCylinder' | 'cone' | 'roundCone' | 'convexHull' | 'convexMesh' | 'roundConvexHull' | 'roundConvexMesh';
|
|
7
6
|
export type AutoCollidersShapes = 'cuboid' | 'ball' | 'trimesh' | 'convexHull' | 'capsule';
|
|
@@ -46,14 +45,12 @@ export type RigidBodyEventMap = ColliderEventMap & {
|
|
|
46
45
|
sleep: void;
|
|
47
46
|
wake: void;
|
|
48
47
|
};
|
|
49
|
-
export type
|
|
50
|
-
export type
|
|
51
|
-
export type RigidBodyEventDispatchers = Map<RigidBodyHandle, RigidBodyEventDispatcher>;
|
|
52
|
-
export type ColliderEventDispatchers = Map<ColliderHandle, ColliderEventDispatcher>;
|
|
48
|
+
export type RigidBodyEventDispatchers = Map<RigidBodyHandle, Record<string, (arg: unknown) => void>>;
|
|
49
|
+
export type ColliderEventDispatchers = Map<ColliderHandle, Record<string, (arg: unknown) => void>>;
|
|
53
50
|
export type RapierContext = ReturnType<typeof createRapierContext>;
|
|
54
51
|
export type CollisionGroupsContext = Writable<number> | undefined;
|
|
55
52
|
export type RigidBodyUserData = {
|
|
56
|
-
|
|
53
|
+
events?: Record<string, (arg: unknown) => void>;
|
|
57
54
|
};
|
|
58
55
|
export type ThrelteRigidBody = RigidBody & {
|
|
59
56
|
userData?: RigidBodyUserData;
|
package/package.json
CHANGED
|
@@ -1,38 +1,41 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@threlte/rapier",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "3.0.0-next.0",
|
|
4
4
|
"author": "Grischa Erbe <hello@legrisch.com> (https://legrisch.com)",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"devDependencies": {
|
|
7
|
-
"@dimforge/rapier3d-compat": "^0.
|
|
8
|
-
"@sveltejs/adapter-auto": "^2.0
|
|
9
|
-
"@sveltejs/kit": "^
|
|
10
|
-
"@sveltejs/package": "^2.1
|
|
11
|
-
"@
|
|
12
|
-
"@types/
|
|
13
|
-
"@
|
|
14
|
-
"@typescript-eslint/
|
|
15
|
-
"@
|
|
16
|
-
"
|
|
17
|
-
"eslint
|
|
18
|
-
"eslint-
|
|
19
|
-
"
|
|
20
|
-
"prettier
|
|
21
|
-
"
|
|
22
|
-
"
|
|
23
|
-
"
|
|
24
|
-
"svelte
|
|
25
|
-
"
|
|
26
|
-
"
|
|
27
|
-
"
|
|
28
|
-
"
|
|
29
|
-
"
|
|
30
|
-
"
|
|
7
|
+
"@dimforge/rapier3d-compat": "^0.12.0",
|
|
8
|
+
"@sveltejs/adapter-auto": "^3.2.0",
|
|
9
|
+
"@sveltejs/kit": "^2.5.5",
|
|
10
|
+
"@sveltejs/package": "^2.3.1",
|
|
11
|
+
"@sveltejs/vite-plugin-svelte": "^3.0.2",
|
|
12
|
+
"@types/node": "^20.12.4",
|
|
13
|
+
"@types/three": "^0.163.0",
|
|
14
|
+
"@typescript-eslint/eslint-plugin": "^7.5.0",
|
|
15
|
+
"@typescript-eslint/parser": "^7.5.0",
|
|
16
|
+
"@yushijinhun/three-minifier-rollup": "^0.4.0",
|
|
17
|
+
"eslint": "^8.57.0",
|
|
18
|
+
"eslint-config-prettier": "^9.1.0",
|
|
19
|
+
"eslint-plugin-svelte": "^2.35.1",
|
|
20
|
+
"prettier": "^3.2.5",
|
|
21
|
+
"prettier-plugin-svelte": "^3.2.2",
|
|
22
|
+
"publint": "^0.2.7",
|
|
23
|
+
"rimraf": "^5.0.5",
|
|
24
|
+
"svelte": "5.0.0-next.94",
|
|
25
|
+
"svelte-check": "^3.6.9",
|
|
26
|
+
"svelte-preprocess": "^5.1.3",
|
|
27
|
+
"svelte2tsx": "^0.7.6",
|
|
28
|
+
"three": "^0.163.0",
|
|
29
|
+
"tslib": "^2.6.2",
|
|
30
|
+
"type-fest": "^4.15.0",
|
|
31
|
+
"typescript": "^5.4.4",
|
|
32
|
+
"vite": "^5.2.8",
|
|
33
|
+
"@threlte/core": "8.0.0-next.0"
|
|
31
34
|
},
|
|
32
35
|
"peerDependencies": {
|
|
36
|
+
"@dimforge/rapier3d-compat": ">=0.11",
|
|
33
37
|
"svelte": ">=4",
|
|
34
|
-
"three": ">=0.
|
|
35
|
-
"@dimforge/rapier3d-compat": ">=0.11"
|
|
38
|
+
"three": ">=0.152"
|
|
36
39
|
},
|
|
37
40
|
"type": "module",
|
|
38
41
|
"exports": {
|
|
@@ -47,6 +50,7 @@
|
|
|
47
50
|
"dist"
|
|
48
51
|
],
|
|
49
52
|
"scripts": {
|
|
53
|
+
"dev": "vite dev",
|
|
50
54
|
"package": "svelte-kit sync && svelte-package && node ./scripts/cleanupPackage.js && publint",
|
|
51
55
|
"check": "svelte-check --tsconfig ./tsconfig.json",
|
|
52
56
|
"check:watch": "svelte-check --tsconfig ./tsconfig.json --watch",
|