angular-three-rapier 4.0.0-next.65 → 4.0.0-next.66

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.
@@ -0,0 +1,3 @@
1
+ # angular-three-rapier/addons
2
+
3
+ Secondary entry point of `angular-three-rapier`. It can be used by importing from `angular-three-rapier/addons`.
@@ -0,0 +1 @@
1
+ export * from './lib/attractor';
@@ -0,0 +1,4 @@
1
+ import { Injector } from '@angular/core';
2
+ import * as THREE from 'three';
3
+ import { NgtrAttactorOptions } from './attractor';
4
+ export declare function injectAttractorDebug(object: THREE.Object3D, options: () => NgtrAttactorOptions, injector?: Injector): void;
@@ -0,0 +1,51 @@
1
+ import { InteractionGroups, RigidBody } from '@dimforge/rapier3d-compat';
2
+ import * as THREE from 'three';
3
+ import * as i0 from "@angular/core";
4
+ export declare function applyAttractorForceOnRigidBody(rigidBody: RigidBody, { object, strength, range, gravitationalConstant, collisionGroups, type, }: NgtrAttactorOptions & {
5
+ object: THREE.Object3D;
6
+ }): void;
7
+ export type NgtrAttractorGravityType = 'static' | 'linear' | 'newtonian';
8
+ export interface NgtrAttactorOptions {
9
+ /**
10
+ * The strength of the attractor.
11
+ * Positive values attract, negative values repel.
12
+ *
13
+ * @defaultValue 1
14
+ */
15
+ strength: number;
16
+ /**
17
+ * The range of the attractor. Will not affect objects outside of this range.
18
+ *
19
+ * @defaultValue 10
20
+ * @min 0
21
+ */
22
+ range: number;
23
+ /**
24
+ * The type of gravity to use.
25
+ * - static: The gravity is constant and does not change over time.
26
+ * - linear: The gravity is linearly interpolated the closer the object is to the attractor.
27
+ * - newtonian: The gravity is calculated using the newtonian gravity formula.
28
+ * @defaultValue "static"
29
+ */
30
+ type: NgtrAttractorGravityType;
31
+ /**
32
+ * The mass of the attractor. Used when type is `newtonian`.
33
+ * @defaultValue 6.673e-11
34
+ */
35
+ gravitationalConstant: number;
36
+ /**
37
+ * The collision groups that this attractor will apply effects to. If a RigidBody contains one or more colliders that are in one of the mask group, it will be affected by this attractor.
38
+ * If not specified, the attractor will apply effects to all RigidBodies.
39
+ */
40
+ collisionGroups?: InteractionGroups;
41
+ }
42
+ export declare class NgtrAttractor {
43
+ position: import("@angular/core").InputSignal<number | THREE.Vector3 | [x: number, y: number, z: number]>;
44
+ options: import("@angular/core").InputSignalWithTransform<NgtrAttactorOptions, "" | Partial<NgtrAttactorOptions>>;
45
+ private objectRef;
46
+ private collisionGroups;
47
+ linkedCollisionGroups: import("@angular/core").WritableSignal<number | undefined>;
48
+ constructor();
49
+ static ɵfac: i0.ɵɵFactoryDeclaration<NgtrAttractor, never>;
50
+ static ɵdir: i0.ɵɵDirectiveDeclaration<NgtrAttractor, "ngt-object3D[attractor]", never, { "position": { "alias": "position"; "required": false; "isSignal": true; }; "options": { "alias": "options"; "required": false; "isSignal": true; }; }, {}, never, never, true, never>;
51
+ }
@@ -0,0 +1,154 @@
1
+ import * as i0 from '@angular/core';
2
+ import { inject, computed, effect, input, ElementRef, linkedSignal, untracked, Directive } from '@angular/core';
3
+ import { injectStore, pick, injectBeforeRender, applyProps } from 'angular-three';
4
+ import { NgtrPhysics, injectBeforePhysicsStep, COLLISION_GROUPS_HANDLER } from 'angular-three-rapier';
5
+ import { mergeInputs } from 'ngxtension/inject-inputs';
6
+ import * as THREE from 'three';
7
+ import { assertInjector } from 'ngxtension/assert-injector';
8
+ import { VertexNormalsHelper } from 'three-stdlib';
9
+
10
+ const _v3 = new THREE.Vector3();
11
+ function injectAttractorDebug(object, options, injector) {
12
+ return assertInjector(injectAttractorDebug, injector, () => {
13
+ const physics = inject(NgtrPhysics);
14
+ const store = injectStore();
15
+ const strength = pick(options, 'strength');
16
+ const range = pick(options, 'range');
17
+ const color = computed(() => (strength() > 0 ? 0x0000ff : 0xff0000));
18
+ let mesh;
19
+ let normalsHelper;
20
+ effect((onCleanup) => {
21
+ if (!physics['debug']())
22
+ return;
23
+ mesh = new THREE.Mesh(new THREE.SphereGeometry(0.2, 6, 6), new THREE.MeshBasicMaterial({ color: color(), wireframe: true }));
24
+ normalsHelper = new VertexNormalsHelper(mesh, range(), color());
25
+ normalsHelper.frustumCulled = false;
26
+ store.snapshot.scene.add(mesh);
27
+ store.snapshot.scene.add(normalsHelper);
28
+ onCleanup(() => {
29
+ if (mesh) {
30
+ store.snapshot.scene.remove(mesh);
31
+ }
32
+ if (normalsHelper) {
33
+ store.snapshot.scene.remove(normalsHelper);
34
+ }
35
+ });
36
+ });
37
+ injectBeforeRender(() => {
38
+ if (!physics['debug']())
39
+ return;
40
+ if (mesh) {
41
+ const worldPosition = object.getWorldPosition(_v3);
42
+ mesh.position.copy(worldPosition);
43
+ normalsHelper?.update();
44
+ }
45
+ });
46
+ });
47
+ }
48
+
49
+ const calcForceByType = {
50
+ static: (s, m2, r, d, G) => s,
51
+ linear: (s, m2, r, d, G) => s * (d / r),
52
+ newtonian: (s, m2, r, d, G) => (G * s * m2) / Math.pow(d, 2),
53
+ };
54
+ const _position = new THREE.Vector3();
55
+ const _vector3 = new THREE.Vector3();
56
+ function applyAttractorForceOnRigidBody(rigidBody, { object, strength, range, gravitationalConstant, collisionGroups, type, }) {
57
+ const rbPosition = rigidBody.translation();
58
+ _position.set(rbPosition.x, rbPosition.y, rbPosition.z);
59
+ const worldPosition = object.getWorldPosition(new THREE.Vector3());
60
+ const distance = worldPosition.distanceTo(_position);
61
+ if (distance < range) {
62
+ let force = calcForceByType[type](strength, rigidBody.mass(), range, distance, gravitationalConstant);
63
+ // Prevent wild forces when Attractors collide
64
+ force = force === Infinity ? strength : force;
65
+ // Naively test if the rigidBody contains a collider in one of the collision groups
66
+ let isRigidBodyInCollisionGroup = collisionGroups === undefined;
67
+ if (collisionGroups !== undefined) {
68
+ for (let i = 0; i < rigidBody.numColliders(); i++) {
69
+ const collider = rigidBody.collider(i);
70
+ const colliderCollisionGroups = collider.collisionGroups();
71
+ if (((collisionGroups >> 16) & colliderCollisionGroups) != 0 &&
72
+ ((colliderCollisionGroups >> 16) & collisionGroups) != 0) {
73
+ isRigidBodyInCollisionGroup = true;
74
+ break;
75
+ }
76
+ }
77
+ }
78
+ if (isRigidBodyInCollisionGroup) {
79
+ _vector3.set(0, 0, 0).subVectors(worldPosition, _position).normalize().multiplyScalar(force);
80
+ rigidBody.applyImpulse(_vector3, true);
81
+ }
82
+ }
83
+ }
84
+ const defaultOptions = {
85
+ strength: 1,
86
+ range: 10,
87
+ type: 'static',
88
+ gravitationalConstant: 6.673e-11,
89
+ };
90
+ class NgtrAttractor {
91
+ position = input([0, 0, 0]);
92
+ options = input(defaultOptions, { transform: mergeInputs(defaultOptions) });
93
+ objectRef = inject(ElementRef);
94
+ collisionGroups = pick(this.options, 'collisionGroups');
95
+ linkedCollisionGroups = linkedSignal(this.collisionGroups);
96
+ constructor() {
97
+ effect(() => {
98
+ applyProps(this.objectRef.nativeElement, { position: this.position() });
99
+ });
100
+ injectBeforePhysicsStep((world) => {
101
+ const { strength, range, type, gravitationalConstant } = untracked(this.options);
102
+ const collisionGroups = untracked(this.linkedCollisionGroups);
103
+ world.bodies.forEach((body) => {
104
+ if (body.isDynamic()) {
105
+ applyAttractorForceOnRigidBody(body, {
106
+ object: this.objectRef.nativeElement,
107
+ strength,
108
+ range,
109
+ type,
110
+ gravitationalConstant,
111
+ collisionGroups,
112
+ });
113
+ }
114
+ });
115
+ });
116
+ injectAttractorDebug(this.objectRef.nativeElement, this.options);
117
+ }
118
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.1.6", ngImport: i0, type: NgtrAttractor, deps: [], target: i0.ɵɵFactoryTarget.Directive });
119
+ static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "19.1.6", type: NgtrAttractor, isStandalone: true, selector: "ngt-object3D[attractor]", inputs: { position: { classPropertyName: "position", publicName: "position", isSignal: true, isRequired: false, transformFunction: null }, options: { classPropertyName: "options", publicName: "options", isSignal: true, isRequired: false, transformFunction: null } }, providers: [
120
+ {
121
+ provide: COLLISION_GROUPS_HANDLER,
122
+ useFactory: (attractor) => {
123
+ return () => (interactionGroups) => {
124
+ attractor.linkedCollisionGroups.set(interactionGroups);
125
+ };
126
+ },
127
+ deps: [NgtrAttractor],
128
+ },
129
+ ], ngImport: i0 });
130
+ }
131
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.1.6", ngImport: i0, type: NgtrAttractor, decorators: [{
132
+ type: Directive,
133
+ args: [{
134
+ selector: 'ngt-object3D[attractor]',
135
+ providers: [
136
+ {
137
+ provide: COLLISION_GROUPS_HANDLER,
138
+ useFactory: (attractor) => {
139
+ return () => (interactionGroups) => {
140
+ attractor.linkedCollisionGroups.set(interactionGroups);
141
+ };
142
+ },
143
+ deps: [NgtrAttractor],
144
+ },
145
+ ],
146
+ }]
147
+ }], ctorParameters: () => [] });
148
+
149
+ /**
150
+ * Generated bundle index. Do not edit.
151
+ */
152
+
153
+ export { NgtrAttractor, applyAttractorForceOnRigidBody };
154
+ //# sourceMappingURL=angular-three-rapier-addons.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"angular-three-rapier-addons.mjs","sources":["../../../../libs/rapier/addons/src/lib/attractor-debug.ts","../../../../libs/rapier/addons/src/lib/attractor.ts","../../../../libs/rapier/addons/src/angular-three-rapier-addons.ts"],"sourcesContent":["import { computed, effect, inject, Injector } from '@angular/core';\nimport { injectBeforeRender, injectStore, pick } from 'angular-three';\nimport { NgtrPhysics } from 'angular-three-rapier';\nimport { assertInjector } from 'ngxtension/assert-injector';\nimport * as THREE from 'three';\nimport { VertexNormalsHelper } from 'three-stdlib';\nimport { NgtrAttactorOptions } from './attractor';\n\nconst _v3 = new THREE.Vector3();\n\nexport function injectAttractorDebug(object: THREE.Object3D, options: () => NgtrAttactorOptions, injector?: Injector) {\n\treturn assertInjector(injectAttractorDebug, injector, () => {\n\t\tconst physics = inject(NgtrPhysics);\n\t\tconst store = injectStore();\n\n\t\tconst strength = pick(options, 'strength');\n\t\tconst range = pick(options, 'range');\n\t\tconst color = computed(() => (strength() > 0 ? 0x0000ff : 0xff0000));\n\n\t\tlet mesh: THREE.Mesh;\n\t\tlet normalsHelper: VertexNormalsHelper;\n\n\t\teffect((onCleanup) => {\n\t\t\tif (!physics['debug']()) return;\n\n\t\t\tmesh = new THREE.Mesh(\n\t\t\t\tnew THREE.SphereGeometry(0.2, 6, 6),\n\t\t\t\tnew THREE.MeshBasicMaterial({ color: color(), wireframe: true }),\n\t\t\t);\n\n\t\t\tnormalsHelper = new VertexNormalsHelper(mesh, range(), color());\n\t\t\tnormalsHelper.frustumCulled = false;\n\n\t\t\tstore.snapshot.scene.add(mesh);\n\t\t\tstore.snapshot.scene.add(normalsHelper);\n\n\t\t\tonCleanup(() => {\n\t\t\t\tif (mesh) {\n\t\t\t\t\tstore.snapshot.scene.remove(mesh);\n\t\t\t\t}\n\n\t\t\t\tif (normalsHelper) {\n\t\t\t\t\tstore.snapshot.scene.remove(normalsHelper);\n\t\t\t\t}\n\t\t\t});\n\t\t});\n\n\t\tinjectBeforeRender(() => {\n\t\t\tif (!physics['debug']()) return;\n\n\t\t\tif (mesh) {\n\t\t\t\tconst worldPosition = object.getWorldPosition(_v3);\n\t\t\t\tmesh.position.copy(worldPosition);\n\t\t\t\tnormalsHelper?.update();\n\t\t\t}\n\t\t});\n\t});\n}\n","import { Directive, effect, ElementRef, inject, input, linkedSignal, untracked } from '@angular/core';\nimport { InteractionGroups, RigidBody } from '@dimforge/rapier3d-compat';\nimport { applyProps, NgtVector3, pick } from 'angular-three';\nimport { COLLISION_GROUPS_HANDLER, injectBeforePhysicsStep } from 'angular-three-rapier';\nimport { mergeInputs } from 'ngxtension/inject-inputs';\nimport * as THREE from 'three';\nimport { injectAttractorDebug } from './attractor-debug';\n\nconst calcForceByType = {\n\tstatic: (s: number, m2: number, r: number, d: number, G: number) => s,\n\tlinear: (s: number, m2: number, r: number, d: number, G: number) => s * (d / r),\n\tnewtonian: (s: number, m2: number, r: number, d: number, G: number) => (G * s * m2) / Math.pow(d, 2),\n};\n\nconst _position = new THREE.Vector3();\nconst _vector3 = new THREE.Vector3();\n\nexport function applyAttractorForceOnRigidBody(\n\trigidBody: RigidBody,\n\t{\n\t\tobject,\n\t\tstrength,\n\t\trange,\n\t\tgravitationalConstant,\n\t\tcollisionGroups,\n\t\ttype,\n\t}: NgtrAttactorOptions & { object: THREE.Object3D },\n) {\n\tconst rbPosition = rigidBody.translation();\n\t_position.set(rbPosition.x, rbPosition.y, rbPosition.z);\n\n\tconst worldPosition = object.getWorldPosition(new THREE.Vector3());\n\n\tconst distance: number = worldPosition.distanceTo(_position);\n\n\tif (distance < range) {\n\t\tlet force = calcForceByType[type](strength, rigidBody.mass(), range, distance, gravitationalConstant);\n\n\t\t// Prevent wild forces when Attractors collide\n\t\tforce = force === Infinity ? strength : force;\n\n\t\t// Naively test if the rigidBody contains a collider in one of the collision groups\n\t\tlet isRigidBodyInCollisionGroup = collisionGroups === undefined;\n\t\tif (collisionGroups !== undefined) {\n\t\t\tfor (let i = 0; i < rigidBody.numColliders(); i++) {\n\t\t\t\tconst collider = rigidBody.collider(i);\n\t\t\t\tconst colliderCollisionGroups = collider.collisionGroups();\n\t\t\t\tif (\n\t\t\t\t\t((collisionGroups >> 16) & colliderCollisionGroups) != 0 &&\n\t\t\t\t\t((colliderCollisionGroups >> 16) & collisionGroups) != 0\n\t\t\t\t) {\n\t\t\t\t\tisRigidBodyInCollisionGroup = true;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tif (isRigidBodyInCollisionGroup) {\n\t\t\t_vector3.set(0, 0, 0).subVectors(worldPosition, _position).normalize().multiplyScalar(force);\n\n\t\t\trigidBody.applyImpulse(_vector3, true);\n\t\t}\n\t}\n}\n\nexport type NgtrAttractorGravityType = 'static' | 'linear' | 'newtonian';\nexport interface NgtrAttactorOptions {\n\t/**\n\t * The strength of the attractor.\n\t * Positive values attract, negative values repel.\n\t *\n\t * @defaultValue 1\n\t */\n\tstrength: number;\n\n\t/**\n\t * The range of the attractor. Will not affect objects outside of this range.\n\t *\n\t * @defaultValue 10\n\t * @min 0\n\t */\n\trange: number;\n\n\t/**\n\t * The type of gravity to use.\n\t * - static: The gravity is constant and does not change over time.\n\t * - linear: The gravity is linearly interpolated the closer the object is to the attractor.\n\t * - newtonian: The gravity is calculated using the newtonian gravity formula.\n\t * @defaultValue \"static\"\n\t */\n\ttype: NgtrAttractorGravityType;\n\n\t/**\n\t * The mass of the attractor. Used when type is `newtonian`.\n\t * @defaultValue 6.673e-11\n\t */\n\tgravitationalConstant: number;\n\n\t/**\n\t * The collision groups that this attractor will apply effects to. If a RigidBody contains one or more colliders that are in one of the mask group, it will be affected by this attractor.\n\t * If not specified, the attractor will apply effects to all RigidBodies.\n\t */\n\tcollisionGroups?: InteractionGroups;\n}\n\nconst defaultOptions: NgtrAttactorOptions = {\n\tstrength: 1,\n\trange: 10,\n\ttype: 'static',\n\tgravitationalConstant: 6.673e-11,\n};\n\n@Directive({\n\tselector: 'ngt-object3D[attractor]',\n\tproviders: [\n\t\t{\n\t\t\tprovide: COLLISION_GROUPS_HANDLER,\n\t\t\tuseFactory: (attractor: NgtrAttractor) => {\n\t\t\t\treturn () => (interactionGroups: InteractionGroups) => {\n\t\t\t\t\tattractor.linkedCollisionGroups.set(interactionGroups);\n\t\t\t\t};\n\t\t\t},\n\t\t\tdeps: [NgtrAttractor],\n\t\t},\n\t],\n})\nexport class NgtrAttractor {\n\tposition = input<NgtVector3>([0, 0, 0]);\n\toptions = input(defaultOptions, { transform: mergeInputs(defaultOptions) });\n\n\tprivate objectRef = inject<ElementRef<THREE.Object3D>>(ElementRef);\n\tprivate collisionGroups = pick(this.options, 'collisionGroups');\n\tlinkedCollisionGroups = linkedSignal(this.collisionGroups);\n\n\tconstructor() {\n\t\teffect(() => {\n\t\t\tapplyProps(this.objectRef.nativeElement, { position: this.position() });\n\t\t});\n\n\t\tinjectBeforePhysicsStep((world) => {\n\t\t\tconst { strength, range, type, gravitationalConstant } = untracked(this.options);\n\t\t\tconst collisionGroups = untracked(this.linkedCollisionGroups);\n\t\t\tworld.bodies.forEach((body) => {\n\t\t\t\tif (body.isDynamic()) {\n\t\t\t\t\tapplyAttractorForceOnRigidBody(body, {\n\t\t\t\t\t\tobject: this.objectRef.nativeElement,\n\t\t\t\t\t\tstrength,\n\t\t\t\t\t\trange,\n\t\t\t\t\t\ttype,\n\t\t\t\t\t\tgravitationalConstant,\n\t\t\t\t\t\tcollisionGroups,\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t});\n\t\t});\n\n\t\tinjectAttractorDebug(this.objectRef.nativeElement, this.options);\n\t}\n}\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":"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"}
@@ -1,5 +1,5 @@
1
1
  import * as i0 from '@angular/core';
