@cyclonium/physics-2d 0.0.100

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.
Files changed (65) hide show
  1. package/lib/body-collider-link.d.ts +32 -0
  2. package/lib/body-collider-link.js +164 -0
  3. package/lib/character-controller-2d.d.ts +69 -0
  4. package/lib/character-controller-2d.js +399 -0
  5. package/lib/collider-2d.d.ts +81 -0
  6. package/lib/collider-2d.js +364 -0
  7. package/lib/colliders/box-collider-2d.d.ts +20 -0
  8. package/lib/colliders/box-collider-2d.js +84 -0
  9. package/lib/colliders/capsule-collider-2d.d.ts +17 -0
  10. package/lib/colliders/capsule-collider-2d.js +78 -0
  11. package/lib/colliders/circle-collider-2d.d.ts +14 -0
  12. package/lib/colliders/circle-collider-2d.js +59 -0
  13. package/lib/colliders/polygon-collider-2d.d.ts +17 -0
  14. package/lib/colliders/polygon-collider-2d.js +77 -0
  15. package/lib/collision-matrix.d.ts +12 -0
  16. package/lib/collision-matrix.js +70 -0
  17. package/lib/contact.d.ts +7 -0
  18. package/lib/contact.js +2 -0
  19. package/lib/exchange.d.ts +5 -0
  20. package/lib/exchange.js +23 -0
  21. package/lib/gizmo-headless.d.ts +7 -0
  22. package/lib/gizmo-headless.js +7 -0
  23. package/lib/gizmo.d.ts +13 -0
  24. package/lib/gizmo.js +122 -0
  25. package/lib/index.d.ts +20 -0
  26. package/lib/index.js +20 -0
  27. package/lib/physics-2d-debugger-headless.d.ts +6 -0
  28. package/lib/physics-2d-debugger-headless.js +9 -0
  29. package/lib/physics-2d-debugger.d.ts +11 -0
  30. package/lib/physics-2d-debugger.js +146 -0
  31. package/lib/physics-2d-settings.d.ts +13 -0
  32. package/lib/physics-2d-settings.js +53 -0
  33. package/lib/physics-component-2d-base.d.ts +22 -0
  34. package/lib/physics-component-2d-base.js +85 -0
  35. package/lib/physics-world-2d-scene-component.d.ts +20 -0
  36. package/lib/physics-world-2d-scene-component.js +107 -0
  37. package/lib/physics-world-2d.d.ts +103 -0
  38. package/lib/physics-world-2d.js +506 -0
  39. package/lib/physics-world-registry.d.ts +6 -0
  40. package/lib/physics-world-registry.js +26 -0
  41. package/lib/px2-impl.d.ts +4 -0
  42. package/lib/px2-impl.js +18 -0
  43. package/lib/rigid-body-2d.d.ts +72 -0
  44. package/lib/rigid-body-2d.js +391 -0
  45. package/lib/scene-query-probe-2d.d.ts +102 -0
  46. package/lib/scene-query-probe-2d.js +223 -0
  47. package/lib/scene-query-probes/box-scene-query-probe-2d.d.ts +21 -0
  48. package/lib/scene-query-probes/box-scene-query-probe-2d.js +62 -0
  49. package/lib/scene-query-probes/capsule-scene-query-probe-2d.d.ts +27 -0
  50. package/lib/scene-query-probes/capsule-scene-query-probe-2d.js +96 -0
  51. package/lib/scene-query-probes/circle-scene-query-probe-2d.d.ts +20 -0
  52. package/lib/scene-query-probes/circle-scene-query-probe-2d.js +64 -0
  53. package/lib/scene-query.d.ts +67 -0
  54. package/lib/scene-query.js +128 -0
  55. package/lib/shared.d.ts +9 -0
  56. package/lib/shared.js +42 -0
  57. package/lib/utils/3-to-2.d.ts +3 -0
  58. package/lib/utils/3-to-2.js +12 -0
  59. package/lib/wasm-binary-helper/index.d.ts +6 -0
  60. package/lib/wasm-binary-helper/index.js +14 -0
  61. package/lib/wasm-binary-helper/wasm-binary-id.d.ts +2 -0
  62. package/lib/wasm-binary-helper/wasm-binary-id.js +2 -0
  63. package/lib/wasm-binary-helper.d.ts +6 -0
  64. package/lib/wasm-binary-helper.js +6 -0
  65. package/package.json +50 -0
