| Safe Haskell | None |
|---|---|
| Language | GHC2021 |
Box2D.Callbacks
Description
Producing FunPtr callbacks from Haskell closures, and a ready-made
multithreaded task system.
The generated bindings take callbacks as raw (see
Box2D.Tags); this module is the hand-written counterpart that turns an
ordinary Haskell function into such a FunPtr TagFunPtr via foreign import "wrapper",
and frees it again. Every mk* returns a FunPtr the caller must
freeHaskellFunPtr (use the with* brackets to get that for free).
Threads
Box2D invokes these callbacks from its solver, which runs on background
worker threads when worldDefWorkerCount > 1 — either its own scheduler, or
the TaskSystem installed here. A Haskell closure wrapped as a FunPtr is
therefore entered concurrently from several non-Haskell OS threads, so the
program must be built with the threaded runtime (-threaded) and the
closure must be thread-safe. Because the solver's task work re-enters Haskell
through these callbacks, the task dispatch is a safe call.
Synopsis
- type CustomFilter = ShapeId -> ShapeId -> Ptr () -> IO Bool
- mkCustomFilterFcn :: CustomFilter -> IO (FunPtr CustomFilterFcn)
- withCustomFilterFcn :: CustomFilter -> (FunPtr CustomFilterFcn -> IO a) -> IO a
- type Friction = Float -> Word64 -> Float -> Word64 -> IO Float
- mkFrictionCallback :: Friction -> IO (FunPtr FrictionCallback)
- withFrictionCallback :: Friction -> (FunPtr FrictionCallback -> IO a) -> IO a
- type Restitution = Float -> Word64 -> Float -> Word64 -> IO Float
- mkRestitutionCallback :: Restitution -> IO (FunPtr RestitutionCallback)
- withRestitutionCallback :: Restitution -> (FunPtr RestitutionCallback -> IO a) -> IO a
- type OverlapResult = ShapeId -> IO Bool
- withOverlapResultFcn :: OverlapResult -> (FunPtr OverlapResultFcn -> Ptr () -> IO a) -> IO a
- type CastResult = ShapeId -> Pos -> Vec2 -> Float -> IO Float
- withCastResultFcn :: CastResult -> (FunPtr CastResultFcn -> Ptr () -> IO a) -> IO a
- type PreSolve = ShapeId -> ShapeId -> Pos -> Vec2 -> IO Bool
- withPreSolveFcn :: PreSolve -> (FunPtr PreSolveFcn -> Ptr () -> IO a) -> IO a
- type PlaneResultVisitor = ShapeId -> PlaneResult -> IO Bool
- withPlaneResultFcn :: PlaneResultVisitor -> (FunPtr PlaneResultFcn -> Ptr () -> IO a) -> IO a
- type TreeQuery = CInt -> Word64 -> IO Bool
- withTreeQueryFcn :: TreeQuery -> (FunPtr TreeQueryCallbackFcn -> Ptr () -> IO a) -> IO a
- type TreeRayCast = RayCastInput -> CInt -> Word64 -> IO Float
- withTreeRayCastFcn :: TreeRayCast -> (FunPtr TreeRayCastCallbackFcn -> Ptr () -> IO a) -> IO a
- type TreeBoxCast = Ptr BoxCastInput -> CInt -> Word64 -> IO Float
- withTreeBoxCastFcn :: TreeBoxCast -> (FunPtr TreeBoxCastCallbackFcn -> Ptr () -> IO a) -> IO a
- data TaskSystem = TaskSystem {}
- withThreadPoolTaskSystem :: Int -> (TaskSystem -> IO a) -> IO a
Leaf callbacks
type CustomFilter = ShapeId -> ShapeId -> Ptr () -> IO Bool Source #
Decide whether two shapes should collide (see
setCustomFilterCallback). The Ptr is the user context.
mkCustomFilterFcn :: CustomFilter -> IO (FunPtr CustomFilterFcn) Source #
Wrap a Haskell predicate as a custom-filter callback. Free it with
freeHaskellFunPtr when the world no longer references it.
withCustomFilterFcn :: CustomFilter -> (FunPtr CustomFilterFcn -> IO a) -> IO a Source #
Run an action with a custom-filter callback that is freed on exit.
type Friction = Float -> Word64 -> Float -> Word64 -> IO Float Source #
Combine the friction of two materials (see
setFrictionCallback): frictionA userMatA frictionB userMatB.
mkFrictionCallback :: Friction -> IO (FunPtr FrictionCallback) Source #
Wrap a Haskell function as a friction-mixing callback.
withFrictionCallback :: Friction -> (FunPtr FrictionCallback -> IO a) -> IO a Source #
Run an action with a friction callback that is freed on exit.
type Restitution = Float -> Word64 -> Float -> Word64 -> IO Float Source #
Combine the restitution of two materials (see
setRestitutionCallback); same shape as Friction.
mkRestitutionCallback :: Restitution -> IO (FunPtr RestitutionCallback) Source #
Wrap a Haskell function as a restitution-mixing callback.
withRestitutionCallback :: Restitution -> (FunPtr RestitutionCallback -> IO a) -> IO a Source #
Run an action with a restitution callback that is freed on exit.
Query and cast visitors
type OverlapResult = ShapeId -> IO Bool Source #
Overlap query visitor: called for each shape found; return True to
continue the query.
withOverlapResultFcn :: OverlapResult -> (FunPtr OverlapResultFcn -> Ptr () -> IO a) -> IO a Source #
Run an action with an overlap visitor and the context to pass alongside
it (e.g. to overlapAABB); both are released on exit.
type CastResult = ShapeId -> Pos -> Vec2 -> Float -> IO Float Source #
Cast visitor: called for each shape a world ray/shape cast finds, with the hit point, normal and fraction. The returned fraction controls the query: 0 terminates, the given fraction clips the ray, 1 continues.
withCastResultFcn :: CastResult -> (FunPtr CastResultFcn -> Ptr () -> IO a) -> IO a Source #
Run an action with a cast visitor and the context to pass alongside it
(e.g. to castRay); both are released on exit.
type PreSolve = ShapeId -> ShapeId -> Pos -> Vec2 -> IO Bool Source #
Contact gate, called after narrow phase but before the solver: return
False to disable the contact. Fired from solver worker threads when the
world is multithreaded, so it must be thread-safe. Requires
shapeDefEnablePreSolveEvents on the shapes.
withPreSolveFcn :: PreSolve -> (FunPtr PreSolveFcn -> Ptr () -> IO a) -> IO a Source #
Run an action with a pre-solve gate and the context to pass alongside it
(to setPreSolveCallback). Unhook the callback from the world
before the action returns: both are released on exit.
type PlaneResultVisitor = ShapeId -> PlaneResult -> IO Bool Source #
Mover collision visitor: one collision plane per convex shape the mover
capsule touches (see collideMover); return True to keep
gathering planes.
withPlaneResultFcn :: PlaneResultVisitor -> (FunPtr PlaneResultFcn -> Ptr () -> IO a) -> IO a Source #
Run an action with a mover-plane visitor and the context to pass
alongside it (to collideMover); both are released on exit.
Dynamic-tree visitors
type TreeQuery = CInt -> Word64 -> IO Bool Source #
Tree query visitor: proxyId userData; return True to continue the
query.
withTreeQueryFcn :: TreeQuery -> (FunPtr TreeQueryCallbackFcn -> Ptr () -> IO a) -> IO a Source #
Run an action with a tree-query visitor and the context to pass alongside
it (to query); both are released on exit.
type TreeRayCast = RayCastInput -> CInt -> Word64 -> IO Float Source #
Tree ray-cast visitor: the (possibly clipped) input, proxyId and
userData. The returned fraction controls the query: 0 terminates, the
given fraction clips the ray, 1 continues.
withTreeRayCastFcn :: TreeRayCast -> (FunPtr TreeRayCastCallbackFcn -> Ptr () -> IO a) -> IO a Source #
Run an action with a tree ray-cast visitor and the context to pass
alongside it (to rayCast); both are released on exit.
type TreeBoxCast = Ptr BoxCastInput -> CInt -> Word64 -> IO Float Source #
Tree box-cast visitor. The input stays a raw Ptr (BoxCastInput has no
Storable yet: it embeds a ShapeProxy point array).
withTreeBoxCastFcn :: TreeBoxCast -> (FunPtr TreeBoxCastCallbackFcn -> Ptr () -> IO a) -> IO a Source #
Run an action with a tree box-cast visitor and the context to pass
alongside it (to boxCast); both are released on exit.
A multithreaded task system
data TaskSystem Source #
The two callbacks (ready to poke into worldDefEnqueueTask /
worldDefFinishTask) plus the worker count to set on worldDefWorkerCount.
Constructors
| TaskSystem | |
Fields | |
withThreadPoolTaskSystem :: Int -> (TaskSystem -> IO a) -> IO a Source #
Install a Haskell thread-pool task system for the duration of an action,
so the Box2D solver runs across the threaded runtime's capabilities. Set
worldDefWorkerCount, worldDefEnqueueTask and worldDefFinishTask from the
TaskSystem before creating the world.
Each enqueued task is run on a fresh forkIO thread; finishTask joins it.
The task's handle travels through the engine as a StablePtr to its join
MVar. Requires -threaded.