2
- import { inject, viewChild, Component, CUSTOM_ELEMENTS_SCHEMA, ChangeDetectionStrategy, input, effect, Directive, contentChild, TemplateRef, signal, computed, untracked, DestroyRef, model, output, ElementRef, viewChildren } from '@angular/core';
2
+ import { InjectionToken, input, computed, inject, effect, Directive, viewChild, Component, CUSTOM_ELEMENTS_SCHEMA, ChangeDetectionStrategy, contentChild, TemplateRef, signal, untracked, DestroyRef, model, output, ElementRef, viewChildren } from '@angular/core';
3
3
  import { Vector3, Quaternion, EventQueue, ColliderDesc, ActiveEvents, RigidBodyDesc } from '@dimforge/rapier3d-compat';
4
4
  import { extend, injectBeforeRender, injectStore, is, pick, vector3, applyProps, getInstanceState, getEmitter, hasListener, resolveRef } from 'angular-three';
5
5
  import { mergeInputs } from 'ngxtension/inject-inputs';
@@ -9,6 +9,70 @@ import { NgTemplateOutlet } from '@angular/common';
9
9
  import { mergeVertices } from 'three-stdlib';
10
10
  import { assertInjector } from 'ngxtension/assert-injector';
11
11
 
12
+ /**
13
+ * Calculates an InteractionGroup bitmask for use in the `collisionGroups` or `solverGroups`
14
+ * properties of RigidBody or Collider components. The first argument represents a list of
15
+ * groups the entity is in (expressed as numbers from 0 to 15). The second argument is a list
16
+ * of groups that will be filtered against. When it is omitted, all groups are filtered against.
17
+ *
18
+ * @example
19
+ * A RigidBody that is member of group 0 and will collide with everything from groups 0 and 1:
20
+ *
21
+ * ```tsx
22
+ * <RigidBody collisionGroups={interactionGroups([0], [0, 1])} />
23
+ * ```
24
+ *
25
+ * A RigidBody that is member of groups 0 and 1 and will collide with everything else:
26
+ *
27
+ * ```tsx
28
+ * <RigidBody collisionGroups={interactionGroups([0, 1])} />
29
+ * ```
30
+ *
31
+ * A RigidBody that is member of groups 0 and 1 and will not collide with anything:
32
+ *
33
+ * ```tsx
34
+ * <RigidBody collisionGroups={interactionGroups([0, 1], [])} />
35
+ * ```
36
+ *
37
+ * Please note that Rapier needs interaction filters to evaluate to true between _both_ colliding
38
+ * entities for collision events to trigger.
39
+ *
40
+ * @param memberships Groups the collider is a member of. (Values can range from 0 to 15.)
41
+ * @param filters Groups the interaction group should filter against. (Values can range from 0 to 15.)
42
+ * @returns An InteractionGroup bitmask.
43
+ */
44
+ function interactionGroups(memberships, filters) {
45
+ return (bitmask(memberships) << 16) + (filters !== undefined ? bitmask(filters) : 0b1111_1111_1111_1111);
46
+ }
47
+ function bitmask(groups) {
48
+ return [groups].flat().reduce((acc, layer) => acc | (1 << layer), 0);
49
+ }
50
+ const COLLISION_GROUPS_HANDLER = new InjectionToken('COLLISION_GROUPS_HANDLER');
51
+ class NgtrInteractionGroups {
52
+ inputs = input.required({ alias: 'interactionGroups' });
53
+ interactionGroups = computed(() => {
54
+ const [memberships, filters] = this.inputs();
55
+ return interactionGroups(memberships, filters);
56
+ });
57
+ constructor() {
58
+ const collisionGroupsHandlerFn = inject(COLLISION_GROUPS_HANDLER, { host: true, optional: true });
59
+ effect(() => {
60
+ if (!collisionGroupsHandlerFn)
61
+ return;
62
+ const handler = collisionGroupsHandlerFn();
63
+ if (!handler)
64
+ return;
65
+ handler(this.interactionGroups());
66
+ });
67
+ }
68
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.1.6", ngImport: i0, type: NgtrInteractionGroups, deps: [], target: i0.ɵɵFactoryTarget.Directive });
69
+ static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "19.1.6", type: NgtrInteractionGroups, isStandalone: true, selector: "ngt-object3D[interactionGroups]", inputs: { inputs: { classPropertyName: "inputs", publicName: "interactionGroups", isSignal: true, isRequired: true, transformFunction: null } }, ngImport: i0 });
70
+ }
71
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.1.6", ngImport: i0, type: NgtrInteractionGroups, decorators: [{
72
+ type: Directive,
73
+ args: [{ selector: 'ngt-object3D[interactionGroups]' }]
74
+ }], ctorParameters: () => [] });
75
+
12
76
  class NgtrDebug {
13
77
  physics = inject(NgtrPhysics);
14
78
  lineSegmentsRef = viewChild.required('lineSegments');
@@ -956,6 +1020,7 @@ class NgtrRigidBody {
956
1020
  quaternion = input();
957
1021
  userData = input();
958
1022
  options = input(rigidBodyDefaultOptions, { transform: mergeInputs(rigidBodyDefaultOptions) });
1023
+ anyColliders = viewChildren(NgtrAnyCollider);
959
1024
  object3DParameters = computed(() => {
960
1025
  const [position, rotation, scale, quaternion, userData] = [
961
1026
  this.position(),
@@ -1181,7 +1246,28 @@ class NgtrRigidBody {
1181
1246
  };
1182
1247
  }
1183
1248
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.1.6", ngImport: i0, type: NgtrRigidBody, deps: [], target: i0.ɵɵFactoryTarget.Component });
1184
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.1.6", type: NgtrRigidBody, isStandalone: true, selector: "ngt-object3D[rigidBody]", inputs: { type: { classPropertyName: "type", publicName: "rigidBody", isSignal: true, isRequired: true, transformFunction: null }, position: { classPropertyName: "position", publicName: "position", isSignal: true, isRequired: false, transformFunction: null }, rotation: { classPropertyName: "rotation", publicName: "rotation", isSignal: true, isRequired: false, transformFunction: null }, scale: { classPropertyName: "scale", publicName: "scale", isSignal: true, isRequired: false, transformFunction: null }, quaternion: { classPropertyName: "quaternion", publicName: "quaternion", isSignal: true, isRequired: false, transformFunction: null }, userData: { classPropertyName: "userData", publicName: "userData", isSignal: true, isRequired: false, transformFunction: null }, options: { classPropertyName: "options", publicName: "options", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { wake: "wake", sleep: "sleep", collisionEnter: "collisionEnter", collisionExit: "collisionExit", intersectionEnter: "intersectionEnter", intersectionExit: "intersectionExit", contactForce: "contactForce" }, exportAs: ["rigidBody"], ngImport: i0, template: `
1249
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.1.6", type: NgtrRigidBody, isStandalone: true, selector: "ngt-object3D[rigidBody]", inputs: { type: { classPropertyName: "type", publicName: "rigidBody", isSignal: true, isRequired: true, transformFunction: null }, position: { classPropertyName: "position", publicName: "position", isSignal: true, isRequired: false, transformFunction: null }, rotation: { classPropertyName: "rotation", publicName: "rotation", isSignal: true, isRequired: false, transformFunction: null }, scale: { classPropertyName: "scale", publicName: "scale", isSignal: true, isRequired: false, transformFunction: null }, quaternion: { classPropertyName: "quaternion", publicName: "quaternion", isSignal: true, isRequired: false, transformFunction: null }, userData: { classPropertyName: "userData", publicName: "userData", isSignal: true, isRequired: false, transformFunction: null }, options: { classPropertyName: "options", publicName: "options", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { wake: "wake", sleep: "sleep", collisionEnter: "collisionEnter", collisionExit: "collisionExit", intersectionEnter: "intersectionEnter", intersectionExit: "intersectionExit", contactForce: "contactForce" }, providers: [
1250
+ {
1251
+ provide: COLLISION_GROUPS_HANDLER,
1252
+ useFactory: (rigidBody) => {
1253
+ return () => {
1254
+ const anyColliders = rigidBody.anyColliders();
1255
+ if (!anyColliders.length)
1256
+ return;
1257
+ const colliders = anyColliders.map((anyCollider) => anyCollider['collider']);
1258
+ return (interactionGroups) => {
1259
+ for (const colliderFn of colliders) {
1260
+ const collider = colliderFn();
1261
+ if (!collider)
1262
+ continue;
1263
+ collider.setCollisionGroups(interactionGroups);
1264
+ }
1265
+ };
1266
+ };
1267
+ },
1268
+ deps: [NgtrRigidBody],
1269
+ },
1270
+ ], viewQueries: [{ propertyName: "anyColliders", predicate: NgtrAnyCollider, descendants: true, isSignal: true }], exportAs: ["rigidBody"], ngImport: i0, template: `
1185
1271
  <ng-content />
1186
1272
  @for (childColliderOption of childColliderOptions(); track $index) {
1187
1273
  <ngt-object3D
@@ -1218,6 +1304,28 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.1.6", ngImpor
1218
1304
  schemas: [CUSTOM_ELEMENTS_SCHEMA],
1219
1305
  changeDetection: ChangeDetectionStrategy.OnPush,
1220
1306
  imports: [NgtrAnyCollider],
1307
+ providers: [
1308
+ {
1309
+ provide: COLLISION_GROUPS_HANDLER,
1310
+ useFactory: (rigidBody) => {
1311
+ return () => {
1312
+ const anyColliders = rigidBody.anyColliders();
1313
+ if (!anyColliders.length)
1314
+ return;
1315
+ const colliders = anyColliders.map((anyCollider) => anyCollider['collider']);
1316
+ return (interactionGroups) => {
1317
+ for (const colliderFn of colliders) {
1318
+ const collider = colliderFn();
1319
+ if (!collider)
1320
+ continue;
1321
+ collider.setCollisionGroups(interactionGroups);
1322
+ }
1323
+ };
1324
+ };
1325
+ },
1326
+ deps: [NgtrRigidBody],
1327
+ },
1328
+ ],
1221
1329
  }]
1222
1330
  }], ctorParameters: () => [] });
1223
1331
 
@@ -1832,9 +1940,28 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.1.6", ngImpor
1832
1940
  }]
1833
1941
  }], ctorParameters: () => [] });
1834
1942
 
1943
+ function injectBeforePhysicsStep(callback, injector) {
1944
+ return assertInjector(injectBeforePhysicsStep, injector, () => {
1945
+ const physics = inject(NgtrPhysics);
1946
+ physics.beforeStepCallbacks.add(callback);
1947
+ inject(DestroyRef).onDestroy(() => {
1948
+ physics.beforeStepCallbacks.delete(callback);
1949
+ });
1950
+ });
1951
+ }
1952
+ function injectAfterPhysicsStep(callback, injector) {
1953
+ return assertInjector(injectAfterPhysicsStep, injector, () => {
1954
+ const physics = inject(NgtrPhysics);
1955
+ physics.afterStepCallbacks.add(callback);
1956
+ inject(DestroyRef).onDestroy(() => {
1957
+ physics.afterStepCallbacks.delete(callback);
1958
+ });
1959
+ });
1960
+ }
1961
+
1835
1962
  /**
1836
1963
  * Generated bundle index. Do not edit.
1837
1964
  */
1838
1965
 
1839
- export { NgtrAnyCollider, NgtrBallCollider, NgtrCapsuleCollider, NgtrConeCollider, NgtrConvexHullCollider, NgtrConvexMeshCollider, NgtrCuboidCollider, NgtrCylinderCollider, NgtrHeightfieldCollider, NgtrInstancedRigidBodies, NgtrMeshCollider, NgtrPhysics, NgtrPhysicsFallback, NgtrPolylineCollider, NgtrRigidBody, NgtrRoundConeCollider, NgtrRoundConvexHullCollider, NgtrRoundConvexMeshCollider, NgtrRoundCuboidCollider, NgtrRoundCylinderCollider, NgtrTrimeshCollider, injectFixedJoint, injectPrismaticJoint, injectRevoluteJoint, injectRopeJoint, injectSphericalJoint, injectSpringJoint, rigidBodyDefaultOptions };
1966
+ export { COLLISION_GROUPS_HANDLER, NgtrAnyCollider, NgtrBallCollider, NgtrCapsuleCollider, NgtrConeCollider, NgtrConvexHullCollider, NgtrConvexMeshCollider, NgtrCuboidCollider, NgtrCylinderCollider, NgtrHeightfieldCollider, NgtrInstancedRigidBodies, NgtrInteractionGroups, NgtrMeshCollider, NgtrPhysics, NgtrPhysicsFallback, NgtrPolylineCollider, NgtrRigidBody, NgtrRoundConeCollider, NgtrRoundConvexHullCollider, NgtrRoundConvexMeshCollider, NgtrRoundCuboidCollider, NgtrRoundCylinderCollider, NgtrTrimeshCollider, injectAfterPhysicsStep, injectBeforePhysicsStep, injectFixedJoint, injectPrismaticJoint, injectRevoluteJoint, injectRopeJoint, injectSphericalJoint, injectSpringJoint, interactionGroups, rigidBodyDefaultOptions };
1840
1967
  //# sourceMappingURL=angular-three-rapier.mjs.map