@@ -0,0 +1,506 @@
1
+ import { Scene } from 'cc';
2
+ import { logger } from '@cyclonium/core/log';
3
+ import { prune } from '@cyclonium/algorithm/prune';
4
+ import { assert } from '@cyclonium/core/utils';
5
+ import { BodyColliderLink, BodyColliderLinkManager } from './body-collider-link.js';
6
+ import { CollisionMatrix } from './collision-matrix.js';
7
+ import {} from './contact.js';
8
+ import { fromPx2ImplVec2, toPx2ImplVec2 } from './exchange.js';
9
+ import { invokeOnAfterStep, invokeOnSyncTransforms, PhysicsComponent2DBase } from './physics-component-2d-base.js';
10
+ import { px2Impl } from './px2-impl.js';
11
+ import { RigidBody2D } from './rigid-body-2d.js';
12
+ import { Vec2 } from '@cyclonium/core/math/vec2';
13
+ import { ManagedEventEmitter } from '@cyclonium/event';
14
+ import { Ray2D } from '@cyclonium/core/math/ray';
15
+ import { getPhysicsWorld, registerPhysicsWorld, unregisterPhysicsWorld } from './physics-world-registry.js';
16
+ import { ColliderShapeCastHit, RayColliderIntersection } from './scene-query.js';
17
+ export class RaycastResult {
18
+ constructor(ray, collider, distance) {
19
+ this._ray = ray;
20
+ this._collider = collider;
21
+ this._distance = distance;
22
+ }
23
+ get collider() {
24
+ return this._collider;
25
+ }
26
+ get distance() {
27
+ return this._distance;
28
+ }
29
+ get position() {
30
+ return this._ray.at(this._distance);
31
+ }
32
+ _ray;
33
+ _collider;
34
+ _distance;
35
+ }
36
+ export class PhysicsWorld2D {
37
+ static of(scene) {
38
+ const world = PhysicsWorld2D.ofUndefined(scene);
39
+ if (!world) {
40
+ throw new Error(`PhysicsWorld2D not found for scene ${scene.name}.`);
41
+ }
42
+ return world;
43
+ }
44
+ static ofUndefined(scene) {
45
+ return getPhysicsWorld(scene);
46
+ }
47
+ constructor({ scene, tags, collisionMatrix, solverMatrix, }) {
48
+ registerPhysicsWorld(scene, this);
49
+ Object.assign(this._tags, tags);
50
+ this._collisionMatrix = collisionMatrix.clone();
51
+ this._solverMatrix = solverMatrix.clone();
52
+ this._worldImpl = new px2Impl.World(new px2Impl.Vector2(0, -9.81), undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined);
53
+ this._eventQueue = new px2Impl.EventQueue(true);
54
+ }
55
+ get listenersOnWillDestroy() {
56
+ return this._emitterForWillDestroy.registry;
57
+ }
58
+ get impl() {
59
+ return this._worldImpl;
60
+ }
61
+ destroy() {
62
+ unregisterPhysicsWorld(this);
63
+ this._emitterForWillDestroy.emit();
64
+ this._worldImpl.free();
65
+ this._worldImpl = null;
66
+ }
67
+ step(_deltaTime) {
68
+ const outdated = this._outDated;
69
+ this._outDated = false;
70
+ for (const component of this._physicsComponents) {
71
+ if (!component.enabled) {
72
+ continue;
73
+ }
74
+ invokeOnSyncTransforms(component, outdated, outdated);
75
+ }
76
+ this._worldImpl.step(this._eventQueue);
77
+ for (const component of this._physicsComponents) {
78
+ if (!component.enabled) {
79
+ continue;
80
+ }
81
+ invokeOnAfterStep(component);
82
+ }
83
+ this._emitEvents();
84
+ }
85
+ setOutdated() {
86
+ this._outDated = true;
87
+ }
88
+ getTagId(tag) {
89
+ const tagId = this._tags[tag];
90
+ if (tagId === undefined) {
91
+ throw new Error(`Tag ${tag} not found.`);
92
+ }
93
+ return tagId;
94
+ }
95
+ *intersectionWithPoint(point, filter) {
96
+ const colliders = [];
97
+ this._worldImpl.intersectionsWithPoint(toPx2ImplVec2(point), (colliderImpl) => {
98
+ const collider = this.getColliderWithWarn_internal(colliderImpl);
99
+ if (collider) {
100
+ colliders.push(collider);
101
+ }
102
+ return true;
103
+ }, filter._filterFlags_internal, filter._filterGroups_internal, undefined, undefined, undefined);
104
+ yield* colliders;
105
+ }
106
+ *intersectionWithCollider(collider, filter) {
107
+ const implCollider = collider.impl_internal;
108
+ if (!implCollider) {
109
+ return;
110
+ }
111
+ const colliders = [];
112
+ this._worldImpl.intersectionWithShape(implCollider.translation(), implCollider.rotation(), implCollider.shape, filter._filterFlags_internal, filter._filterGroups_internal, undefined, undefined, (otherImplCollider) => {
113
+ const otherCollider = this.getColliderWithWarn_internal(otherImplCollider);
114
+ if (otherCollider) {
115
+ colliders.push(otherCollider);
116
+ }
117
+ return true;
118
+ });
119
+ yield* colliders;
120
+ }
121
+ intersectWithCircle(center, radius, filter, rotation = 0) {
122
+ return this._intersectWithShape(new px2Impl.Ball(radius), center, rotation, filter);
123
+ }
124
+ intersectWithBox(center, halfExtents, filter, rotation = 0) {
125
+ return this._intersectWithShape(new px2Impl.Cuboid(halfExtents.x, halfExtents.y), center, rotation, filter);
126
+ }
127
+ /**
128
+ * Finds colliders overlapping a capsule shape.
129
+ */
130
+ intersectWithCapsule(capsule, filter) {
131
+ return this._intersectWithShape(new px2Impl.Capsule(capsule.halfHeight, capsule.radius), capsule.position, capsule.rotation ?? 0, filter);
132
+ }
133
+ *intersectWithRay(ray, maxDistance, filter) {
134
+ const intersections = [];
135
+ this._worldImpl.intersectionsWithRay(new px2Impl.Ray(toPx2ImplVec2(ray.origin), toPx2ImplVec2(ray.direction)), maxDistance, false, (intersection) => {
136
+ const collider = this.getColliderWithWarn_internal(intersection.collider);
137
+ if (collider) {
138
+ intersections.push(new RayColliderIntersection(collider, intersection.timeOfImpact, fromPx2ImplVec2(intersection.normal)));
139
+ }
140
+ return true;
141
+ }, filter._filterFlags_internal, filter._filterGroups_internal, undefined, undefined, undefined);
142
+ yield* intersections;
143
+ }
144
+ castRay(ray, maxDistance, filter) {
145
+ const rayColliderHit = this._worldImpl.castRay(new px2Impl.Ray(toPx2ImplVec2(ray.origin), toPx2ImplVec2(ray.direction)), maxDistance, false, filter._filterFlags_internal, filter._filterGroups_internal, undefined, undefined, undefined);
146
+ if (!rayColliderHit) {
147
+ return undefined;
148
+ }
149
+ const collider = this.getColliderWithWarn_internal(rayColliderHit.collider);
150
+ if (!collider) {
151
+ return undefined;
152
+ }
153
+ return new RaycastResult(new Ray2D(ray.origin, ray.direction), collider, rayColliderHit.timeOfImpact);
154
+ }
155
+ castCircle(circle, opts) {
156
+ return this._castShape(new px2Impl.Ball(circle.radius), circle, opts);
157
+ }
158
+ castRect(rect, opts) {
159
+ return this._castShape(new px2Impl.Cuboid(rect.halfExtents.x, rect.halfExtents.y), rect, opts);
160
+ }
161
+ castCapsule(capsule, opts) {
162
+ return this._castShape(new px2Impl.Capsule(capsule.halfHeight, capsule.radius), capsule, opts);
163
+ }
164
+ /**
165
+ * Pushes current scene graph transforms to the physics backend without stepping simulation.
166
+ */
167
+ syncTransforms() {
168
+ for (const component of this._physicsComponents) {
169
+ if (!component.enabled) {
170
+ continue;
171
+ }
172
+ invokeOnSyncTransforms(component, true, false);
173
+ }
174
+ this._worldImpl.propagateModifiedBodyPositionsToColliders();
175
+ this._worldImpl.updateSceneQueries();
176
+ }
177
+ _createRigidBody(component, desc) {
178
+ if (this._physicsComponents.has(component)) {
179
+ throw new Error('RigidBody already created for this component.');
180
+ }
181
+ const impl = this._worldImpl.createRigidBody(desc);
182
+ this._physicsComponents.add(component);
183
+ const link = this._linkManager.joinRigidBody(component);
184
+ this._rigidBodies.set(impl.handle, {
185
+ component,
186
+ link,
187
+ impl,
188
+ });
189
+ return {
190
+ impl,
191
+ enableCollisionEvents(value) {
192
+ link.enableCollisionEventsFromBody(value);
193
+ },
194
+ setTags: (tags) => {
195
+ let groupBits = 0;
196
+ let collisionBits = 0;
197
+ let solverBits = 0;
198
+ if (tags.length === 0) {
199
+ logger.warn(`RigidBody ${component.name} has no any tag, this leads to no scene query can be made to its colliders.`);
200
+ }
201
+ for (const tag of tags) {
202
+ const tagBitIndex = this._getTagBit(tag);
203
+ if (tagBitIndex < 0) {
204
+ logger.warn(`Tag ${tag} not found`);
205
+ }
206
+ else {
207
+ groupBits |= (1 << tagBitIndex);
208
+ const collisionBitsOfTag = this._collisionMatrix.getCollisionsBitsOf(tagBitIndex);
209
+ collisionBits |= collisionBitsOfTag;
210
+ const solverBitsOfTag = this._solverMatrix.getCollisionsBitsOf(tagBitIndex);
211
+ solverBits |= solverBitsOfTag;
212
+ }
213
+ }
214
+ // > The membership and filter are both 16-bit bit masks packed into a single 32-bits value.
215
+ // > The 16 left-most bits contain the memberships whereas the 16 right-most bits contain the filter.
216
+ link.setBodyCollisionGroups((groupBits << 16) | collisionBits);
217
+ link.setBodySolverGroups((groupBits << 16) | solverBits);
218
+ },
219
+ setActiveCollisionTypes(activeCollisionTypes) {
220
+ link.setBodyActiveCollisionTypes(activeCollisionTypes);
221
+ },
222
+ };
223
+ }
224
+ _removeRigidBody(impl) {
225
+ const key = impl.handle;
226
+ const record = this._rigidBodies.get(key);
227
+ if (!record) {
228
+ logger.warn(`RigidBody ${key} not found`);
229
+ return;
230
+ }
231
+ this._rigidBodies.delete(key);
232
+ assert(record.impl === impl);
233
+ if (!this._physicsComponents.delete(record.component)) {
234
+ logger.warn(`RigidBody ${key} not found in physics components`);
235
+ }
236
+ if (!this._linkManager.removeRigidBody(record.component)) {
237
+ logger.warn(`RigidBody ${key} not found in link manager`);
238
+ }
239
+ // This should be the last since above calls call to impl rigid body/impl colliders.
240
+ this._worldImpl.removeRigidBody(impl);
241
+ }
242
+ _addColliderHandle(component) {
243
+ if (this._physicsComponents.has(component)) {
244
+ throw new Error('Collider handle already created for this component.');
245
+ }
246
+ this._physicsComponents.add(component);
247
+ this._linkManager.joinCollider(component);
248
+ // eslint-disable-next-line @typescript-eslint/no-this-alias
249
+ const world = this;
250
+ return {
251
+ component,
252
+ destroy(wakeUp) {
253
+ this.removeCollider(wakeUp);
254
+ if (!world._physicsComponents.delete(component)) {
255
+ logger.warn(`Collider ${component} not found in physics components`);
256
+ }
257
+ if (!world._linkManager.removeCollider(component)) {
258
+ logger.warn(`Collider ${component} not found in link manager`);
259
+ }
260
+ },
261
+ get attachedRigidBody() {
262
+ return world._linkManager.getLinkedRigidBody(component)?.rigidBody ?? null;
263
+ },
264
+ impl: null,
265
+ createCollider(desc) {
266
+ this.removeCollider(false);
267
+ const rigidBody = this.attachedRigidBody;
268
+ const impl = world._createImplCollider(component, desc, rigidBody?.impl);
269
+ this.impl = impl;
270
+ return impl;
271
+ },
272
+ removeCollider(wakeUp) {
273
+ const impl = this.impl;
274
+ if (!impl) {
275
+ return;
276
+ }
277
+ world._removeImplCollider(impl, wakeUp);
278
+ this.impl = null;
279
+ },
280
+ };
281
+ }
282
+ _getCollider(impl) {
283
+ return this._colliders.get(impl.handle)?.component ?? undefined;
284
+ }
285
+ getColliderWithWarn_internal(impl) {
286
+ const collider = this._getCollider(impl);
287
+ if (!collider) {
288
+ logger.warn(`Collider ${impl.handle} not found`);
289
+ }
290
+ return collider;
291
+ }
292
+ _tags = {};
293
+ _collisionMatrix;
294
+ _solverMatrix;
295
+ _worldImpl;
296
+ _eventQueue;
297
+ _linkManager = new BodyColliderLinkManager();
298
+ _rigidBodies = new Map();
299
+ _colliders = new Map();
300
+ _collisionRecords = [];
301
+ _physicsComponents = new Set();
302
+ _outDated = false;
303
+ _emitterForWillDestroy = new ManagedEventEmitter();
304
+ _getTagBit(tag) {
305
+ return this._tags[tag] ?? -1;
306
+ }
307
+ _createImplCollider(component, desc, parent) {
308
+ const impl = this._worldImpl.createCollider(desc, parent);
309
+ this._colliders.set(impl.handle, { impl, component });
310
+ return impl;
311
+ }
312
+ _removeImplCollider(impl, wakeUp) {
313
+ const key = impl.handle;
314
+ const colliderRecord = this._colliders.get(key);
315
+ if (!colliderRecord) {
316
+ logger.warn(`Collider ${key} not found`);
317
+ }
318
+ else {
319
+ this._colliders.delete(key);
320
+ assert(colliderRecord.impl === impl);
321
+ }
322
+ this._collisionRecords.forEach((record) => {
323
+ if (record.collider1.impl !== impl && record.collider2.impl !== impl) {
324
+ return;
325
+ }
326
+ if (record.state === CollisionRecordState.start) {
327
+ this._emitCollisionEvent(record, 'onContactEnd');
328
+ }
329
+ });
330
+ // todo: should notify the other side?
331
+ prune(this._collisionRecords, (record) => record.collider1.impl !== impl && record.collider2.impl !== impl);
332
+ this._worldImpl.removeCollider(impl, wakeUp);
333
+ }
334
+ _emitEvents() {
335
+ let exception;
336
+ let hasException = false;
337
+ const catchCallback = (callback) => {
338
+ return (...args) => {
339
+ if (hasException) {
340
+ return;
341
+ }
342
+ try {
343
+ callback(...args);
344
+ }
345
+ catch (e) {
346
+ exception = e;
347
+ hasException = true;
348
+ }
349
+ };
350
+ };
351
+ this._eventQueue.drainCollisionEvents(catchCallback((collider1Handle, collider2Handle, started) => {
352
+ // Find local colliders.
353
+ const collider1 = this._colliders.get(collider1Handle);
354
+ const collider2 = this._colliders.get(collider2Handle);
355
+ if (!collider1 || !collider2) {
356
+ if (!collider1) {
357
+ logger.warn(`Impl collider ${collider1Handle} not found`);
358
+ }
359
+ if (!collider2) {
360
+ logger.warn(`Collider ${collider2Handle} not found`);
361
+ }
362
+ return;
363
+ }
364
+ // Get or create collision record.
365
+ let collisionRecord = this._collisionRecords.find((record) => record.collider1 === collider1 && record.collider2 === collider2);
366
+ if (started) {
367
+ if (!collisionRecord) {
368
+ // ok: not colliding in previous steps, start collide in this frame
369
+ collisionRecord = { collider1, collider2, state: CollisionRecordState.start };
370
+ this._collisionRecords.push(collisionRecord);
371
+ }
372
+ else if (collisionRecord.state === CollisionRecordState.end) {
373
+ // also ok: the end event has emitted for these two collider in current step,
374
+ // but they collide gain right way in current step.
375
+ collisionRecord.state = CollisionRecordState.start;
376
+ }
377
+ else {
378
+ // unexpected, who's wrong?
379
+ return void warnUnexpectedCollisionEventOrder(`is already colliding, but received start gain?`, collider1, collider2);
380
+ }
381
+ }
382
+ else {
383
+ if (collisionRecord) {
384
+ if (collisionRecord.state === CollisionRecordState.end) {
385
+ // unexpected, who's wrong?
386
+ return void warnUnexpectedCollisionEventOrder(`has already end their collision in current step, but received end again?`, collider1, collider2);
387
+ }
388
+ else {
389
+ collisionRecord.state = CollisionRecordState.end;
390
+ }
391
+ }
392
+ else {
393
+ // unexpected, who's wrong?
394
+ return void warnUnexpectedCollisionEventOrder(`was not colliding in last step, but received end this step?`, collider1, collider2);
395
+ }
396
+ }
397
+ }));
398
+ // Emit events
399
+ for (const collisionRecord of this._collisionRecords) {
400
+ switch (collisionRecord.state) {
401
+ case CollisionRecordState.stay:
402
+ this._emitCollisionEvent(collisionRecord, 'onContactStay');
403
+ break;
404
+ case CollisionRecordState.start:
405
+ collisionRecord.state = CollisionRecordState.stay;
406
+ this._emitCollisionEvent(collisionRecord, 'onContactBegin');
407
+ break;
408
+ case CollisionRecordState.end:
409
+ this._emitCollisionEvent(collisionRecord, 'onContactEnd');
410
+ break;
411
+ }
412
+ }
413
+ this._collisionRecords = this._collisionRecords.filter((record) => record.state !== CollisionRecordState.end);
414
+ if (hasException) {
415
+ throw exception;
416
+ }
417
+ }
418
+ _emitCollisionEvent(collisionRecord, eventType) {
419
+ const { collider1, collider2 } = collisionRecord;
420
+ // Get contact info.
421
+ const contactInfo = {
422
+ manifold: {
423
+ points: [],
424
+ },
425
+ };
426
+ const isAnySensor = collider1.component.isSensor || collider2.component.isSensor;
427
+ if (isAnySensor) {
428
+ // todo: no need this
429
+ void this._worldImpl.intersectionPair(collider1.impl, collider2.impl);
430
+ }
431
+ else {
432
+ this._worldImpl.contactPair(collider1.impl, collider2.impl, (manifold) => {
433
+ const nContacts = manifold.numSolverContacts();
434
+ for (let iContact = 0; iContact < nContacts; iContact++) {
435
+ const contactPoint = manifold.solverContactPoint(iContact);
436
+ contactInfo.manifold.points.push(fromPx2ImplVec2(contactPoint));
437
+ }
438
+ });
439
+ }
440
+ // Emit.
441
+ const implRigidBody1 = collider1.impl.parent();
442
+ const rigidBody1 = implRigidBody1 ? this._rigidBodies.get(implRigidBody1.handle) : null;
443
+ const implRigidBody2 = collider2.impl.parent();
444
+ const rigidBody2 = implRigidBody2 ? this._rigidBodies.get(implRigidBody2.handle) : null;
445
+ collider1.component[eventType].emit(collider1.component, collider2.component, contactInfo);
446
+ if (rigidBody1) {
447
+ rigidBody1.component[eventType].emit(collider1.component, collider2.component, contactInfo);
448
+ }
449
+ collider2.component[eventType].emit(collider2.component, collider1.component, contactInfo);
450
+ if (rigidBody2) {
451
+ rigidBody2.component[eventType].emit(collider2.component, collider1.component, contactInfo);
452
+ }
453
+ }
454
+ *_intersectWithShape(shape, shapePosition, shapeRotation, filter) {
455
+ const colliders = [];
456
+ this._worldImpl.intersectionWithShape(toPx2ImplVec2(shapePosition), shapeRotation, shape, filter._filterFlags_internal, filter._filterGroups_internal, undefined, undefined, (colliderImpl) => {
457
+ const collider = this._colliders.get(colliderImpl.handle);
458
+ if (collider) {
459
+ colliders.push(collider.component);
460
+ }
461
+ else {
462
+ logger.warn(`Collider ${colliderImpl.handle} not found`);
463
+ }
464
+ return true;
465
+ });
466
+ yield* colliders;
467
+ }
468
+ _castShape(shape, transform, opts) {
469
+ const { direction, targetDistance = 1e-6, maxDistance, filter, } = opts;
470
+ const directionNormalized = direction.normalize();
471
+ let filterPredicate;
472
+ if (opts.excludeColliders) {
473
+ const excludedColliderHandles = new Set();
474
+ for (const collider of opts.excludeColliders) {
475
+ const excludedImplCollider = collider.impl_internal;
476
+ if (excludedImplCollider) {
477
+ excludedColliderHandles.add(excludedImplCollider.handle);
478
+ }
479
+ }
480
+ if (excludedColliderHandles.size > 0) {
481
+ filterPredicate = (collider) => !excludedColliderHandles.has(collider.handle);
482
+ }
483
+ }
484
+ const hit = this._worldImpl.castShape(toPx2ImplVec2(transform.position), transform.rotation ?? 0, toPx2ImplVec2(directionNormalized), shape, targetDistance, maxDistance, opts.stopAtPenetration ?? false, filter?._filterFlags_internal, filter?._filterGroups_internal, undefined, undefined, filterPredicate);
485
+ if (!hit) {
486
+ return;
487
+ }
488
+ const hitCollider = this.getColliderWithWarn_internal(hit.collider);
489
+ if (!hitCollider) {
490
+ return;
491
+ }
492
+ return new ColliderShapeCastHit(hit, transform.position, directionNormalized, hitCollider);
493
+ }
494
+ }
495
+ var CollisionRecordState;
496
+ (function (CollisionRecordState) {
497
+ CollisionRecordState[CollisionRecordState["start"] = 0] = "start";
498
+ CollisionRecordState[CollisionRecordState["stay"] = 1] = "stay";
499
+ CollisionRecordState[CollisionRecordState["end"] = 2] = "end";
500
+ })(CollisionRecordState || (CollisionRecordState = {}));
501
+ function warnUnexpectedCollisionEventOrder(message, collider1, collider2) {
502
+ logger.warn(`${collider1.component.name} <=> ${collider2.component.name} `, message);
503
+ // eslint-disable-next-line no-debugger
504
+ debugger;
505
+ }
506
+ //# sourceMappingURL=physics-world-2d.js.map
@@ -0,0 +1,6 @@
1
+ import type { Scene } from 'cc';
2
+ import type { PhysicsWorld2D } from './physics-world-2d.js';
3
+ export declare function registerPhysicsWorld(scene: Scene, world: PhysicsWorld2D): void;
4
+ export declare function unregisterPhysicsWorld(world: PhysicsWorld2D): void;
5
+ export declare function getPhysicsWorld(scene: Scene): PhysicsWorld2D | undefined;
6
+ //# sourceMappingURL=physics-world-registry.d.ts.map
@@ -0,0 +1,26 @@
1
+ import { assert } from '@cyclonium/core/utils';
2
+ /// This file serves as de-circle dependency.
3
+ const sceneToWorld = new Map();
4
+ const worldToScene = new Map();
5
+ export function registerPhysicsWorld(scene, world) {
6
+ if (sceneToWorld.has(scene)) {
7
+ throw new Error('Physics world already registered for a scene.');
8
+ }
9
+ if (worldToScene.has(world)) {
10
+ throw new Error('The scene already has a physics world registered.');
11
+ }
12
+ sceneToWorld.set(scene, world);
13
+ worldToScene.set(world, scene);
14
+ }
15
+ export function unregisterPhysicsWorld(world) {
16
+ const scene = worldToScene.get(world);
17
+ if (!scene) {
18
+ throw new Error('No physics world registered for the scene.');
19
+ }
20
+ sceneToWorld.delete(scene);
21
+ assert(worldToScene.delete(world));
22
+ }
23
+ export function getPhysicsWorld(scene) {
24
+ return sceneToWorld.get(scene);
25
+ }
26
+ //# sourceMappingURL=physics-world-registry.js.map
@@ -0,0 +1,4 @@
1
+ import * as px2Impl from '@cyclonium/rapier2d';
2
+ export { px2Impl };
3
+ export declare const initializePx2Impl: () => Promise<void>;
4
+ //# sourceMappingURL=px2-impl.d.ts.map
@@ -0,0 +1,18 @@
1
+ import * as px2Impl from '@cyclonium/rapier2d';
2
+ import { EDITOR_NOT_IN_PREVIEW } from 'cc/env';
3
+ export { px2Impl };
4
+ export const initializePx2Impl = (() => {
5
+ let promise = null;
6
+ return async () => {
7
+ if (!promise) {
8
+ promise = (async () => {
9
+ await px2Impl.__init__();
10
+ })();
11
+ }
12
+ await promise;
13
+ };
14
+ })();
15
+ if (!EDITOR_NOT_IN_PREVIEW) {
16
+ await initializePx2Impl().catch(console.error.bind(console));
17
+ }
18
+ //# sourceMappingURL=px2-impl.js.map
@@ -0,0 +1,72 @@
1
+ import { Vec2 } from '@cyclonium/core/math/vec2';
2
+ import { px2Impl } from './px2-impl.js';
3
+ import { PhysicsComponent2DBase } from './physics-component-2d-base.js';
4
+ import type { PhysicsWorld2D } from './physics-world-2d.js';
5
+ import type { Collider2D } from './collider-2d.js';
6
+ import type { Contact2DInfo } from './contact.js';
7
+ export declare enum RigidBody2DType {
8
+ fixed = "fixed",
9
+ dynamic = "dynamic",
10
+ kinematicPositionBased = "kinematicPositionBased",
11
+ kinematicVelocityBased = "kinematicVelocityBased"
12
+ }
13
+ export declare class RigidBody2D extends PhysicsComponent2DBase {
14
+ onContactBegin: import("@cyclonium/event").ManagedEventEmitter<[Collider2D, Collider2D, Contact2DInfo]>;
15
+ onContactStay: import("@cyclonium/event").ManagedEventEmitter<[Collider2D, Collider2D, Contact2DInfo]>;
16
+ onContactEnd: import("@cyclonium/event").ManagedEventEmitter<[Collider2D, Collider2D, Contact2DInfo]>;
17
+ get tags(): string[];
18
+ set tags(value: string[]);
19
+ get type(): RigidBody2DType;
20
+ set type(value: RigidBody2DType);
21
+ get collisionWithDynamic(): boolean;
22
+ set collisionWithDynamic(value: boolean);
23
+ get collisionWithFixed(): boolean;
24
+ set collisionWithFixed(value: boolean);
25
+ get collisionWithKinematic(): boolean;
26
+ set collisionWithKinematic(value: boolean);
27
+ get ccd(): boolean;
28
+ set ccd(value: boolean);
29
+ get gravityScale(): number;
30
+ set gravityScale(value: number);
31
+ get position(): Vec2;
32
+ set position(value: Vec2);
33
+ get rotation(): number;
34
+ set rotation(value: number);
35
+ get linearVelocity(): Vec2;
36
+ set linearVelocity(value: Vec2);
37
+ hasTag(tag: string): boolean;
38
+ addTag(tag: string): void;
39
+ setNextKinematicPosition(position: Vec2): void;
40
+ setNextKinematicRotation(rotation: number): void;
41
+ get impl(): px2Impl.RigidBody | undefined;
42
+ protected onDestroy(): void;
43
+ protected onAttachToWorld(world: PhysicsWorld2D): void;
44
+ protected onDetachFromWorld(_world: PhysicsWorld2D): void;
45
+ protected onEnabled(): void;
46
+ protected onDisabled(): void;
47
+ protected onStart(): void;
48
+ protected onSyncTransforms(forceTransform: boolean, _forceScale: boolean): void;
49
+ protected onAfterPhysicsStep(): void;
50
+ private _rigidBodyControlBlock;
51
+ private _tags;
52
+ private _type;
53
+ private _ccd;
54
+ private _gravityScale;
55
+ private _collisionTargetTypeFilter;
56
+ private _physicsPosition;
57
+ private _physicsRotation;
58
+ private _linearVelocity;
59
+ private _listenerFlags;
60
+ private _transformChangeFlagsObserver;
61
+ private get _transform();
62
+ private _getCollisionTargetTypeFilter;
63
+ private _setCollisionTargetTypeFilter;
64
+ private _updateActiveCollisionTypes;
65
+ private _updateListenerFlag;
66
+ private _destroyImplBody;
67
+ private _setPhysicsPosition;
68
+ private _setPhysicsRotation;
69
+ private _syncToPhysics;
70
+ private _syncFromPhysics;
71
+ }
72
+ //# sourceMappingURL=rigid-body-2d.d.ts.map