ffi library

just_box_2d's native API, for native platforms only (it imports dart:ffi):

  • Box2D, to check the library is there before anything else;
  • the generated bindings to the C layer (b2w_*, see src/b2w/box2d_wrapper.h), and addresses of the finalizers and of the functions Box2D checks.

Handles are int64. Every function accepts a dead one, or one of a world that has gone, and does nothing with it. Use the library from one isolate per process: its worlds belong to the whole process.

Classes

Box2D
Box2D in this process: whether its native library is in the build.

Constants

addresses → const _SymbolAddresses
B2W_BODY_DYNAMIC → const int
B2W_BODY_KINEMATIC → const int
B2W_BODY_STATIC → const int
B2W_ONEWAY_DIR_SHIFT → const int
B2W_ONEWAY_FROM_ABOVE → const int
B2W_ONEWAY_FROM_BELOW → const int
B2W_ONEWAY_FROM_LEFT → const int
B2W_ONEWAY_FROM_RIGHT → const int
B2W_SHAPE_FLAG_ONE_WAY → const int

Functions

b2w_addBoxShape(int bodyHandle, double halfW, double halfH, double density, double friction, double restitution) → void
Attach a box centred on the body's origin. halfW/halfH are half-extents.
b2w_addCapsuleShape(int bodyHandle, double cx1, double cy1, double cx2, double cy2, double radius, double density, double friction, double restitution) → void
Attach a capsule: the segment from (cx1, cy1) to (cx2, cy2) grown by radius.
b2w_addChainShape(int bodyHandle, Pointer<Float> points, int count, int loop, double friction, double restitution) → int
Attach a chain of segments. points: count points as x0, y0, x1, y1, …; loop != 0 joins the last back to the first. At least 4 points; an open chain's first and last are ghosts that only shape its ends. A chain is one-sided: it collides on the right of its direction (counter-clockwise points face out) and sensors never see it. Returns its handle, for b2w_destroyChain; 0 for too few points or a dead body.
b2w_addCircleShape(int bodyHandle, double cx, double cy, double radius, double density, double friction, double restitution) → void
Attach a circle centred at (cx, cy).
b2w_addPolygonShape(int bodyHandle, Pointer<Float> verts, int count, double density, double friction, double restitution) → void
Attach a convex polygon. verts: count points as x0, y0, x1, y1, …; Box2D takes their convex hull. More than 8 points (Box2D's limit) are cut into a fan of pieces that share the first point, so the body keeps the whole shape. Fewer than 3 attach nothing.
b2w_addRoundedPolygonShape(int bodyHandle, Pointer<Float> verts, int count, double cornerRadius, double density, double friction, double restitution) → void
Attach a convex polygon grown by cornerRadius, which rounds its corners. verts as for b2w_addPolygonShape, cut the same way past 8 points (the pieces then overlap along their seams by the rounding).
b2w_addSegmentShape(int bodyHandle, double x1, double y1, double x2, double y2, double density, double friction, double restitution) → void
Attach a line segment from (x1, y1) to (x2, y2). It has no area, so it adds no mass; use it on static bodies.
b2w_applyForce(int bodyHandle, double fx, double fy) → void
Apply a force at the body's centre of mass, for the next step.
b2w_applyLinearImpulse(int bodyHandle, double ix, double iy) → void
Apply an impulse at the body's centre of mass: its velocity changes now.
b2w_applyTorque(int bodyHandle, double torque) → void
Apply a torque, for the next step.
b2w_bulkExtractTransforms(Pointer<Int64> handles, Pointer<Float> buffer, int count) → void
Read count bodies at once, after a step. handles: count body handles. buffer: count * 7 floats, written per body as posX, posY, angle, velX, velY, isAwake (1 or 0), angularVelocity A dead handle's seven are zeros.
b2w_castRayAll(int worldHandle, double originX, double originY, double translationX, double translationY, int categoryBits, int maskBits, Pointer<Int64> outBodies, Pointer<Float> outBuffer, int maxHits) → int
Cast a ray and report up to maxHits hits, in no order, one per shape (a body of several shapes can be there more than once). outBodies: maxHits handles. outBuffer: maxHits * 5 floats, per hit pointX, pointY, normalX, normalY, fraction A shape the ray starts inside is a hit at fraction 0, at the origin, with a zero normal. Returns how many it wrote.
b2w_castRayClosest(int worldHandle, double originX, double originY, double translationX, double translationY, int categoryBits, int maskBits, Pointer<Int64> outBody, Pointer<Float> outPointX, Pointer<Float> outPointY, Pointer<Float> outNormalX, Pointer<Float> outNormalY, Pointer<Float> outFraction) → int
Cast a ray and report the closest hit: the body, the point, the surface normal there, and how far along the ray it is (0 to 1). Returns 1 on a hit, 0 on none (the out-parameters are then not written). A ray passes the shapes it starts inside; b2w_castRayAll reports those.
b2w_createBody(int worldHandle, int bodyType, double posX, double posY, double angle) → int
Create a body of bodyType (a B2W_BODY_* value) at (posX, posY), turned by angle. Returns its handle; 0 when the world has gone.
b2w_createDistanceJoint(int worldHandle, int bodyA, int bodyB, double minLen, double maxLen) → int
A rope or rod between the two bodies' origins: their distance stays within minLen, maxLen, free in between and rigid at the ends; equal lengths make a rigid rod. b2w_setDistanceSpring makes it springy.
b2w_createDynamicBody(int worldHandle, double posX, double posY, double angle) → int
Create a dynamic body at (posX, posY), turned by angle. Returns its handle; 0 when the world has gone. Same as b2w_createBody with B2W_BODY_DYNAMIC.
b2w_createPrismaticJoint(int worldHandle, int bodyA, int bodyB, double anchorX, double anchorY, double axisX, double axisY) → int
A slider: bodyB moves along the axis through the anchor, and the two do not turn against each other.
b2w_createRevoluteJoint(int worldHandle, int bodyA, int bodyB, double anchorX, double anchorY) → int
A hinge: the bodies turn freely about the anchor they share.
b2w_createStaticBody(int worldHandle, double posX, double posY, double angle) → int
Create a static body. Same as b2w_createBody with B2W_BODY_STATIC.
b2w_createWeldJoint(int worldHandle, int bodyA, int bodyB, double anchorX, double anchorY) → int
Weld the bodies together at the anchor, as they are now.
b2w_createWheelJoint(int worldHandle, int bodyA, int bodyB, double anchorX, double anchorY, double axisX, double axisY) → int
A wheel: bodyB turns freely about the anchor and moves on a spring along the axis (suspension; 4 Hz, damping ratio 0.7 until b2w_setWheelSpring).
b2w_createWorld(double gravityX, double gravityY, int numThreads) → int
Create a world with gravity (gravityX, gravityY) and a thread pool of its own for Box2D's work. numThreads <= 0 → cores - 1, at most 4. Returns its handle; 0 when every world slot is taken (Box2D has 128).
b2w_destroyBody(int bodyHandle) → void
Destroy a body with its shapes, chains and joints.
b2w_destroyChain(int chainHandle) → void
Destroy a chain made by b2w_addChainShape.
b2w_destroyJoint(int jointHandle) → void
Destroy a joint.
b2w_destroyWorld(int worldHandle) → void
Destroy a world with everything in it, then its thread pool.
b2w_finalizer_body(Pointer<Void> token) → void
Queue a body for destruction. On a 32-bit platform a pointer keeps only a body handle's low 32 bits, so this does nothing there: the body goes with its world.
b2w_finalizer_world(Pointer<Void> token) → void
Queue a world for destruction.
b2w_getBodyMoveEvent(int worldHandle, int index, Pointer<Int64> outBodyHandle, Pointer<Int32> outFellAsleep) → void
Read the index-th body that moved, and whether it fell asleep (1) or not (0).
b2w_getBodyMoveEventCount(int worldHandle) → int
How many bodies moved in the last step, including those that fell asleep at the end of it.
b2w_getBodyType(int bodyHandle) → int
The body's type; B2W_BODY_STATIC for a dead handle.
b2w_getContactBeginCount(int worldHandle) → int
How many contacts began in the last step.
b2w_getContactBeginEvent(int worldHandle, int index, Pointer<Int64> outBodyA, Pointer<Int64> outBodyB, Pointer<Float> outNormalX, Pointer<Float> outNormalY) → void
Read the index-th contact that began: the two bodies, and the contact normal, pointing from A to B (zeros if the contact has gone since).
b2w_getContactEndCount(int worldHandle) → int
How many contacts ended in the last step.
b2w_getContactEndEvent(int worldHandle, int index, Pointer<Int64> outBodyA, Pointer<Int64> outBodyB) → void
Read the index-th contact that ended.
b2w_getJointReactionForce(int jointHandle, Pointer<Float> outFx, Pointer<Float> outFy) → void
The force the joint applied in the last step, in world space.
b2w_getJointReactionTorque(int jointHandle) → double
The torque the joint applied in the last step.
b2w_getSensorBeginCount(int worldHandle) → int
How many overlaps began in the last step.
b2w_getSensorBeginEvent(int worldHandle, int index, Pointer<Int64> outSensorBody, Pointer<Int64> outVisitorBody) → void
Read the index-th overlap that began: the sensor's body and the body that entered it.
b2w_getSensorEndCount(int worldHandle) → int
How many overlaps ended in the last step.
b2w_getSensorEndEvent(int worldHandle, int index, Pointer<Int64> outSensorBody, Pointer<Int64> outVisitorBody) → void
Read the index-th overlap that ended.
b2w_moverCast(int worldHandle, double originX, double originY, Pointer<Float> points, int pointCount, double radius, double translationX, double translationY, int categoryBits, int maskBits, int ignoreBody) → double
How much of translation the mover can travel before it touches something, from 0 to 1 (1: all of it). What it touches at the start does not stop it, and a chain stops it only from the chain's front.
b2w_moverCollide(int worldHandle, double originX, double originY, Pointer<Float> points, int pointCount, double radius, int categoryBits, int maskBits, int ignoreBody, Pointer<Float> outPlanes, Pointer<Int64> outBodies, int maxPlanes) → int
The surfaces the mover touches, as Box2D collision planes. outPlanes: maxPlanes * 5 floats, per plane normalX, normalY, offset, pointX, pointY The normal points toward the mover; offset is how far the mover reaches into the surface; the point, on the surface, is relative to origin. outBodies: maxPlanes handles, the body of each plane. Returns how many planes it wrote.
b2w_queryAABB(int worldHandle, double minX, double minY, double maxX, double maxY, int categoryBits, int maskBits, Pointer<Int64> outBodies, int maxBodies) → int
Report up to maxBodies bodies, each once, with a shape whose bounding box (grown a little, as Box2D keeps it) overlaps the box: more than what truly overlaps, so test the shapes yourself when it matters. Returns how many it wrote to outBodies.
b2w_setAngularVelocity(int bodyHandle, double omega) → void
Set the body's angular velocity (radians per second).
b2w_setBodyAngularDamping(int bodyHandle, double damping) → void
Slow the body's turning the same way.
b2w_setBodyAwake(int bodyHandle, int awake) → void
Wake the body (awake != 0) or put it to sleep. A body sleeps by itself once it rests, and contacts, forces and impulses wake it.
b2w_setBodyBullet(int bodyHandle, int isBullet) → void
Turn continuous collision against other moving bodies on (isBullet != 0) or off, for a small fast body that would pass through them. Box2D already keeps every dynamic body from passing through static ones.
b2w_setBodyFilter(int bodyHandle, int categoryBits, int maskBits, int groupIndex) → void
Set the collision filter of every shape on the body (chains included), with 32-bit category and mask bits. Two shapes collide when each one's mask has a bit of the other's category, unless they share a groupIndex: then a positive group always collides and a negative one never does. b2w_setBodyFilter64 takes all 64 bits.
b2w_setBodyFilter64(int bodyHandle, int categoryBits, int maskBits, int groupIndex) → void
b2w_setBodyFilter with all 64 bits of category and mask.
b2w_setBodyFixedRotation(int bodyHandle, int fixed) → void
Lock the body's rotation (fixed != 0): nothing turns it, not torques nor contacts. Its movement stays free.
b2w_setBodyFriction(int bodyHandle, double friction) → void
Set the friction of every shape on the body (chains included), from the next step on: ice, mud.
b2w_setBodyGravityScale(int bodyHandle, double gravityScale) → void
Scale the world's gravity for this body: 1 is normal, 0 none.
b2w_setBodyLinearDamping(int bodyHandle, double damping) → void
Slow the body's movement: its velocity v becomes v / (1 + h * damping) every sub-step of length h. 0, the default, never slows it.
b2w_setBodyMass(int bodyHandle, double mass) → void
Give the body this mass instead of the one its shapes' density adds up to. The centre of mass stays where the shapes put it, and the rotational inertia scales with the mass, so the body turns as before. Call it after adding the shapes (adding one sums the mass again), and again after b2w_setBodyType.
b2w_setBodyOneWay(int bodyHandle, int enabled, int solidFromDirection) → void
Make every shape on the body a one-way platform, solid only to what comes from solidFromDirection (a B2W_ONEWAY_FROM_* value; +y down), or solid again (enabled == 0). Applies to the shapes on the body now.
b2w_setBodyRestitution(int bodyHandle, double restitution) → void
Set the restitution of every shape on the body (chains included), from the next step on: bounce pads.
b2w_setBodySensor(int bodyHandle, int isSensor) → void
Make the shapes added to the body from now on sensors (isSensor != 0) or solid (0). Call it before adding them: shapes already on the body keep what they are, as Box2D cannot change a shape between the two.
b2w_setBodySleepEnabled(int bodyHandle, int enabled) → void
Allow the body to sleep (enabled != 0, the default) or keep it awake for as long as it exists.
b2w_setBodyTargetTransform(int bodyHandle, double x, double y, double angle, double timeStep, int wake) → void
Move a kinematic body to a transform over the next timeStep, by giving it the velocity that gets it there. Bodies standing on it are carried along, which teleporting would not do. wake != 0 wakes it.
b2w_setBodyTransform(int bodyHandle, double x, double y, double angle, int wake) → void
Teleport a body. Box2D calls this fairly expensive (it moves the body's shapes in the broad phase and drops their contacts' warm start): use it for respawns, checkpoints and warps, and velocity for ordinary motion. wake != 0 wakes the body too, which moving it alone does not.
b2w_setBodyType(int bodyHandle, int bodyType) → void
Change a body's type. Expensive, and it sums the mass from the shapes again (call b2w_setBodyMass after it). The type it already has does nothing.
b2w_setDistanceLimits(int jointHandle, double minLen, double maxLen) → void
Change a distance joint's range. Its rest length becomes the middle of it.
b2w_setDistanceSpring(int jointHandle, double hertz, double dampingRatio) → void
Give a distance joint a spring that pulls toward its rest length (the middle of its range): hertz is how fast it swings, dampingRatio how soon it settles (0 never, 1 without overshoot). With an open range the ends still stop it; with equal lengths there is only the spring. hertz 0 takes the spring away.
b2w_setGravity(int worldHandle, double gx, double gy) → void
Change the world's gravity.
b2w_setImpactCallback(int worldHandle, ImpactCallbackFn callback, double speedThreshold) → void
Have b2w_step call callback for every contact whose shapes closed faster than speedThreshold (units per second) in that step, with the two bodies and that speed: Box2D's hit events. It is called on the thread that called b2w_step, after the step and before b2w_step returns; it must not call back into this library (a Dart NativeCallable.listener, which only queues the call, is the way to receive it). NULL removes the callback, and with no callback Box2D gathers no hit events.
b2w_setLinearVelocity(int bodyHandle, double vx, double vy) → void
Set the body's velocity.
b2w_setPrismaticLimits(int jointHandle, double lower, double upper, int enable) → void
Limit a prismatic joint's travel to lower, upper along its axis (enable != 0), or free it.
b2w_setPrismaticMotor(int jointHandle, double speed, double maxForce, int enable) → void
Drive a prismatic joint at speed (units per second) with up to maxForce (enable != 0), or turn the motor off.
b2w_setRevoluteLimits(int jointHandle, double lower, double upper, int enable) → void
Limit a revolute joint's angle to lower, upper radians (enable != 0) or free it.
b2w_setRevoluteMotor(int jointHandle, double speed, double maxTorque, int enable) → void
Drive a revolute joint at speed (radians per second) with up to maxTorque (enable != 0), or turn the motor off.
b2w_setWheelMotor(int jointHandle, double speed, double maxTorque, int enable) → void
Drive a wheel joint's wheel at speed (radians per second) with up to maxTorque (enable != 0), or turn the motor off.
b2w_setWheelSpring(int jointHandle, double hertz, double dampingRatio) → void
Set a wheel joint's suspension: hertz, and dampingRatio as for b2w_setDistanceSpring.
b2w_step(int worldHandle, double timeStep, int subSteps) → void
Advance the world by timeStep seconds in subSteps sub-steps (Box2D recommends 4). The events read below are this step's until the next one.
b2w_version() → int
Box2D's version, major << 16 | minor << 8 | revision (3.2.0 is 0x030200).

Typedefs

DartImpactCallbackFnFunction = void Function(int bodyA, int bodyB, double speed)
ImpactCallbackFn = Pointer<NativeFunction<ImpactCallbackFnFunction>>
What b2w_setImpactCallback calls: the two bodies, and the speed (units per second) their shapes closed at.
ImpactCallbackFnFunction = Void Function(Int64 bodyA, Int64 bodyB, Float speed)