@vworlds/vecs-physics 1.0.26 → 1.0.28
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/adapter/{state.d.ts → engine.d.ts} +12 -5
- package/adapter/{state.js → engine.js} +19 -21
- package/adapter/engine.js.map +1 -0
- package/adapter/queries.d.ts +68 -0
- package/adapter/queries.js +145 -0
- package/adapter/queries.js.map +1 -0
- package/adapter/runtime.d.ts +4 -0
- package/adapter/runtime.js +20 -0
- package/adapter/runtime.js.map +1 -1
- package/components/body.js +1 -1
- package/components/body.js.map +1 -1
- package/components/geometry.d.ts +15 -8
- package/components/geometry.js +26 -14
- package/components/geometry.js.map +1 -1
- package/components/material.d.ts +5 -0
- package/components/material.js +5 -0
- package/components/material.js.map +1 -1
- package/index.d.ts +3 -1
- package/index.js +4 -2
- package/index.js.map +1 -1
- package/module.js +25 -22
- package/module.js.map +1 -1
- package/package.json +2 -2
- package/systems/chain_lifecycle.d.ts +6 -0
- package/systems/chain_lifecycle.js +102 -0
- package/systems/chain_lifecycle.js.map +1 -0
- package/systems/debug.d.ts +2 -2
- package/systems/debug.js +17 -17
- package/systems/debug.js.map +1 -1
- package/systems/event_opt_in_sync.d.ts +2 -2
- package/systems/event_opt_in_sync.js +64 -28
- package/systems/event_opt_in_sync.js.map +1 -1
- package/systems/events.d.ts +2 -2
- package/systems/events.js +34 -34
- package/systems/events.js.map +1 -1
- package/systems/forces.d.ts +2 -2
- package/systems/forces.js +9 -9
- package/systems/forces.js.map +1 -1
- package/systems/impulse_accumulate.d.ts +3 -3
- package/systems/impulse_accumulate.js +28 -26
- package/systems/impulse_accumulate.js.map +1 -1
- package/systems/impulse_zero.d.ts +2 -2
- package/systems/impulse_zero.js +4 -4
- package/systems/impulse_zero.js.map +1 -1
- package/systems/index.d.ts +3 -3
- package/systems/index.js +31 -28
- package/systems/index.js.map +1 -1
- package/systems/kinematic.d.ts +2 -2
- package/systems/kinematic.js +26 -25
- package/systems/kinematic.js.map +1 -1
- package/systems/lifecycle.d.ts +2 -2
- package/systems/lifecycle.js +21 -21
- package/systems/lifecycle.js.map +1 -1
- package/systems/mass_recompute.d.ts +2 -2
- package/systems/mass_recompute.js +12 -12
- package/systems/mass_recompute.js.map +1 -1
- package/systems/material_filter_sync.d.ts +2 -2
- package/systems/material_filter_sync.js +48 -34
- package/systems/material_filter_sync.js.map +1 -1
- package/systems/pose_sync_in.d.ts +2 -2
- package/systems/pose_sync_in.js +14 -11
- package/systems/pose_sync_in.js.map +1 -1
- package/systems/pose_sync_out.d.ts +2 -2
- package/systems/pose_sync_out.js +6 -6
- package/systems/pose_sync_out.js.map +1 -1
- package/systems/shape_lifecycle.d.ts +29 -4
- package/systems/shape_lifecycle.js +46 -86
- package/systems/shape_lifecycle.js.map +1 -1
- package/systems/shape_pose_sync.d.ts +2 -2
- package/systems/shape_pose_sync.js +28 -13
- package/systems/shape_pose_sync.js.map +1 -1
- package/systems/shape_predicates.d.ts +8 -3
- package/systems/shape_predicates.js +3 -2
- package/systems/shape_predicates.js.map +1 -1
- package/systems/step.d.ts +2 -2
- package/systems/step.js +5 -5
- package/systems/step.js.map +1 -1
- package/util/resolve_body.d.ts +1 -1
- package/util/resolve_body.js +1 -3
- package/util/resolve_body.js.map +1 -1
- package/adapter/state.js.map +0 -1
package/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
// Public API surface for @vworlds/vecs-physics. Only re-exports — no logic.
|
|
2
|
-
// The stable contract is documented in docs/ and architecture/
|
|
2
|
+
// The stable contract is documented in docs/ and architecture/ARCHITECTURE.md →
|
|
3
3
|
// Public API Contract.
|
|
4
4
|
// Entry point
|
|
5
5
|
export { PhysicsModule } from "./module.js";
|
|
@@ -13,11 +13,13 @@ export { ShapePosition, ShapeRotation } from "./components/shape_pose.js";
|
|
|
13
13
|
// Geometry
|
|
14
14
|
export { Shape, Box, Circle, Capsule, Segment, Polygon, Chain, } from "./components/geometry.js";
|
|
15
15
|
// Material / filter / sensor
|
|
16
|
-
export { Material, CollisionFilter, Sensor } from "./components/material.js";
|
|
16
|
+
export { Material, CollisionFilter, Sensor, Detectable } from "./components/material.js";
|
|
17
17
|
// Forces & impulses
|
|
18
18
|
export { Force, Torque, Impulse, AngularImpulse } from "./components/force.js";
|
|
19
19
|
// Kinematic targets
|
|
20
20
|
export { KinematicTargetPosition, KinematicTargetRotation } from "./components/target.js";
|
|
21
21
|
// Events
|
|
22
22
|
export { ContactEvents, SensorEvents, HitEvents, } from "./components/events.js";
|
|
23
|
+
// Queries
|
|
24
|
+
export { physics } from "./adapter/queries.js";
|
|
23
25
|
//# sourceMappingURL=index.js.map
|
package/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/index.ts"],"names":[],"mappings":"AAAA,4EAA4E;AAC5E,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/index.ts"],"names":[],"mappings":"AAAA,4EAA4E;AAC5E,gFAAgF;AAChF,uBAAuB;AAEvB,cAAc;AACd,OAAO,EAAE,aAAa,EAAuB,MAAM,aAAa,CAAC;AACjE,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAEtD,OAAO;AACP,OAAO,EACL,IAAI,EACJ,QAAQ,EACR,QAAQ,EACR,QAAQ,EACR,cAAc,EACd,eAAe,GAChB,MAAM,sBAAsB,CAAC;AAE9B,gBAAgB;AAChB,OAAO,EAAE,OAAO,EAAE,YAAY,EAAE,WAAW,EAAE,KAAK,EAAE,MAAM,6BAA6B,CAAC;AAExF,aAAa;AACb,OAAO,EAAE,aAAa,EAAE,aAAa,EAAE,MAAM,4BAA4B,CAAC;AAE1E,WAAW;AACX,OAAO,EACL,KAAK,EACL,GAAG,EACH,MAAM,EACN,OAAO,EACP,OAAO,EACP,OAAO,EACP,KAAK,GAEN,MAAM,0BAA0B,CAAC;AAElC,6BAA6B;AAC7B,OAAO,EAAE,QAAQ,EAAE,eAAe,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,0BAA0B,CAAC;AAEzF,oBAAoB;AACpB,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAE/E,oBAAoB;AACpB,OAAO,EAAE,uBAAuB,EAAE,uBAAuB,EAAE,MAAM,wBAAwB,CAAC;AAE1F,SAAS;AACT,OAAO,EACL,aAAa,EAEb,YAAY,EAEZ,SAAS,GAEV,MAAM,wBAAwB,CAAC;AAEhC,UAAU;AACV,OAAO,EAAE,OAAO,EAAE,MAAM,sBAAsB,CAAC"}
|
package/module.js
CHANGED
|
@@ -3,22 +3,22 @@
|
|
|
3
3
|
// (mutually exclusive: setting one evicts any previous geometry), ensures the
|
|
4
4
|
// three physics phases exist, creates the Box2D world, installs the physics
|
|
5
5
|
// systems (each tagged with `PhysicsSystemTag`), and attaches the private
|
|
6
|
-
// `
|
|
6
|
+
// `PhysicsEngine`.
|
|
7
7
|
//
|
|
8
8
|
// Registration order matters: Vecs assigns component type ids in registration
|
|
9
9
|
// order, so keeping the order stable keeps ids deterministic across worlds.
|
|
10
10
|
import { Implements, insertPhaseAfter, Module, ON_UPDATE, Phase, } from "@vworlds/vecs";
|
|
11
11
|
import { AngularVelocity, Body, LinearVelocity, Position, Rotation } from "./components/body.js";
|
|
12
12
|
import { Damping, GravityScale, MotionLocks, Sleep } from "./components/body_tuning.js";
|
|
13
|
-
import { Box, Capsule, Chain, Circle, Polygon, Segment, Shape } from "./components/geometry.js";
|
|
13
|
+
import { Box, Capsule, Chain, Circle, Polygon, Segment, Shape, SingleShape, } from "./components/geometry.js";
|
|
14
14
|
import { AngularImpulse, Force, Impulse, Torque } from "./components/force.js";
|
|
15
|
-
import { CollisionFilter, Material, Sensor } from "./components/material.js";
|
|
15
|
+
import { CollisionFilter, Detectable, Material, Sensor } from "./components/material.js";
|
|
16
16
|
import { ContactEvents, HitEvents, SensorEvents } from "./components/events.js";
|
|
17
17
|
import { KinematicTargetPosition, KinematicTargetRotation } from "./components/target.js";
|
|
18
18
|
import { ShapePosition, ShapeRotation } from "./components/shape_pose.js";
|
|
19
19
|
import { getBox2D } from "./adapter/runtime.js";
|
|
20
20
|
import { withAllocated } from "./adapter/disposal.js";
|
|
21
|
-
import {
|
|
21
|
+
import { attachPhysicsEngine, hasPhysicsEngine, PhysicsEngine, registerInternalComponents, } from "./adapter/engine.js";
|
|
22
22
|
import { registerImpulseHooks } from "./systems/impulse_accumulate.js";
|
|
23
23
|
import { registerPhysicsSystems } from "./systems/index.js";
|
|
24
24
|
const DEFAULT_PRE_STEP_PHASE = "physics-pre";
|
|
@@ -31,7 +31,7 @@ export class PhysicsModule extends Module {
|
|
|
31
31
|
}
|
|
32
32
|
}
|
|
33
33
|
function registerPhysics(world, opts) {
|
|
34
|
-
if (
|
|
34
|
+
if (hasPhysicsEngine(world)) {
|
|
35
35
|
throw new Error("PhysicsModule has already been registered on this world");
|
|
36
36
|
}
|
|
37
37
|
// 1. Register every public component, in a stable order (see file header).
|
|
@@ -48,6 +48,7 @@ function registerPhysics(world, opts) {
|
|
|
48
48
|
world.component(ShapePosition);
|
|
49
49
|
world.component(ShapeRotation);
|
|
50
50
|
world.component(Shape);
|
|
51
|
+
world.component(SingleShape);
|
|
51
52
|
world.component(Box);
|
|
52
53
|
world.component(Circle);
|
|
53
54
|
world.component(Capsule);
|
|
@@ -57,6 +58,7 @@ function registerPhysics(world, opts) {
|
|
|
57
58
|
world.component(Material);
|
|
58
59
|
world.component(CollisionFilter);
|
|
59
60
|
world.component(Sensor);
|
|
61
|
+
world.component(Detectable);
|
|
60
62
|
world.component(Force);
|
|
61
63
|
world.component(Torque);
|
|
62
64
|
world.component(Impulse);
|
|
@@ -66,17 +68,18 @@ function registerPhysics(world, opts) {
|
|
|
66
68
|
world.component(ContactEvents);
|
|
67
69
|
world.component(SensorEvents);
|
|
68
70
|
world.component(HitEvents);
|
|
69
|
-
// 2. Internal, non-exported components (`
|
|
71
|
+
// 2. Internal, non-exported components (`PhysicsEngine`, `PhysicsSystemTag`),
|
|
70
72
|
// registered in their documented order for deterministic type ids.
|
|
71
73
|
registerInternalComponents(world);
|
|
72
|
-
// 3. Geometry components
|
|
73
|
-
// `
|
|
74
|
-
//
|
|
75
|
-
world.component(
|
|
76
|
-
world.component(
|
|
77
|
-
world.component(
|
|
78
|
-
world.component(
|
|
79
|
-
world.component(
|
|
74
|
+
// 3. Geometry components implement `Shape` through either the internal
|
|
75
|
+
// `SingleShape` tier or Chain's direct umbrella implementation. This keeps
|
|
76
|
+
// geometry exclusivity while letting b2Shape-only systems query only singles.
|
|
77
|
+
world.component(SingleShape).set(Implements, { interfaces: [Shape] });
|
|
78
|
+
world.component(Box).set(Implements, { interfaces: [SingleShape] });
|
|
79
|
+
world.component(Circle).set(Implements, { interfaces: [SingleShape] });
|
|
80
|
+
world.component(Capsule).set(Implements, { interfaces: [SingleShape] });
|
|
81
|
+
world.component(Segment).set(Implements, { interfaces: [SingleShape] });
|
|
82
|
+
world.component(Polygon).set(Implements, { interfaces: [SingleShape] });
|
|
80
83
|
world.component(Chain).set(Implements, { interfaces: [Shape] });
|
|
81
84
|
// 4. Ensure the three physics phase entities exist and are ordered after update.
|
|
82
85
|
const preStep = resolvePhase(world, opts.preStepPhase, DEFAULT_PRE_STEP_PHASE);
|
|
@@ -86,20 +89,20 @@ function registerPhysics(world, opts) {
|
|
|
86
89
|
insertPhaseAfter(preStep, updatePhase);
|
|
87
90
|
insertPhaseAfter(step, preStep);
|
|
88
91
|
insertPhaseAfter(postStep, step);
|
|
89
|
-
// 5. Allocate WASM
|
|
92
|
+
// 5. Allocate WASM engine, create the Box2D world, register the systems (bound
|
|
90
93
|
// to it), then attach it.
|
|
91
94
|
const box2d = getBox2D();
|
|
92
95
|
const options = resolveOptions(opts);
|
|
93
|
-
const
|
|
94
|
-
|
|
95
|
-
registerImpulseHooks(world,
|
|
96
|
-
registerPhysicsSystems(world,
|
|
96
|
+
const engine = new PhysicsEngine(box2d, options, opts.debugSink);
|
|
97
|
+
engine.worldId = createWorldId(engine, options);
|
|
98
|
+
registerImpulseHooks(world, engine);
|
|
99
|
+
registerPhysicsSystems(world, engine, { preStep, step, postStep }, {
|
|
97
100
|
debug: opts.debug ?? false,
|
|
98
101
|
});
|
|
99
|
-
|
|
102
|
+
attachPhysicsEngine(world, engine);
|
|
100
103
|
}
|
|
101
|
-
function createWorldId(
|
|
102
|
-
const box2d =
|
|
104
|
+
function createWorldId(engine, options) {
|
|
105
|
+
const box2d = engine.box2d;
|
|
103
106
|
return withAllocated(box2d.b2DefaultWorldDef, (def) => {
|
|
104
107
|
def.gravity.x = options.gravityX;
|
|
105
108
|
def.gravity.y = options.gravityY;
|
package/module.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"module.js","sourceRoot":"","sources":["../../../src/module.ts"],"names":[],"mappings":"AAAA,iFAAiF;AACjF,8EAA8E;AAC9E,8EAA8E;AAC9E,4EAA4E;AAC5E,0EAA0E;AAC1E,
|
|
1
|
+
{"version":3,"file":"module.js","sourceRoot":"","sources":["../../../src/module.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@vworlds/vecs-physics",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.28",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"main": "./index.js",
|
|
6
6
|
"types": "./index.d.ts",
|
|
@@ -15,7 +15,7 @@
|
|
|
15
15
|
"url": "git+https://github.com/vworlds/vecs.git"
|
|
16
16
|
},
|
|
17
17
|
"dependencies": {
|
|
18
|
-
"@vworlds/vecs": "1.0.
|
|
18
|
+
"@vworlds/vecs": "1.0.28",
|
|
19
19
|
"box2d3-wasm": "^5.2.0"
|
|
20
20
|
},
|
|
21
21
|
"license": "MIT"
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { type Entity, type World } from "@vworlds/vecs";
|
|
2
|
+
import { Body } from "../components/body.js";
|
|
3
|
+
import { Chain } from "../components/geometry.js";
|
|
4
|
+
import { type PhysicsEngine } from "../adapter/engine.js";
|
|
5
|
+
export declare function installChainLifecycle(world: World, engine: PhysicsEngine, phase: Entity): void;
|
|
6
|
+
export declare function recreateChainForEntity(engine: PhysicsEngine, entity: Entity, parentEntity: Entity | undefined, parentBody: Body | undefined, chain: Chain | undefined): void;
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
import { ChildOf, Iter } from "@vworlds/vecs";
|
|
2
|
+
import { Body } from "../components/body.js";
|
|
3
|
+
import { Chain } from "../components/geometry.js";
|
|
4
|
+
import { PhysicsSystemTag } from "../adapter/engine.js";
|
|
5
|
+
import { withAllocated } from "../adapter/disposal.js";
|
|
6
|
+
import { chainWithBodyParent } from "./shape_predicates.js";
|
|
7
|
+
import { applyChainDef, markParentBodyMassDirty, parentBodyStillExists, readLocalPose, readShapeOptions, } from "./shape_lifecycle.js";
|
|
8
|
+
export function installChainLifecycle(world, engine, phase) {
|
|
9
|
+
const system = world.system("PhysicsChainLifecycle").with(chainWithBodyParent).phase(phase);
|
|
10
|
+
system.entity.add(PhysicsSystemTag);
|
|
11
|
+
system.enter(Iter, [Chain, { target: [ChildOf, [Body]] }], (it, [chain, body]) => {
|
|
12
|
+
createChainForEntity(engine, it.entity, it.src[1], body, chain);
|
|
13
|
+
});
|
|
14
|
+
system.exit([ChildOf, Chain], (entity, [childOf, chain]) => {
|
|
15
|
+
destroyChainForEntity(engine, entity, true, childOf?.target, chain);
|
|
16
|
+
});
|
|
17
|
+
system.update(Iter, Chain, [{ target: [ChildOf, [Body]] }], (it, chain, [body]) => {
|
|
18
|
+
recreateChainForEntity(engine, it.entity, it.src[0], body, chain);
|
|
19
|
+
});
|
|
20
|
+
const childOfSystem = world
|
|
21
|
+
.system("PhysicsChainLifecycle:ChildOf")
|
|
22
|
+
.with(ChildOf, chainWithBodyParent)
|
|
23
|
+
.phase(phase)
|
|
24
|
+
.update(Iter, ChildOf, [Chain, { target: [ChildOf, [Body]] }], (it, _childOf, [chain, body]) => {
|
|
25
|
+
recreateChainForEntity(engine, it.entity, it.src[1], body, chain);
|
|
26
|
+
});
|
|
27
|
+
childOfSystem.entity.add(PhysicsSystemTag);
|
|
28
|
+
}
|
|
29
|
+
export function recreateChainForEntity(engine, entity, parentEntity, parentBody, chain) {
|
|
30
|
+
destroyChainForEntity(engine, entity, false, parentEntity, chain);
|
|
31
|
+
createChainForEntity(engine, entity, parentEntity, parentBody, chain);
|
|
32
|
+
}
|
|
33
|
+
function createChainForEntity(engine, entity, parentEntity, parentBody, chain) {
|
|
34
|
+
const bodyId = parentBody?._bodyId;
|
|
35
|
+
if (parentEntity === undefined || bodyId === undefined || chain === undefined) {
|
|
36
|
+
return;
|
|
37
|
+
}
|
|
38
|
+
createChain(engine, entity, parentEntity, bodyId, chain);
|
|
39
|
+
}
|
|
40
|
+
function destroyChainForEntity(engine, entity, allowCascadeSkip, parent, chain) {
|
|
41
|
+
const resolvedParent = parent ?? entity.parent;
|
|
42
|
+
const resolvedChain = chain ?? entity.get(Chain);
|
|
43
|
+
const chainId = resolvedChain?._chainId;
|
|
44
|
+
if (resolvedChain !== undefined) {
|
|
45
|
+
for (const index of resolvedChain._segmentIndices) {
|
|
46
|
+
engine.entityByShapeIndex.delete(index);
|
|
47
|
+
}
|
|
48
|
+
resolvedChain._segmentIndices.length = 0;
|
|
49
|
+
}
|
|
50
|
+
if (chainId === undefined) {
|
|
51
|
+
return;
|
|
52
|
+
}
|
|
53
|
+
const parentBodyExists = parentBodyStillExists(resolvedParent);
|
|
54
|
+
if ((!allowCascadeSkip || parentBodyExists) && engine.box2d.b2Chain_IsValid(chainId)) {
|
|
55
|
+
engine.box2d.b2DestroyChain(chainId);
|
|
56
|
+
}
|
|
57
|
+
markParentBodyMassDirty(engine, resolvedParent);
|
|
58
|
+
const mutableChain = entity.get(Chain);
|
|
59
|
+
if (mutableChain !== undefined) {
|
|
60
|
+
mutableChain._chainId = undefined;
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
function createChain(engine, entity, parent, bodyId, chain) {
|
|
64
|
+
if (chain.points.length < 4) {
|
|
65
|
+
return;
|
|
66
|
+
}
|
|
67
|
+
const box2d = engine.box2d;
|
|
68
|
+
const pose = readLocalPose(entity);
|
|
69
|
+
const cos = Math.cos(pose.angle);
|
|
70
|
+
const sin = Math.sin(pose.angle);
|
|
71
|
+
const points = chain.points.map((point) => new box2d.b2Vec2(point.x * cos - point.y * sin + pose.x, point.x * sin + point.y * cos + pose.y));
|
|
72
|
+
try {
|
|
73
|
+
const chainId = withAllocated(box2d.b2DefaultChainDef, (def) => {
|
|
74
|
+
applyChainDef(def, readShapeOptions(entity));
|
|
75
|
+
def.isLoop = chain.loop;
|
|
76
|
+
def.count = points.length;
|
|
77
|
+
def.SetPoints(points);
|
|
78
|
+
return box2d.b2CreateChain(bodyId, def);
|
|
79
|
+
});
|
|
80
|
+
chain._chainId = chainId;
|
|
81
|
+
registerChainSegments(engine, entity, chain);
|
|
82
|
+
markParentBodyMassDirty(engine, parent);
|
|
83
|
+
}
|
|
84
|
+
finally {
|
|
85
|
+
for (const point of points) {
|
|
86
|
+
point.delete();
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
function registerChainSegments(engine, entity, chain) {
|
|
91
|
+
const chainId = chain._chainId;
|
|
92
|
+
if (chainId === undefined) {
|
|
93
|
+
return;
|
|
94
|
+
}
|
|
95
|
+
const count = engine.box2d.b2Chain_GetSegmentCount(chainId);
|
|
96
|
+
const segments = engine.box2d.b2Chain_GetSegments(chainId, count);
|
|
97
|
+
for (const segment of segments) {
|
|
98
|
+
engine.entityByShapeIndex.set(segment.index1, entity.eid);
|
|
99
|
+
chain._segmentIndices.push(segment.index1);
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
//# sourceMappingURL=chain_lifecycle.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"chain_lifecycle.js","sourceRoot":"","sources":["../../../../src/systems/chain_lifecycle.ts"],"names":[],"mappings":"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"}
|
package/systems/debug.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
import { type Entity, type World } from "@vworlds/vecs";
|
|
2
|
-
import { type
|
|
2
|
+
import { type PhysicsEngine } from "../adapter/engine.js";
|
|
3
3
|
/** Create `PhysicsDebugValidation` on `world` in `phase`. */
|
|
4
|
-
export declare function installDebugValidation(world: World,
|
|
4
|
+
export declare function installDebugValidation(world: World, engine: PhysicsEngine, phase: Entity): void;
|
package/systems/debug.js
CHANGED
|
@@ -33,10 +33,10 @@
|
|
|
33
33
|
// intentionally trades hot-path structure for simple whole-world checks.
|
|
34
34
|
// An entity enters the relevant filter when it carries the matching
|
|
35
35
|
// component(s), and the validator re-checks it every step.
|
|
36
|
-
// - WarnDedupe instance is owned by
|
|
36
|
+
// - WarnDedupe instance is owned by PhysicsEngine (survives across systems).
|
|
37
37
|
// - The injectable WarnSink in WarnDedupe is the test hook; pass it via
|
|
38
38
|
// PhysicsOptions.debugSink.
|
|
39
|
-
// - Does NOT modify
|
|
39
|
+
// - Does NOT modify engine internals — read-only pass.
|
|
40
40
|
//
|
|
41
41
|
// Upstream docs: docs/debug-validation.md.
|
|
42
42
|
// Polygon validity is checked via b2ComputeHull (box2d3-wasm); see isValidPolygon.
|
|
@@ -46,7 +46,7 @@ import { AngularImpulse, Force, Impulse, Torque } from "../components/force.js";
|
|
|
46
46
|
import { Chain, Polygon, Shape } from "../components/geometry.js";
|
|
47
47
|
import { Material } from "../components/material.js";
|
|
48
48
|
import { ShapePosition, ShapeRotation } from "../components/shape_pose.js";
|
|
49
|
-
import { PhysicsSystemTag } from "../adapter/
|
|
49
|
+
import { PhysicsSystemTag } from "../adapter/engine.js";
|
|
50
50
|
// ─── Issue codes ──────────────────────────────────────────────────────────────
|
|
51
51
|
const CODE_SHAPE_WITHOUT_PARENT_BODY = "shape-without-parent-body";
|
|
52
52
|
const CODE_DYNAMIC_BODY_WITHOUT_DENSITY = "dynamic-body-without-density";
|
|
@@ -57,7 +57,7 @@ const CODE_POSITION_ON_SHAPE_ENTITY = "position-on-shape-entity";
|
|
|
57
57
|
const CODE_FORCE_WITHOUT_TARGET = "force-without-target";
|
|
58
58
|
// ─── System factory ───────────────────────────────────────────────────────────
|
|
59
59
|
/** Create `PhysicsDebugValidation` on `world` in `phase`. */
|
|
60
|
-
export function installDebugValidation(world,
|
|
60
|
+
export function installDebugValidation(world, engine, phase) {
|
|
61
61
|
// ── Filters (non-reactive; walked every step) ─────────────────────────────
|
|
62
62
|
// Geometry entities: any entity with at least one geometry component.
|
|
63
63
|
const geomFilter = world.filter(Shape);
|
|
@@ -77,10 +77,10 @@ export function installDebugValidation(world, state, phase) {
|
|
|
77
77
|
.system("PhysicsDebugValidation")
|
|
78
78
|
.phase(phase)
|
|
79
79
|
.run(() => {
|
|
80
|
-
_validateGeomEntities(
|
|
81
|
-
_validateBodyEntities(geomFilter, bodyFilter,
|
|
82
|
-
_validateBodyShapePositionEntities(bodyPoseFilter, prevBodyPoseEids,
|
|
83
|
-
_validateForceEntities(forceFilter,
|
|
80
|
+
_validateGeomEntities(engine, geomFilter, engine.warn);
|
|
81
|
+
_validateBodyEntities(geomFilter, bodyFilter, engine.warn);
|
|
82
|
+
_validateBodyShapePositionEntities(bodyPoseFilter, prevBodyPoseEids, engine.warn);
|
|
83
|
+
_validateForceEntities(forceFilter, engine.warn);
|
|
84
84
|
});
|
|
85
85
|
system.entity.add(PhysicsSystemTag);
|
|
86
86
|
}
|
|
@@ -90,11 +90,11 @@ export function installDebugValidation(world, state, phase) {
|
|
|
90
90
|
* - chain-too-few-points (code 3)
|
|
91
91
|
* - polygon-invalid (code 4)
|
|
92
92
|
* - position-on-shape-entity (code 6) */
|
|
93
|
-
function _validateGeomEntities(
|
|
93
|
+
function _validateGeomEntities(engine, geomFilter, dedupe) {
|
|
94
94
|
geomFilter.forEach((e) => {
|
|
95
95
|
const eid = e.eid;
|
|
96
96
|
// ── shape-without-parent-body (code 1) ───────────────────────────────────
|
|
97
|
-
const parent = e.parent
|
|
97
|
+
const parent = e.parent;
|
|
98
98
|
const parentHasBody = parent !== undefined && parent.get(Body) !== undefined;
|
|
99
99
|
if (!parentHasBody) {
|
|
100
100
|
dedupe.warnOnce(eid, CODE_SHAPE_WITHOUT_PARENT_BODY, `Entity${eid} has geometry but its immediate parent does not have Body.`);
|
|
@@ -115,7 +115,7 @@ function _validateGeomEntities(state, geomFilter, dedupe) {
|
|
|
115
115
|
// ── polygon-invalid (code 4) ─────────────────────────────────────────────
|
|
116
116
|
const polygon = e.get(Polygon);
|
|
117
117
|
if (polygon !== undefined) {
|
|
118
|
-
const valid = isValidPolygon(
|
|
118
|
+
const valid = isValidPolygon(engine, polygon.vertices);
|
|
119
119
|
if (!valid) {
|
|
120
120
|
dedupe.warnOnce(eid, CODE_POLYGON_INVALID, `Entity${eid} has Polygon with invalid or non-convex vertices.`);
|
|
121
121
|
}
|
|
@@ -140,15 +140,15 @@ function _validateGeomEntities(state, geomFilter, dedupe) {
|
|
|
140
140
|
* A dynamic body must have at least one child shape with density > 0. Sensor
|
|
141
141
|
* shapes count — Box2D parity skips only density === 0, not isSensor shapes.
|
|
142
142
|
*
|
|
143
|
-
* To find child shapes without engine-
|
|
143
|
+
* To find child shapes without engine-internal access, we build a map of
|
|
144
144
|
* body-eid → geometry child entities by walking the geometry filter and checking
|
|
145
145
|
* which have a direct Body parent. This is a read-only ECS walk with no
|
|
146
|
-
* dependency on
|
|
146
|
+
* dependency on PhysicsEngine internals. */
|
|
147
147
|
function _validateBodyEntities(geomFilter, bodyFilter, dedupe) {
|
|
148
148
|
// Build a map: body-eid → list of geometry child entities (per this step).
|
|
149
149
|
const geomChildrenByBody = new ArrayMap();
|
|
150
150
|
geomFilter.forEach((e) => {
|
|
151
|
-
const parent = e.parent
|
|
151
|
+
const parent = e.parent;
|
|
152
152
|
if (parent === undefined || parent.get(Body) === undefined) {
|
|
153
153
|
return;
|
|
154
154
|
}
|
|
@@ -230,11 +230,11 @@ function _validateBodyShapePositionEntities(bodyPoseFilter, prevBodyPoseEids, de
|
|
|
230
230
|
* Delegates to `b2ComputeHull` (WASM); a hull with count >= 3 is valid. Allocates
|
|
231
231
|
* and frees temporary b2Vec2 objects via the WASM heap.
|
|
232
232
|
*/
|
|
233
|
-
function isValidPolygon(
|
|
233
|
+
function isValidPolygon(engine, vertices) {
|
|
234
234
|
if (vertices.length < 3) {
|
|
235
235
|
return false;
|
|
236
236
|
}
|
|
237
|
-
const box2d =
|
|
237
|
+
const box2d = engine.box2d;
|
|
238
238
|
const points = vertices.map((v) => new box2d.b2Vec2(v.x, v.y));
|
|
239
239
|
try {
|
|
240
240
|
const hull = box2d.b2ComputeHull(points);
|
|
@@ -255,7 +255,7 @@ function isValidPolygon(state, vertices) {
|
|
|
255
255
|
function _validateForceEntities(forceFilter, dedupe) {
|
|
256
256
|
forceFilter.forEach((e) => {
|
|
257
257
|
const eid = e.eid;
|
|
258
|
-
const parent = e.
|
|
258
|
+
const parent = e.target(ChildOf);
|
|
259
259
|
const hasTarget = e.get(Body) !== undefined || (parent !== undefined && parent.get(Body) !== undefined);
|
|
260
260
|
if (!hasTarget) {
|
|
261
261
|
dedupe.warnOnce(eid, CODE_FORCE_WITHOUT_TARGET, `Entity${eid} has Force/Torque/Impulse/AngularImpulse but no Body or immediate Body parent.`);
|
package/systems/debug.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"debug.js","sourceRoot":"","sources":["../../../../src/systems/debug.ts"],"names":[],"mappings":"AAAA,2EAA2E;AAC3E,qEAAqE;AACrE,2EAA2E;AAC3E,8BAA8B;AAC9B,EAAE;AACF,6EAA6E;AAC7E,8EAA8E;AAC9E,4EAA4E;AAC5E,EAAE;AACF,gDAAgD;AAChD,8EAA8E;AAC9E,6EAA6E;AAC7E,+EAA+E;AAC/E,gFAAgF;AAChF,iFAAiF;AACjF,gFAAgF;AAChF,gFAAgF;AAChF,gEAAgE;AAChE,2EAA2E;AAC3E,4EAA4E;AAC5E,sDAAsD;AACtD,2EAA2E;AAC3E,iDAAiD;AACjD,+EAA+E;AAC/E,8DAA8D;AAC9D,EAAE;AACF,+EAA+E;AAC/E,+EAA+E;AAC/E,gFAAgF;AAChF,EAAE;AACF,iBAAiB;AACjB,+EAA+E;AAC/E,6EAA6E;AAC7E,wEAAwE;AACxE,+DAA+D;AAC/D
|
|
1
|
+
{"version":3,"file":"debug.js","sourceRoot":"","sources":["../../../../src/systems/debug.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
import { type Entity, type World } from "@vworlds/vecs";
|
|
2
|
-
import { type
|
|
3
|
-
export declare function installEventOptInSync(world: World,
|
|
2
|
+
import { type PhysicsEngine } from "../adapter/engine.js";
|
|
3
|
+
export declare function installEventOptInSync(world: World, engine: PhysicsEngine, phase: Entity): void;
|
|
@@ -1,43 +1,79 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { ChildOf, Iter } from "@vworlds/vecs";
|
|
2
|
+
import { Body } from "../components/body.js";
|
|
3
|
+
import { Chain, SingleShape } from "../components/geometry.js";
|
|
2
4
|
import { ContactEvents, HitEvents, SensorEvents } from "../components/events.js";
|
|
3
|
-
import {
|
|
4
|
-
|
|
5
|
-
|
|
5
|
+
import { Detectable } from "../components/material.js";
|
|
6
|
+
import { PhysicsSystemTag } from "../adapter/engine.js";
|
|
7
|
+
import { recreateChainForEntity } from "./chain_lifecycle.js";
|
|
8
|
+
import { chainWithBodyParent } from "./shape_predicates.js";
|
|
9
|
+
export function installEventOptInSync(world, engine, phase) {
|
|
10
|
+
world.component(ContactEvents).onAdd((entity) => setEventFlag(engine, entity, "contact", true));
|
|
6
11
|
world
|
|
7
12
|
.component(ContactEvents)
|
|
8
|
-
.onRemove((entity) => setEventFlag(
|
|
9
|
-
world.component(HitEvents).onAdd((entity) => setEventFlag(
|
|
10
|
-
world.component(HitEvents).onRemove((entity) => setEventFlag(
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
13
|
+
.onRemove((entity) => setEventFlag(engine, entity, "contact", false));
|
|
14
|
+
world.component(HitEvents).onAdd((entity) => setEventFlag(engine, entity, "hit", true));
|
|
15
|
+
world.component(HitEvents).onRemove((entity) => setEventFlag(engine, entity, "hit", false));
|
|
16
|
+
// Sensor detection: enable if SensorEvents OR Detectable is present.
|
|
17
|
+
// Query only single b2Shape geometries; chains have no runtime sensor-event
|
|
18
|
+
// setter and are recreated by the chain opt-in system below.
|
|
19
|
+
const sensorSystem = world
|
|
20
|
+
.system("PhysicsEventOptInSync:Sensor")
|
|
21
|
+
.with({ all: [SingleShape, { any: [SensorEvents, Detectable] }] })
|
|
15
22
|
.phase(phase)
|
|
16
|
-
.
|
|
17
|
-
|
|
23
|
+
.enter([SingleShape], (_e, [shape]) => {
|
|
24
|
+
const shapeId = shape._shapeId;
|
|
25
|
+
if (shapeId !== undefined) {
|
|
26
|
+
engine.box2d.b2Shape_EnableSensorEvents(shapeId, true);
|
|
27
|
+
}
|
|
28
|
+
})
|
|
29
|
+
.exit([SingleShape], (_e, [shape]) => {
|
|
30
|
+
const shapeId = shape._shapeId;
|
|
31
|
+
// Stale shape-id guard. When a shape entity is destroyed, Box2D can recycle
|
|
32
|
+
// its shape-id slot to a shape created in the SAME frame. This exit's
|
|
33
|
+
// captured id keeps the old generation, but b2Shape_EnableSensorEvents does
|
|
34
|
+
// NOT validate the generation (unlike b2Shape_IsValid) -- it indexes by
|
|
35
|
+
// index1 and would clobber the live shape now occupying that slot, silently
|
|
36
|
+
// disabling sensor events on an unrelated, freshly-created shape. Match the
|
|
37
|
+
// validity guard already used in material_filter_sync.
|
|
38
|
+
if (shapeId !== undefined && engine.box2d.b2Shape_IsValid(shapeId)) {
|
|
39
|
+
engine.box2d.b2Shape_EnableSensorEvents(shapeId, false);
|
|
40
|
+
}
|
|
18
41
|
});
|
|
19
|
-
|
|
42
|
+
sensorSystem.entity.add(PhysicsSystemTag);
|
|
43
|
+
const chainSensorSystem = world
|
|
44
|
+
.system("PhysicsEventOptInSync:ChainSensor")
|
|
45
|
+
.with({ all: [Chain, { any: [SensorEvents, Detectable] }] }, chainWithBodyParent)
|
|
46
|
+
.phase(phase)
|
|
47
|
+
.enter(Iter, [Chain, { target: [ChildOf, [Body]] }], (it, [chain, body]) => {
|
|
48
|
+
recreateChainForEntity(engine, it.entity, it.src[1], body, chain);
|
|
49
|
+
})
|
|
50
|
+
.exit((entity) => {
|
|
51
|
+
const chain = entity.get(Chain);
|
|
52
|
+
const parent = entity.parent;
|
|
53
|
+
recreateChainForEntity(engine, entity, parent, parent?.get(Body), chain);
|
|
54
|
+
});
|
|
55
|
+
chainSensorSystem.entity.add(PhysicsSystemTag);
|
|
20
56
|
}
|
|
21
|
-
function setEventFlag(
|
|
22
|
-
const shape = entity.get(
|
|
23
|
-
if (shape
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
57
|
+
function setEventFlag(engine, entity, flag, enabled) {
|
|
58
|
+
const shape = entity.get(SingleShape);
|
|
59
|
+
if (shape !== undefined) {
|
|
60
|
+
const shapeId = shape._shapeId;
|
|
61
|
+
// Same stale shape-id guard as the sensor exit: never write a contact/hit
|
|
62
|
+
// flag through a destroyed/recycled shape id. Box2D contact/hit setters do
|
|
63
|
+
// not validate the id generation, so a stale id would clobber whichever live
|
|
64
|
+
// shape recycled that slot.
|
|
65
|
+
if (shapeId !== undefined && engine.box2d.b2Shape_IsValid(shapeId)) {
|
|
66
|
+
applyEventFlag(engine, shapeId, flag, enabled);
|
|
67
|
+
}
|
|
29
68
|
}
|
|
30
69
|
}
|
|
31
|
-
function applyEventFlag(
|
|
70
|
+
function applyEventFlag(engine, shapeId, flag, enabled) {
|
|
32
71
|
switch (flag) {
|
|
33
72
|
case "contact":
|
|
34
|
-
|
|
73
|
+
engine.box2d.b2Shape_EnableContactEvents(shapeId, enabled);
|
|
35
74
|
break;
|
|
36
75
|
case "hit":
|
|
37
|
-
|
|
38
|
-
break;
|
|
39
|
-
case "sensor":
|
|
40
|
-
state.box2d.b2Shape_EnableSensorEvents(shapeId, enabled);
|
|
76
|
+
engine.box2d.b2Shape_EnableHitEvents(shapeId, enabled);
|
|
41
77
|
break;
|
|
42
78
|
}
|
|
43
79
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"event_opt_in_sync.js","sourceRoot":"","sources":["../../../../src/systems/event_opt_in_sync.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"event_opt_in_sync.js","sourceRoot":"","sources":["../../../../src/systems/event_opt_in_sync.ts"],"names":[],"mappings":"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"}
|
package/systems/events.d.ts
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
import { type Entity, type World } from "@vworlds/vecs";
|
|
2
|
-
import { type
|
|
3
|
-
export declare function installEvents(world: World,
|
|
2
|
+
import { type PhysicsEngine } from "../adapter/engine.js";
|
|
3
|
+
export declare function installEvents(world: World, engine: PhysicsEngine, phase: Entity): void;
|