@ignifx/physics-2d 0.2.1 → 0.3.1
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/index.d.ts +24 -157
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +21 -123
- package/dist/index.js.map +1 -1
- package/package.json +6 -6
- package/skills/physics-2d/SKILL.md +2 -2
package/dist/index.d.ts
CHANGED
|
@@ -82,20 +82,9 @@ export declare function defaultPhysics2DSettings(): Physics2DSettings;
|
|
|
82
82
|
//#endregion
|
|
83
83
|
//#region src/material.d.ts
|
|
84
84
|
/**
|
|
85
|
-
*
|
|
86
|
-
*
|
|
87
|
-
*
|
|
88
|
-
*
|
|
89
|
-
* `11-2d-toolkit.md` §8 lists a `PhysicsMaterial2D`, and `09-physics.md` §2.4 already defines
|
|
90
|
-
* `{ "format": "ignifx.physicsmaterial", "friction": …, "staticFriction": …, "restitution": … }`.
|
|
91
|
-
* Inventing a second document for the same two numbers would give artists two files to keep in
|
|
92
|
-
* step, so this package reads **the same format and the same `.physicsmaterial.json` extension**,
|
|
93
|
-
* ignoring `staticFriction` (Rapier 2D has one friction coefficient, `geometry/collider.d.ts`).
|
|
94
|
-
* `@ignifx/physics` and `@ignifx/physics-2d` never run in one world — `IGX-1101` — so the two
|
|
95
|
-
* loaders never collide.
|
|
96
|
-
*
|
|
97
|
-
* The 2D-only knobs, how two surfaces' friction and restitution are **combined**, are fields on the
|
|
98
|
-
* collider rather than on the asset, so the document stays byte-identical to the 3D one.
|
|
85
|
+
* Read the shared `.physicsmaterial.json` format, ignoring `staticFriction` because Rapier has one
|
|
86
|
+
* friction coefficient. Combine rules stay on colliders. Only one physics extension runs per world,
|
|
87
|
+
* so the 2D and 3D loaders do not compete.
|
|
99
88
|
*/
|
|
100
89
|
/**
|
|
101
90
|
* The asset type name `.physicsmaterial.json` addresses resolve to.
|
|
@@ -184,23 +173,10 @@ export declare function parsePhysicsMaterial2D(address: string, document: JsonVa
|
|
|
184
173
|
//#endregion
|
|
185
174
|
//#region src/lite/rapier/world.d.ts
|
|
186
175
|
/**
|
|
187
|
-
*
|
|
188
|
-
*
|
|
189
|
-
*
|
|
190
|
-
*
|
|
191
|
-
* ## Facts measured against `@dimforge/rapier2d-compat@0.20.0` (spike S6.2)
|
|
192
|
-
*
|
|
193
|
-
* - **The broadphase is only built by `World.step`.** Before the first step, `castRay` returns
|
|
194
|
-
* `null` and `KinematicCharacterController.computeColliderMovement` reports the full requested
|
|
195
|
-
* motion with no obstacles; a collider created after the last step is invisible until the next
|
|
196
|
-
* one. {@link primeWorld} runs a zero-length step, which builds the broadphase without
|
|
197
|
-
* integrating — but it is *not* free of side effects on a running simulation (a settled pile
|
|
198
|
-
* hashes differently), so the runtime primes only when the collider set changed.
|
|
199
|
-
* - **`InteractionGroups` is one 32-bit number**: membership in the high 16 bits, filter in the low
|
|
200
|
-
* 16 (`geometry/interaction_groups.d.ts`). Sixteen layers, not thirty-two.
|
|
201
|
-
* - **`ActiveCollisionTypes.DEFAULT` excludes non-dynamic pairs**, so a kinematic character never
|
|
202
|
-
* reports entering a static sensor. Colliders that want events are given
|
|
203
|
-
* `ActiveCollisionTypes.ALL`.
|
|
176
|
+
* Keep Rapier calls inside the adapter (ADR-0006).
|
|
177
|
+
* Queries need a built broadphase. Prime after collider-set changes only: a zero-length step can
|
|
178
|
+
* still affect a running simulation. Interaction groups support sixteen layers; event-enabled
|
|
179
|
+
* colliders include non-dynamic pairs so characters can enter static sensors.
|
|
204
180
|
*/
|
|
205
181
|
/**
|
|
206
182
|
* Rapier's physics world.
|
|
@@ -265,29 +241,9 @@ type RapierShape2D = {
|
|
|
265
241
|
//#endregion
|
|
266
242
|
//#region src/components/collider.d.ts
|
|
267
243
|
/**
|
|
268
|
-
*
|
|
269
|
-
*
|
|
270
|
-
*
|
|
271
|
-
*
|
|
272
|
-
* ## Corrections to §8
|
|
273
|
-
*
|
|
274
|
-
* - **The material is two fields, not a union.** A schema field has exactly one kind (ADR-0004), so
|
|
275
|
-
* {@link Collider2D.material} (an asset reference) and {@link Collider2D.inlineMaterial} (a
|
|
276
|
-
* record) are separate; the asset wins, the inline record is the fallback, and
|
|
277
|
-
* `physics2d.defaultMaterial` is the last resort. This is the same split `@ignifx/physics` makes.
|
|
278
|
-
* - **Combine rules are collider fields.** Rapier combines two surfaces' friction and restitution
|
|
279
|
-
* with a per-collider rule (`dynamics/coefficient_combine_rule.d.ts`); the 3D
|
|
280
|
-
* `ignifx.physicsmaterial` document has no such field, so the knob lives here rather than
|
|
281
|
-
* forking the asset format.
|
|
282
|
-
* - **A collider may stand for several Rapier colliders.** `TilemapCollider2D` produces one polygon
|
|
283
|
-
* per merged tile run, so {@link Collider2D.collectShapes} fills a list rather than returning one
|
|
284
|
-
* shape.
|
|
285
|
-
*
|
|
286
|
-
* ## Sizes and scale
|
|
287
|
-
*
|
|
288
|
-
* Sizes are authored in local metres and multiplied by the entity's lossy scale when the shapes are
|
|
289
|
-
* built. Rapier cannot rescale a built shape, so a later scale change needs
|
|
290
|
-
* {@link Collider2D.rebuild}.
|
|
244
|
+
* Build shapes from local metres multiplied by entity scale; call `rebuild` after changing scale.
|
|
245
|
+
* Material assets take precedence over inline values, then project defaults. Friction and restitution
|
|
246
|
+
* combine rules belong to each collider. A tilemap collider can produce several backend shapes.
|
|
291
247
|
*/
|
|
292
248
|
/**
|
|
293
249
|
* How two surfaces' coefficients are combined when they touch, mirroring Rapier's
|
|
@@ -390,26 +346,8 @@ export declare abstract class Collider2D extends Component implements ComponentH
|
|
|
390
346
|
//#endregion
|
|
391
347
|
//#region src/events.d.ts
|
|
392
348
|
/**
|
|
393
|
-
*
|
|
394
|
-
*
|
|
395
|
-
*
|
|
396
|
-
* ## The callbacks are the 3D names
|
|
397
|
-
*
|
|
398
|
-
* `11-2d-toolkit.md` §8 writes them as `onCollisionEnter2D`/`onTriggerEnter2D`. The kernel's
|
|
399
|
-
* `PhysicsCallbackName` union has five members and no `2D` variants
|
|
400
|
-
* (`packages/core/src/lifecycle/callbacks.ts`), and a world uses either `physics()` or
|
|
401
|
-
* `physics2d()` — never both, which is what `IGX-1101` enforces. So a 2D game implements
|
|
402
|
-
* `onCollisionEnter`, `onCollisionStay`, `onCollisionExit`, `onTriggerEnter`, and `onTriggerExit`,
|
|
403
|
-
* and receives the 2D payloads below. §8 is corrected accordingly.
|
|
404
|
-
*
|
|
405
|
-
* ## Identities are native
|
|
406
|
-
*
|
|
407
|
-
* Rapier reports **both** colliders of every event (`pipeline/event_queue.d.ts`,
|
|
408
|
-
* `drainCollisionEvents`), so `other` is never `null` for a live body and the ADR-0013 waiver that
|
|
409
|
-
* 3D physics needs has no counterpart here.
|
|
410
|
-
*
|
|
411
|
-
* Every payload is **pooled**: the same instances are reused for every event of a step, so a script
|
|
412
|
-
* that needs a value after its callback returns must copy it out (coding standards §7).
|
|
349
|
+
* 2D physics uses the same five collision and trigger callback names as 3D, without a `2D` suffix.
|
|
350
|
+
* Rapier supplies both collider identities. Payloads are pooled; copy values needed after a callback.
|
|
413
351
|
*/
|
|
414
352
|
/**
|
|
415
353
|
* One contact point of a 2D collision. Pooled with its owning {@link Collision2D}.
|
|
@@ -488,24 +426,9 @@ interface CharacterCollision2D {
|
|
|
488
426
|
//#endregion
|
|
489
427
|
//#region src/components/rigidbody.d.ts
|
|
490
428
|
/**
|
|
491
|
-
*
|
|
492
|
-
*
|
|
493
|
-
*
|
|
494
|
-
* ## Decisions §8 leaves open
|
|
495
|
-
*
|
|
496
|
-
* - **`mass` is exact, and `0` means "weigh the colliders".** Rapier derives a body's mass and
|
|
497
|
-
* angular inertia from each collider's *density* and area (`geometry/collider.d.ts`,
|
|
498
|
-
* `setDensity`), and `setAdditionalMass` adds mass without inertia. So a non-zero `mass` is
|
|
499
|
-
* applied by scaling every collider's density until the body weighs exactly that, which keeps the
|
|
500
|
-
* inertia distribution the shapes imply; `mass: 0` leaves Rapier's own density of 1 kg/m² alone.
|
|
501
|
-
* - **`freezeRotation` is one boolean, not three.** A 2D body has one rotational degree of freedom
|
|
502
|
-
* (`dynamics/rigid_body.d.ts`, `lockRotations`).
|
|
503
|
-
* - **Damping is per body here, unlike 3D.** Havok has no per-body damping; Rapier does
|
|
504
|
-
* (`setLinearDamping`, `setAngularDamping`), so `linearDamping` and `angularDamping` are real
|
|
505
|
-
* fields rather than upstream requests.
|
|
506
|
-
* - **`collisionEvents` is a three-valued enum**, exactly as in `@ignifx/physics`: a schema field
|
|
507
|
-
* has one kind (ADR-0004), and `"auto"` recomputes from `ctx.entityImplements` whenever a
|
|
508
|
-
* component joins or leaves the entity.
|
|
429
|
+
* A nonzero mass rescales collider densities while preserving their inertia distribution.
|
|
430
|
+
* Zero keeps the default density of 1 kg/m². Rotation has one freeze flag; damping is per body.
|
|
431
|
+
* Automatic collision events follow callbacks as components join or leave the entity.
|
|
509
432
|
*/
|
|
510
433
|
/**
|
|
511
434
|
* How a 2D body moves.
|
|
@@ -675,27 +598,9 @@ export declare class Rigidbody2D extends Component implements ComponentHooks {
|
|
|
675
598
|
//#endregion
|
|
676
599
|
//#region src/components/character-controller.d.ts
|
|
677
600
|
/**
|
|
678
|
-
*
|
|
679
|
-
*
|
|
680
|
-
*
|
|
681
|
-
* ## How it is driven
|
|
682
|
-
*
|
|
683
|
-
* Call {@link CharacterController2D.move} from `fixedUpdate`. The requested displacements of one
|
|
684
|
-
* step are summed and handed to Rapier's `computeColliderMovement` by the step system, so two
|
|
685
|
-
* scripts moving the same character compose instead of fighting. Gravity is **not** applied by this
|
|
686
|
-
* component: a bare controller is purely kinematic, exactly as the 3D one is, and the toolkit
|
|
687
|
-
* controller scripts integrate gravity themselves.
|
|
688
|
-
*
|
|
689
|
-
* After the step the controller owns the entity's world X and Y. Z and `rotation2D` stay
|
|
690
|
-
* user-controlled.
|
|
691
|
-
*
|
|
692
|
-
* ## The one addition to §8: `shape`
|
|
693
|
-
*
|
|
694
|
-
* §8 describes the controller as a capsule. Measured against `@dimforge/rapier2d-compat@0.20.0`
|
|
695
|
-
* (spike S6.2), Rapier's autostep clears a 0.3 m step with a **box** character and refuses anything
|
|
696
|
-
* above about 0.15 m with a capsule of radius 0.2 — so `stepOffset` is only usable with a box.
|
|
697
|
-
* {@link CharacterController2D.shape} therefore chooses between the two, defaulting to `"capsule"`
|
|
698
|
-
* as §8 says, and the limitation is documented in the skill and in ADR-0006's validation section.
|
|
601
|
+
* Sum `move` displacements during `fixedUpdate`; game scripts supply gravity.
|
|
602
|
+
* After the step the controller owns world X/Y, while Z and rotation remain user-controlled.
|
|
603
|
+
* Box shapes support taller autosteps than capsules; see ADR-0006's validation results.
|
|
699
604
|
*/
|
|
700
605
|
/**
|
|
701
606
|
* The collision shape a 2D character controller uses.
|
|
@@ -974,25 +879,9 @@ export declare class EdgeCollider2D extends Collider2D {
|
|
|
974
879
|
//#endregion
|
|
975
880
|
//#region src/components/tilemap-collider.d.ts
|
|
976
881
|
/**
|
|
977
|
-
*
|
|
978
|
-
*
|
|
979
|
-
*
|
|
980
|
-
* ## How it reaches the data
|
|
981
|
-
*
|
|
982
|
-
* `@ignifx/2d` is an **optional** peer of `@ignifx/physics-2d` (a physics-only 2D game needs no
|
|
983
|
-
* sprite toolkit), so this component never imports the toolkit as a value — only the
|
|
984
|
-
* `TilemapCollisionData` type. A game, or `@ignifx/2d`'s own tilemap loader, assigns
|
|
985
|
-
* {@link TilemapCollider2D.collisionData}; the runtime compares the data's `version` at the start of
|
|
986
|
-
* every fixed step and rebuilds the shapes when it changes, which is the same moment
|
|
987
|
-
* `Tilemap.onCollisionChanged` fires and needs no signal subscription across the package boundary.
|
|
988
|
-
*
|
|
989
|
-
* ## Why closed polylines rather than polygons
|
|
990
|
-
*
|
|
991
|
-
* A merged run of solid tiles is not convex in general — an L of tiles merges into an L — and
|
|
992
|
-
* Rapier's polygon shape is a **convex hull** (`geometry/shape.d.ts`, `ConvexPolygon`), which would
|
|
993
|
-
* silently fill the notch. A closed `polyline` reproduces the outline exactly and is the shape
|
|
994
|
-
* static level geometry wants; the trade-off is that a polyline is infinitely thin, so a body that
|
|
995
|
-
* starts inside the tilemap is not pushed out.
|
|
882
|
+
* Read tile collision data through the optional 2D toolkit's type and rebuild when its version changes.
|
|
883
|
+
* Closed polylines preserve concave tile outlines that convex hulls would fill in. They are thin
|
|
884
|
+
* surfaces, so a body starting inside the map is not pushed out.
|
|
996
885
|
*/
|
|
997
886
|
/**
|
|
998
887
|
* The collision surface of a tilemap, as one static body's worth of Rapier shapes.
|
|
@@ -1600,31 +1489,9 @@ export declare class Physics2DService {
|
|
|
1600
1489
|
//#endregion
|
|
1601
1490
|
//#region src/extension.d.ts
|
|
1602
1491
|
/**
|
|
1603
|
-
* The
|
|
1604
|
-
* `
|
|
1605
|
-
*
|
|
1606
|
-
* ## Why `@ignifx/2d` is optional rather than required
|
|
1607
|
-
*
|
|
1608
|
-
* `00-overview.md` §2 draws `@ignifx/physics-2d` above `@ignifx/2d`, and the layering rule allows
|
|
1609
|
-
* the dependency. At runtime the only thing this package needs from the toolkit is the
|
|
1610
|
-
* `TilemapCollisionData` **type**, which is erased at build time, so a platformer that draws its own
|
|
1611
|
-
* graphics can register `physics2d()` on its own. The manifest therefore declares
|
|
1612
|
-
* `requires: []` and `optional: ["@ignifx/2d"]`, and `package.json` makes `@ignifx/2d` an optional
|
|
1613
|
-
* peer dependency.
|
|
1614
|
-
*
|
|
1615
|
-
* ## Why the world is built in `onStart`
|
|
1616
|
-
*
|
|
1617
|
-
* `register` runs before `createApp` builds the `World` (`packages/core/src/app/app.ts`,
|
|
1618
|
-
* `initialize`), and the Rapier world needs the world's layer table; Rapier's WebAssembly module
|
|
1619
|
-
* also has to be instantiated, which is asynchronous. So `register` declares everything against a
|
|
1620
|
-
* {@link Physics2DHost} holder and `onStart` fills the holder in.
|
|
1621
|
-
*
|
|
1622
|
-
* ## One physics extension per world
|
|
1623
|
-
*
|
|
1624
|
-
* `11-2d-toolkit.md` §8: "A world uses either `physics()` or `physics2d()`; registering both throws
|
|
1625
|
-
* `IGX-1101`". `@ignifx/physics` publishes its Havok simulation scene through
|
|
1626
|
-
* `ExtensionContext.setSimulationScene`, so `app.world.lite.simulationScene !== null` at `onStart`
|
|
1627
|
-
* is the test — and it needs no dependency on `@ignifx/physics`, which this package must not have.
|
|
1492
|
+
* The 2D toolkit is optional; physics only needs its tile-collision data type.
|
|
1493
|
+
* Create the Rapier world in `onStart`, once the world's layer table exists and WASM is ready.
|
|
1494
|
+
* Reject a world already using 3D physics with `IGX-1101`.
|
|
1628
1495
|
*/
|
|
1629
1496
|
/**
|
|
1630
1497
|
* What `physics2d()` accepts.
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","names":[],"sources":["../src/settings.ts","../src/material.ts","../src/lite/rapier/world.ts","../src/components/collider.ts","../src/events.ts","../src/components/rigidbody.ts","../src/components/character-controller.ts","../src/components/colliders.ts","../src/components/tilemap-collider.ts","../src/errors.ts","../src/queries.ts","../src/runtime/body-record.ts","../src/runtime/runtime.ts","../src/runtime/host.ts","../src/service.ts","../src/extension.ts","../src/schemas.ts"],"mappings":";;;;;;;;;;;;;;;;;qBAiBa;;;;;;UAOI;;WAEN;;WAEA;;;;;;;;;;;;;;;;;;;UAoBM;;WAEN,SAAS;;;;;WAKT,iBAAiB,SAAS;;WAE1B,iBAAiB;;WAEjB;;WAEA;;;;;;;;;;;;;wBAuBK,2BAA2B;;;;;;;;wBAoB3B,4BAA4B
|
|
1
|
+
{"version":3,"file":"index.d.ts","names":[],"sources":["../src/settings.ts","../src/material.ts","../src/lite/rapier/world.ts","../src/components/collider.ts","../src/events.ts","../src/components/rigidbody.ts","../src/components/character-controller.ts","../src/components/colliders.ts","../src/components/tilemap-collider.ts","../src/errors.ts","../src/queries.ts","../src/runtime/body-record.ts","../src/runtime/runtime.ts","../src/runtime/host.ts","../src/service.ts","../src/extension.ts","../src/schemas.ts"],"mappings":"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"}
|
package/dist/index.js
CHANGED
|
@@ -16,24 +16,9 @@ const Physics2DHostKey = createServiceKey("@ignifx/physics-2d:host");
|
|
|
16
16
|
//#endregion
|
|
17
17
|
//#region src/components/rigidbody.ts
|
|
18
18
|
/**
|
|
19
|
-
*
|
|
20
|
-
*
|
|
21
|
-
*
|
|
22
|
-
* ## Decisions §8 leaves open
|
|
23
|
-
*
|
|
24
|
-
* - **`mass` is exact, and `0` means "weigh the colliders".** Rapier derives a body's mass and
|
|
25
|
-
* angular inertia from each collider's *density* and area (`geometry/collider.d.ts`,
|
|
26
|
-
* `setDensity`), and `setAdditionalMass` adds mass without inertia. So a non-zero `mass` is
|
|
27
|
-
* applied by scaling every collider's density until the body weighs exactly that, which keeps the
|
|
28
|
-
* inertia distribution the shapes imply; `mass: 0` leaves Rapier's own density of 1 kg/m² alone.
|
|
29
|
-
* - **`freezeRotation` is one boolean, not three.** A 2D body has one rotational degree of freedom
|
|
30
|
-
* (`dynamics/rigid_body.d.ts`, `lockRotations`).
|
|
31
|
-
* - **Damping is per body here, unlike 3D.** Havok has no per-body damping; Rapier does
|
|
32
|
-
* (`setLinearDamping`, `setAngularDamping`), so `linearDamping` and `angularDamping` are real
|
|
33
|
-
* fields rather than upstream requests.
|
|
34
|
-
* - **`collisionEvents` is a three-valued enum**, exactly as in `@ignifx/physics`: a schema field
|
|
35
|
-
* has one kind (ADR-0004), and `"auto"` recomputes from `ctx.entityImplements` whenever a
|
|
36
|
-
* component joins or leaves the entity.
|
|
19
|
+
* A nonzero mass rescales collider densities while preserving their inertia distribution.
|
|
20
|
+
* Zero keeps the default density of 1 kg/m². Rotation has one freeze flag; damping is per body.
|
|
21
|
+
* Automatic collision events follow callbacks as components join or leave the entity.
|
|
37
22
|
*/
|
|
38
23
|
/**
|
|
39
24
|
* How a 2D body moves.
|
|
@@ -233,27 +218,9 @@ function rigidbody2DSchema() {
|
|
|
233
218
|
//#endregion
|
|
234
219
|
//#region src/components/character-controller.ts
|
|
235
220
|
/**
|
|
236
|
-
*
|
|
237
|
-
*
|
|
238
|
-
*
|
|
239
|
-
* ## How it is driven
|
|
240
|
-
*
|
|
241
|
-
* Call {@link CharacterController2D.move} from `fixedUpdate`. The requested displacements of one
|
|
242
|
-
* step are summed and handed to Rapier's `computeColliderMovement` by the step system, so two
|
|
243
|
-
* scripts moving the same character compose instead of fighting. Gravity is **not** applied by this
|
|
244
|
-
* component: a bare controller is purely kinematic, exactly as the 3D one is, and the toolkit
|
|
245
|
-
* controller scripts integrate gravity themselves.
|
|
246
|
-
*
|
|
247
|
-
* After the step the controller owns the entity's world X and Y. Z and `rotation2D` stay
|
|
248
|
-
* user-controlled.
|
|
249
|
-
*
|
|
250
|
-
* ## The one addition to §8: `shape`
|
|
251
|
-
*
|
|
252
|
-
* §8 describes the controller as a capsule. Measured against `@dimforge/rapier2d-compat@0.20.0`
|
|
253
|
-
* (spike S6.2), Rapier's autostep clears a 0.3 m step with a **box** character and refuses anything
|
|
254
|
-
* above about 0.15 m with a capsule of radius 0.2 — so `stepOffset` is only usable with a box.
|
|
255
|
-
* {@link CharacterController2D.shape} therefore chooses between the two, defaulting to `"capsule"`
|
|
256
|
-
* as §8 says, and the limitation is documented in the skill and in ADR-0006's validation section.
|
|
221
|
+
* Sum `move` displacements during `fixedUpdate`; game scripts supply gravity.
|
|
222
|
+
* After the step the controller owns world X/Y, while Z and rotation remain user-controlled.
|
|
223
|
+
* Box shapes support taller autosteps than capsules; see ADR-0006's validation results.
|
|
257
224
|
*/
|
|
258
225
|
/**
|
|
259
226
|
* The collision shape a 2D character controller uses.
|
|
@@ -525,20 +492,9 @@ function physics2DError(code, message, options) {
|
|
|
525
492
|
//#endregion
|
|
526
493
|
//#region src/material.ts
|
|
527
494
|
/**
|
|
528
|
-
*
|
|
529
|
-
*
|
|
530
|
-
*
|
|
531
|
-
*
|
|
532
|
-
* `11-2d-toolkit.md` §8 lists a `PhysicsMaterial2D`, and `09-physics.md` §2.4 already defines
|
|
533
|
-
* `{ "format": "ignifx.physicsmaterial", "friction": …, "staticFriction": …, "restitution": … }`.
|
|
534
|
-
* Inventing a second document for the same two numbers would give artists two files to keep in
|
|
535
|
-
* step, so this package reads **the same format and the same `.physicsmaterial.json` extension**,
|
|
536
|
-
* ignoring `staticFriction` (Rapier 2D has one friction coefficient, `geometry/collider.d.ts`).
|
|
537
|
-
* `@ignifx/physics` and `@ignifx/physics-2d` never run in one world — `IGX-1101` — so the two
|
|
538
|
-
* loaders never collide.
|
|
539
|
-
*
|
|
540
|
-
* The 2D-only knobs, how two surfaces' friction and restitution are **combined**, are fields on the
|
|
541
|
-
* collider rather than on the asset, so the document stays byte-identical to the 3D one.
|
|
495
|
+
* Read the shared `.physicsmaterial.json` format, ignoring `staticFriction` because Rapier has one
|
|
496
|
+
* friction coefficient. Combine rules stay on colliders. Only one physics extension runs per world,
|
|
497
|
+
* so the 2D and 3D loaders do not compete.
|
|
542
498
|
*/
|
|
543
499
|
/**
|
|
544
500
|
* The asset type name `.physicsmaterial.json` addresses resolve to.
|
|
@@ -685,29 +641,9 @@ function numberAt(object, key, fallback) {
|
|
|
685
641
|
//#endregion
|
|
686
642
|
//#region src/components/collider.ts
|
|
687
643
|
/**
|
|
688
|
-
*
|
|
689
|
-
*
|
|
690
|
-
*
|
|
691
|
-
*
|
|
692
|
-
* ## Corrections to §8
|
|
693
|
-
*
|
|
694
|
-
* - **The material is two fields, not a union.** A schema field has exactly one kind (ADR-0004), so
|
|
695
|
-
* {@link Collider2D.material} (an asset reference) and {@link Collider2D.inlineMaterial} (a
|
|
696
|
-
* record) are separate; the asset wins, the inline record is the fallback, and
|
|
697
|
-
* `physics2d.defaultMaterial` is the last resort. This is the same split `@ignifx/physics` makes.
|
|
698
|
-
* - **Combine rules are collider fields.** Rapier combines two surfaces' friction and restitution
|
|
699
|
-
* with a per-collider rule (`dynamics/coefficient_combine_rule.d.ts`); the 3D
|
|
700
|
-
* `ignifx.physicsmaterial` document has no such field, so the knob lives here rather than
|
|
701
|
-
* forking the asset format.
|
|
702
|
-
* - **A collider may stand for several Rapier colliders.** `TilemapCollider2D` produces one polygon
|
|
703
|
-
* per merged tile run, so {@link Collider2D.collectShapes} fills a list rather than returning one
|
|
704
|
-
* shape.
|
|
705
|
-
*
|
|
706
|
-
* ## Sizes and scale
|
|
707
|
-
*
|
|
708
|
-
* Sizes are authored in local metres and multiplied by the entity's lossy scale when the shapes are
|
|
709
|
-
* built. Rapier cannot rescale a built shape, so a later scale change needs
|
|
710
|
-
* {@link Collider2D.rebuild}.
|
|
644
|
+
* Build shapes from local metres multiplied by entity scale; call `rebuild` after changing scale.
|
|
645
|
+
* Material assets take precedence over inline values, then project defaults. Friction and restitution
|
|
646
|
+
* combine rules belong to each collider. A tilemap collider can produce several backend shapes.
|
|
711
647
|
*/
|
|
712
648
|
/**
|
|
713
649
|
* How two surfaces' coefficients are combined when they touch, mirroring Rapier's
|
|
@@ -793,19 +729,9 @@ var Collider2D = class extends Component {
|
|
|
793
729
|
//#endregion
|
|
794
730
|
//#region src/components/colliders.ts
|
|
795
731
|
/**
|
|
796
|
-
*
|
|
797
|
-
*
|
|
798
|
-
*
|
|
799
|
-
* ## The two point-list colliders
|
|
800
|
-
*
|
|
801
|
-
* - `PolygonCollider2D` builds a **convex** shape (`ColliderDesc.convexHull`). Rapier 2D also ships
|
|
802
|
-
* `convexDecomposition`, which needs a triangle mesh with an index buffer and runs V-HACD — far
|
|
803
|
-
* too heavy for a component field. Concave outlines are expressed as several
|
|
804
|
-
* `PolygonCollider2D`s on one entity, which is what a compound body is for, or as an
|
|
805
|
-
* `EdgeCollider2D` when the outline is open.
|
|
806
|
-
* - `EdgeCollider2D` builds a `polyline`, the open chain a platformer's ground contour wants. A
|
|
807
|
-
* polyline is infinitely thin: a fast body can tunnel through it, and a character controller that
|
|
808
|
-
* starts *inside* one is not pushed out. Static level geometry is what it is for.
|
|
732
|
+
* Polygon colliders use convex hulls; represent concave geometry with multiple colliders.
|
|
733
|
+
* Edge colliders are thin, open polylines for static contours: fast bodies can tunnel through them,
|
|
734
|
+
* and bodies starting inside are not pushed out.
|
|
809
735
|
*/
|
|
810
736
|
/** A quarter turn in radians, which is how a horizontal capsule is expressed. */
|
|
811
737
|
const QUARTER_TURN = Math.PI / 2;
|
|
@@ -1128,25 +1054,9 @@ function degenerate(entity, component, requirement) {
|
|
|
1128
1054
|
//#endregion
|
|
1129
1055
|
//#region src/components/tilemap-collider.ts
|
|
1130
1056
|
/**
|
|
1131
|
-
*
|
|
1132
|
-
*
|
|
1133
|
-
*
|
|
1134
|
-
* ## How it reaches the data
|
|
1135
|
-
*
|
|
1136
|
-
* `@ignifx/2d` is an **optional** peer of `@ignifx/physics-2d` (a physics-only 2D game needs no
|
|
1137
|
-
* sprite toolkit), so this component never imports the toolkit as a value — only the
|
|
1138
|
-
* `TilemapCollisionData` type. A game, or `@ignifx/2d`'s own tilemap loader, assigns
|
|
1139
|
-
* {@link TilemapCollider2D.collisionData}; the runtime compares the data's `version` at the start of
|
|
1140
|
-
* every fixed step and rebuilds the shapes when it changes, which is the same moment
|
|
1141
|
-
* `Tilemap.onCollisionChanged` fires and needs no signal subscription across the package boundary.
|
|
1142
|
-
*
|
|
1143
|
-
* ## Why closed polylines rather than polygons
|
|
1144
|
-
*
|
|
1145
|
-
* A merged run of solid tiles is not convex in general — an L of tiles merges into an L — and
|
|
1146
|
-
* Rapier's polygon shape is a **convex hull** (`geometry/shape.d.ts`, `ConvexPolygon`), which would
|
|
1147
|
-
* silently fill the notch. A closed `polyline` reproduces the outline exactly and is the shape
|
|
1148
|
-
* static level geometry wants; the trade-off is that a polyline is infinitely thin, so a body that
|
|
1149
|
-
* starts inside the tilemap is not pushed out.
|
|
1057
|
+
* Read tile collision data through the optional 2D toolkit's type and rebuild when its version changes.
|
|
1058
|
+
* Closed polylines preserve concave tile outlines that convex hulls would fill in. They are thin
|
|
1059
|
+
* surfaces, so a body starting inside the map is not pushed out.
|
|
1150
1060
|
*/
|
|
1151
1061
|
/**
|
|
1152
1062
|
* The collision surface of a tilemap, as one static body's worth of Rapier shapes.
|
|
@@ -1290,21 +1200,9 @@ function segment(from, to, scale) {
|
|
|
1290
1200
|
//#endregion
|
|
1291
1201
|
//#region src/lite/rapier/module.ts
|
|
1292
1202
|
/**
|
|
1293
|
-
*
|
|
1294
|
-
*
|
|
1295
|
-
*
|
|
1296
|
-
* `src/lite/**` — hence `src/lite/rapier/`.
|
|
1297
|
-
*
|
|
1298
|
-
* ## Why `-compat`
|
|
1299
|
-
*
|
|
1300
|
-
* The `-compat` build inlines the WebAssembly module as base64 inside `rapier.mjs`, so it needs no
|
|
1301
|
-
* asset serving and works unchanged in Node and in the browser (spike S6.2, ADR-0006 Validation).
|
|
1302
|
-
* `init()` is what decodes and instantiates it; every other Rapier call before that throws.
|
|
1303
|
-
*
|
|
1304
|
-
* The import is static: `world.ts` and `service.ts` also import Rapier's classes statically, so a
|
|
1305
|
-
* dynamic import here alone would not move the 2 MB module out of an app's entry chunk (measured in
|
|
1306
|
-
* Phase 6). Splitting it needs the adapter to read every class off the loaded module instead, which
|
|
1307
|
-
* is the Phase 12 bundle work.
|
|
1203
|
+
* Initialise Rapier's embedded WebAssembly before making backend calls.
|
|
1204
|
+
* The compat build includes the binary, so both Node and browser apps need no separate asset.
|
|
1205
|
+
* Rapier classes are imported statically by the adapters; delaying `init` does not split that bundle.
|
|
1308
1206
|
*
|
|
1309
1207
|
* @internal
|
|
1310
1208
|
*/
|