You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
feat!: Migrate flame_forge2d to the Box2D v3 based forge2d (#3952)
Migrates `flame_forge2d` (and everything in the monorepo that uses it)
to the new forge2d, the
native Box2D v3.1.1 bindings that shipped in forge2d 0.15.0 through
flame-engine/forge2d#115 (the
native rewrite) and flame-engine/forge2d#116 (web support through a
WebAssembly build).
`flame_forge2d` now depends on the published `forge2d: ^0.15.1`, which
includes
`initializeForge2D(lengthUnitsPerMeter:)` and `Tolerances` from
flame-engine/forge2d#120.
`flame_forge2d` stays in the
`customer_testing.dart` exclusions, because forge2d compiles Box2D from
source through the Dart
build hooks and so needs a C toolchain on the flutter/flutter presubmit
runner; the reasoning is
documented next to the exclusion.
## Core package
- `Forge2DWorld` steps the world with `physicsWorld.step(dt,
subStepCount: subStepCount)` and then
dispatches the polled contact and sensor events through the new
overridable
`ContactEventsDispatcher` (replacing `WorldContactListener`, since
listener interfaces no longer
exist). It keeps a Dart-side `bodies` set (upstream no longer exposes
one) which the gravity
setter uses to wake bodies, and exposes the new query API
(`castRayClosest`, `castRay`,
`castRayAll`, `overlapAabb`) plus forwarding setters for
`preSolveCallback` and
`customFilterCallback`.
- `ContactCallbacks` keeps its familiar `beginContact(Object other,
Contact contact)` shape through
a new lightweight flame-side `Contact` class that wraps both contact and
sensor events.
- `BodyComponent` renders from the new `Shape.geometry` read-back
(`Circle`, `Capsule`, `Segment`,
`Polygon`; chain segments arrive as `Segment`s), with
`renderShape`/`renderSegment` and a new
`renderCapsule`. `fixtureDefs` is replaced by `shapeSpecs` (a list of
`ShapeSpec`, pairing a
`ShapeGeometry` with an optional `ShapeDef`). The default `createBody()`
auto-enables
contact/sensor events on shapes whose body or shape userData is a
`ContactCallbacks`, since the
new engine only generates events for shapes that opted in.
- SDK floors raised to Dart `>=3.12.0` / Flutter `>=3.44.0` (root
workspace, melos bootstrap,
package, and `FLUTTER_MIN_VERSION` in CI).
- `Forge2DGame` awaits `initializeForge2D()` in its `onLoad`, and
`Forge2DWorld` creates its
physics world lazily so that this can happen first. Without it every
`Forge2DGame` throws on the
web, since that call is what loads the Box2D WebAssembly module. Code
that creates a world
outside of a `Forge2DGame` has to await it itself.
- Tests rewritten against real physics worlds (mocked
`Fixture`/`Contact`/`Manifold` are gone) and
all goldens regenerated. `flame`'s `MultiTapDispatcher.handleTapDown`
annotation changed from
`@internal` to `@visibleForTesting` so the tests can use it without
ignores.
## Examples and docs
- The examples stories, `padracing`, and the package example are
migrated. The examples for joints
that no longer exist in Box2D v3 (gear, pulley, rope, friction,
constant-volume) and the blob
example are removed.
- `doc/bridge_packages/flame_forge2d/forge2d.md` and `joints.md` are
rewritten for the new API
(including the new filter and wheel joints).
## Verification
- `flutter test` in `packages/flame_forge2d` (45 tests, compiles native
Box2D through build hooks),
goldens visually inspected.
- `dart analyze` clean across the whole workspace.
- `flutter build web` of the examples app confirms the Box2D wasm module
is bundled automatically
at the package asset path.
## Notes for the forge2d review (found during this migration)
- `Shape.geometry` read-back was added upstream during this work and is
what makes
`BodyComponent` rendering possible without a Dart-side geometry
registry.
- There is no upstream way to enumerate a world's bodies, hence the
Dart-side set in
`Forge2DWorld`.
- Behavior change to be aware of: destroying a body clears its userData
registries, so removed
`BodyComponent`s no longer receive a final `endContact` for contacts
that end due to the
destruction (the old engine fired those synchronously inside destroy).
0 commit comments