-- Produced by boxnd-gen; edit the generator, not this file.

module Box3D.RecPlayer
  ( create
  , destroy
  , stepFrame
  , restart
  , seekFrame
  , getWorldId
  , getFrame
  , getFrameCount
  , isAtEnd
  , hasDiverged
  , getInfo
  , getDivergeFrame
  , setWorkerCount
  , setKeyframePolicy
  , getKeyframeBudget
  , getKeyframeMinInterval
  , getKeyframeInterval
  , getKeyframeBytes
  , getBodyCount
  , getBodyId
  , setDebugShapeCallbacks
  , drawFrameQueries
  , getFrameQueryCount
  , getFrameQuery
  , getFrameQueryHit
  )

  where

import Foreign
import Foreign.C.Types (CInt(..), CBool(..), CSize(..))
import Box3D.Id (BodyId(..), WorldId(..))
import Box3D.Tags (CreateDebugShapeCallback, DebugDraw, DestroyDebugShapeCallback, RecPlayer, RecPlayerInfo, RecQueryHit, RecQueryInfo)

foreign import ccall unsafe "b3RecPlayer_Create"
  c_b3RecPlayer_Create :: Ptr () -> CInt -> CInt -> IO (Ptr RecPlayer)

foreign import ccall unsafe "b3RecPlayer_Destroy"
  c_b3RecPlayer_Destroy :: Ptr RecPlayer -> IO ()

foreign import ccall safe "b3RecPlayer_StepFrame"
  c_b3RecPlayer_StepFrame :: Ptr RecPlayer -> IO CBool

foreign import ccall unsafe "b3RecPlayer_Restart"
  c_b3RecPlayer_Restart :: Ptr RecPlayer -> IO ()

foreign import ccall unsafe "b3RecPlayer_SeekFrame"
  c_b3RecPlayer_SeekFrame :: Ptr RecPlayer -> CInt -> IO ()

foreign import ccall unsafe "b3RecPlayer_GetWorldId"
  c_b3RecPlayer_GetWorldId :: Ptr RecPlayer -> IO WorldId

foreign import ccall unsafe "b3RecPlayer_GetFrame"
  c_b3RecPlayer_GetFrame :: Ptr RecPlayer -> IO CInt

foreign import ccall unsafe "b3RecPlayer_GetFrameCount"
  c_b3RecPlayer_GetFrameCount :: Ptr RecPlayer -> IO CInt

foreign import ccall unsafe "b3RecPlayer_IsAtEnd"
  c_b3RecPlayer_IsAtEnd :: Ptr RecPlayer -> IO CBool

foreign import ccall unsafe "b3RecPlayer_HasDiverged"
  c_b3RecPlayer_HasDiverged :: Ptr RecPlayer -> IO CBool

foreign import ccall unsafe "hsg_b3RecPlayer_GetInfo"
  c_b3RecPlayer_GetInfo :: Ptr RecPlayer -> Ptr RecPlayerInfo -> IO ()

foreign import ccall unsafe "b3RecPlayer_GetDivergeFrame"
  c_b3RecPlayer_GetDivergeFrame :: Ptr RecPlayer -> IO CInt

foreign import ccall unsafe "b3RecPlayer_SetWorkerCount"
  c_b3RecPlayer_SetWorkerCount :: Ptr RecPlayer -> CInt -> IO ()

foreign import ccall unsafe "b3RecPlayer_SetKeyframePolicy"
  c_b3RecPlayer_SetKeyframePolicy :: Ptr RecPlayer -> CSize -> CInt -> IO ()

foreign import ccall unsafe "b3RecPlayer_GetKeyframeBudget"
  c_b3RecPlayer_GetKeyframeBudget :: Ptr RecPlayer -> IO CSize

foreign import ccall unsafe "b3RecPlayer_GetKeyframeMinInterval"
  c_b3RecPlayer_GetKeyframeMinInterval :: Ptr RecPlayer -> IO CInt

foreign import ccall unsafe "b3RecPlayer_GetKeyframeInterval"
  c_b3RecPlayer_GetKeyframeInterval :: Ptr RecPlayer -> IO CInt

foreign import ccall unsafe "b3RecPlayer_GetKeyframeBytes"
  c_b3RecPlayer_GetKeyframeBytes :: Ptr RecPlayer -> IO CSize

foreign import ccall unsafe "b3RecPlayer_GetBodyCount"
  c_b3RecPlayer_GetBodyCount :: Ptr RecPlayer -> IO CInt

foreign import ccall unsafe "b3RecPlayer_GetBodyId"
  c_b3RecPlayer_GetBodyId :: Ptr RecPlayer -> CInt -> IO BodyId

foreign import ccall safe "b3RecPlayer_SetDebugShapeCallbacks"
  c_b3RecPlayer_SetDebugShapeCallbacks :: Ptr RecPlayer -> FunPtr CreateDebugShapeCallback -> FunPtr DestroyDebugShapeCallback -> Ptr () -> IO ()

foreign import ccall unsafe "b3RecPlayer_DrawFrameQueries"
  c_b3RecPlayer_DrawFrameQueries :: Ptr RecPlayer -> Ptr DebugDraw -> CInt -> CInt -> IO ()

foreign import ccall unsafe "b3RecPlayer_GetFrameQueryCount"
  c_b3RecPlayer_GetFrameQueryCount :: Ptr RecPlayer -> IO CInt

foreign import ccall unsafe "hsg_b3RecPlayer_GetFrameQuery"
  c_b3RecPlayer_GetFrameQuery :: Ptr RecPlayer -> CInt -> Ptr RecQueryInfo -> IO ()

foreign import ccall unsafe "hsg_b3RecPlayer_GetFrameQueryHit"
  c_b3RecPlayer_GetFrameQueryHit :: Ptr RecPlayer -> CInt -> CInt -> Ptr RecQueryHit -> IO ()

{- | Create a player over a recording. Owns a private copy of the bytes.

Returns: a new player, or NULL on bad header or deserialization failure

Binds @b3RecPlayer_Create@.
-}
create
  :: Ptr ()
  -- ^ @data@: pointer to recording bytes
  -> Int
  -- ^ @size@: byte count of the recording
  -> Int
  -- ^ @workerCount@: worker count for the replay world; pass 1 to match a serial recording. Replaying at a different count re-partitions the constraint graph, so the StateHash check becomes a cross-thread determinism test. Adjustable later with b3RecPlayer_SetWorkerCount.
  -> IO (Ptr RecPlayer)
create :: Ptr () -> Int -> Int -> IO (Ptr RecPlayer)
create Ptr ()
a0 Int
a1 Int
a2 =
  Ptr () -> CInt -> CInt -> IO (Ptr RecPlayer)
c_b3RecPlayer_Create Ptr ()
a0 (Int -> CInt
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
a1) (Int -> CInt
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
a2)

{- | Destroy the player and free all memory. Restores the previous global length scale.

Binds @b3RecPlayer_Destroy@.
-}
destroy
  :: Ptr RecPlayer
  -> IO ()
destroy :: Ptr RecPlayer -> IO ()
destroy Ptr RecPlayer
a0 =
  Ptr RecPlayer -> IO ()
c_b3RecPlayer_Destroy Ptr RecPlayer
a0

{- | Advance one frame: dispatch ops until the next Step completes.

Returns: true when a frame was stepped, false at end-of-recording

Binds @b3RecPlayer_StepFrame@.
-}
stepFrame
  :: Ptr RecPlayer
  -> IO Bool
stepFrame :: Ptr RecPlayer -> IO Bool
stepFrame Ptr RecPlayer
a0 =
  CBool -> Bool
forall a. (Eq a, Num a) => a -> Bool
toBool (CBool -> Bool) -> IO CBool -> IO Bool
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> (Ptr RecPlayer -> IO CBool
c_b3RecPlayer_StepFrame Ptr RecPlayer
a0)

{- | Rewind to frame 0 (in-place restore so the world id stays stable).

Binds @b3RecPlayer_Restart@.
-}
restart
  :: Ptr RecPlayer
  -> IO ()
restart :: Ptr RecPlayer -> IO ()
restart Ptr RecPlayer
a0 =
  Ptr RecPlayer -> IO ()
c_b3RecPlayer_Restart Ptr RecPlayer
a0

{- | Seek to a specific frame. Forward seek steps op-by-op; backward seek restores
the nearest keyframe then re-steps the remaining gap.

Binds @b3RecPlayer_SeekFrame@.
-}
seekFrame
  :: Ptr RecPlayer
  -> Int
  -- ^ @targetFrame@
  -> IO ()
seekFrame :: Ptr RecPlayer -> Int -> IO ()
seekFrame Ptr RecPlayer
a0 Int
a1 =
  Ptr RecPlayer -> CInt -> IO ()
c_b3RecPlayer_SeekFrame Ptr RecPlayer
a0 (Int -> CInt
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
a1)

{- | Returns: the world currently driven by this player

Binds @b3RecPlayer_GetWorldId@.
-}
getWorldId
  :: Ptr RecPlayer
  -> IO WorldId
getWorldId :: Ptr RecPlayer -> IO WorldId
getWorldId Ptr RecPlayer
a0 =
  Ptr RecPlayer -> IO WorldId
c_b3RecPlayer_GetWorldId Ptr RecPlayer
a0

{- | Returns: the last fully-stepped frame index (0 before any step)

Binds @b3RecPlayer_GetFrame@.
-}
getFrame
  :: Ptr RecPlayer
  -> IO Int
getFrame :: Ptr RecPlayer -> IO Int
getFrame Ptr RecPlayer
a0 =
  CInt -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral (CInt -> Int) -> IO CInt -> IO Int
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> (Ptr RecPlayer -> IO CInt
c_b3RecPlayer_GetFrame Ptr RecPlayer
a0)

{- | Returns: total number of recorded frames

Binds @b3RecPlayer_GetFrameCount@.
-}
getFrameCount
  :: Ptr RecPlayer
  -> IO Int
getFrameCount :: Ptr RecPlayer -> IO Int
getFrameCount Ptr RecPlayer
a0 =
  CInt -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral (CInt -> Int) -> IO CInt -> IO Int
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> (Ptr RecPlayer -> IO CInt
c_b3RecPlayer_GetFrameCount Ptr RecPlayer
a0)

{- | Returns: true when the op stream is exhausted

Binds @b3RecPlayer_IsAtEnd@.
-}
isAtEnd
  :: Ptr RecPlayer
  -> IO Bool
isAtEnd :: Ptr RecPlayer -> IO Bool
isAtEnd Ptr RecPlayer
a0 =
  CBool -> Bool
forall a. (Eq a, Num a) => a -> Bool
toBool (CBool -> Bool) -> IO CBool -> IO Bool
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> (Ptr RecPlayer -> IO CBool
c_b3RecPlayer_IsAtEnd Ptr RecPlayer
a0)

{- | Returns: true when any StateHash mismatch has been detected

Binds @b3RecPlayer_HasDiverged@.
-}
hasDiverged
  :: Ptr RecPlayer
  -> IO Bool
hasDiverged :: Ptr RecPlayer -> IO Bool
hasDiverged Ptr RecPlayer
a0 =
  CBool -> Bool
forall a. (Eq a, Num a) => a -> Bool
toBool (CBool -> Bool) -> IO CBool -> IO Bool
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> (Ptr RecPlayer -> IO CBool
c_b3RecPlayer_HasDiverged Ptr RecPlayer
a0)

{- | Returns: a summary of the recording read at open: frame count, recorded tuning, and bounds

Binds @b3RecPlayer_GetInfo@.
-}
getInfo
  :: Ptr RecPlayer
  -> Ptr RecPlayerInfo
  -- ^ Result buffer.
  -> IO ()
getInfo :: Ptr RecPlayer -> Ptr RecPlayerInfo -> IO ()
getInfo Ptr RecPlayer
a0 Ptr RecPlayerInfo
out =
  Ptr RecPlayer -> Ptr RecPlayerInfo -> IO ()
c_b3RecPlayer_GetInfo Ptr RecPlayer
a0 Ptr RecPlayerInfo
out

{- | Returns: the first frame at which replay diverged, or -1 if it has not diverged

Binds @b3RecPlayer_GetDivergeFrame@.
-}
getDivergeFrame
  :: Ptr RecPlayer
  -> IO Int
getDivergeFrame :: Ptr RecPlayer -> IO Int
getDivergeFrame Ptr RecPlayer
a0 =
  CInt -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral (CInt -> Int) -> IO CInt -> IO Int
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> (Ptr RecPlayer -> IO CInt
c_b3RecPlayer_GetDivergeFrame Ptr RecPlayer
a0)

{- | Set the worker count of the replay world. Clamped to \[1, B3_MAX_WORKERS\]. Applied to the live
world at once and reused whenever the player rebuilds its world on Restart or a backward seek.
Replaying at a different count than recorded re-partitions the constraint graph, so the StateHash
check becomes a cross-thread determinism test.

Binds @b3RecPlayer_SetWorkerCount@.
-}
setWorkerCount
  :: Ptr RecPlayer
  -> Int
  -- ^ @count@
  -> IO ()
setWorkerCount :: Ptr RecPlayer -> Int -> IO ()
setWorkerCount Ptr RecPlayer
a0 Int
a1 =
  Ptr RecPlayer -> CInt -> IO ()
c_b3RecPlayer_SetWorkerCount Ptr RecPlayer
a0 (Int -> CInt
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
a1)

{- | Tune the keyframe ring used to speed up backward seeking. A keyframe is a periodic snapshot the
player restores from instead of replaying from the start, trading memory for seek speed.

Binds @b3RecPlayer_SetKeyframePolicy@.
-}
setKeyframePolicy
  :: Ptr RecPlayer
  -- ^ @player@: the recording player
  -> CSize
  -- ^ @budgetBytes@: memory cap for the kept snapshots; the spacing widens to stay under it
  -> Int
  -- ^ @minIntervalFrames@: finest spacing between keyframes, in frames A zero budget or a non-positive interval keeps that value. Clears the existing ring, so call b3RecPlayer_Restart afterward to repopulate it under the new policy.
  -> IO ()
setKeyframePolicy :: Ptr RecPlayer -> CSize -> Int -> IO ()
setKeyframePolicy Ptr RecPlayer
a0 CSize
a1 Int
a2 =
  Ptr RecPlayer -> CSize -> CInt -> IO ()
c_b3RecPlayer_SetKeyframePolicy Ptr RecPlayer
a0 CSize
a1 (Int -> CInt
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
a2)

{- | Returns: the keyframe memory budget in bytes

Binds @b3RecPlayer_GetKeyframeBudget@.
-}
getKeyframeBudget
  :: Ptr RecPlayer
  -> IO CSize
getKeyframeBudget :: Ptr RecPlayer -> IO CSize
getKeyframeBudget Ptr RecPlayer
a0 =
  Ptr RecPlayer -> IO CSize
c_b3RecPlayer_GetKeyframeBudget Ptr RecPlayer
a0

{- | Returns: the finest keyframe spacing in frames

Binds @b3RecPlayer_GetKeyframeMinInterval@.
-}
getKeyframeMinInterval
  :: Ptr RecPlayer
  -> IO Int
getKeyframeMinInterval :: Ptr RecPlayer -> IO Int
getKeyframeMinInterval Ptr RecPlayer
a0 =
  CInt -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral (CInt -> Int) -> IO CInt -> IO Int
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> (Ptr RecPlayer -> IO CInt
c_b3RecPlayer_GetKeyframeMinInterval Ptr RecPlayer
a0)

{- | Returns: the current keyframe spacing in frames; starts at the min interval and doubles as the ring evicts to stay under budget, so it reflects the effective backward-seek granularity now

Binds @b3RecPlayer_GetKeyframeInterval@.
-}
getKeyframeInterval
  :: Ptr RecPlayer
  -> IO Int
getKeyframeInterval :: Ptr RecPlayer -> IO Int
getKeyframeInterval Ptr RecPlayer
a0 =
  CInt -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral (CInt -> Int) -> IO CInt -> IO Int
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> (Ptr RecPlayer -> IO CInt
c_b3RecPlayer_GetKeyframeInterval Ptr RecPlayer
a0)

{- | Returns: the memory currently held by keyframe snapshots, in bytes

Binds @b3RecPlayer_GetKeyframeBytes@.
-}
getKeyframeBytes
  :: Ptr RecPlayer
  -> IO CSize
getKeyframeBytes :: Ptr RecPlayer -> IO CSize
getKeyframeBytes Ptr RecPlayer
a0 =
  Ptr RecPlayer -> IO CSize
c_b3RecPlayer_GetKeyframeBytes Ptr RecPlayer
a0

{- | Returns: the number of bodies tracked in creation order (including holes for destroyed bodies)

Binds @b3RecPlayer_GetBodyCount@.
-}
getBodyCount
  :: Ptr RecPlayer
  -> IO Int
getBodyCount :: Ptr RecPlayer -> IO Int
getBodyCount Ptr RecPlayer
a0 =
  CInt -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral (CInt -> Int) -> IO CInt -> IO Int
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> (Ptr RecPlayer -> IO CInt
c_b3RecPlayer_GetBodyCount Ptr RecPlayer
a0)

{- | Resolve a creation ordinal to the live body id at the current frame.

Returns: the body id, or a null id if that ordinal is out of range or its body is destroyed

Binds @b3RecPlayer_GetBodyId@.
-}
getBodyId
  :: Ptr RecPlayer
  -> Int
  -- ^ @index@
  -> IO BodyId
getBodyId :: Ptr RecPlayer -> Int -> IO BodyId
getBodyId Ptr RecPlayer
a0 Int
a1 =
  Ptr RecPlayer -> CInt -> IO BodyId
c_b3RecPlayer_GetBodyId Ptr RecPlayer
a0 (Int -> CInt
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
a1)

{- | Wire host debug-shape callbacks into the player\'s replay world so a renderer can build
per-shape draw resources (the 3D sample needs this or the replay world draws nothing).
Rebuilds the current world under the new callbacks and rewinds to frame 0, so call it
once right after b3RecPlayer_Create and re-read the world id afterward. The callbacks
persist across Restart and backward seeks, which recreate the world internally.

Binds @b3RecPlayer_SetDebugShapeCallbacks@.
-}
setDebugShapeCallbacks
  :: Ptr RecPlayer
  -- ^ @player@: the player to configure
  -> FunPtr CreateDebugShapeCallback
  -- ^ @createDebugShape@: called when a replayed shape is added; returns a user draw handle
  -> FunPtr DestroyDebugShapeCallback
  -- ^ @destroyDebugShape@: called when a replayed shape is removed; may be NULL
  -> Ptr ()
  -- ^ @context@: user context passed to both callbacks
  -> IO ()
setDebugShapeCallbacks :: Ptr RecPlayer
-> FunPtr CreateDebugShapeCallback
-> FunPtr DestroyDebugShapeCallback
-> Ptr ()
-> IO ()
setDebugShapeCallbacks Ptr RecPlayer
a0 FunPtr CreateDebugShapeCallback
a1 FunPtr DestroyDebugShapeCallback
a2 Ptr ()
a3 =
  Ptr RecPlayer
-> FunPtr CreateDebugShapeCallback
-> FunPtr DestroyDebugShapeCallback
-> Ptr ()
-> IO ()
c_b3RecPlayer_SetDebugShapeCallbacks Ptr RecPlayer
a0 FunPtr CreateDebugShapeCallback
a1 FunPtr DestroyDebugShapeCallback
a2 Ptr ()
a3

{- | Draw the spatial queries recorded during the most recently replayed frame, layered on top of the
world. Call after b3World_Draw. NULL draw function pointers are skipped.

Binds @b3RecPlayer_DrawFrameQueries@.
-}
drawFrameQueries
  :: Ptr RecPlayer
  -- ^ @player@: a valid player handle
  -> Ptr DebugDraw
  -- ^ @draw@: debug draw callbacks
  -> Int
  -- ^ @queryIndex@: index of the frame query to draw, or -1 to draw all of them
  -> Int
  -- ^ @selectedIndex@: index of the query to emphasize (reserved color plus a label), or -1 for none
  -> IO ()
drawFrameQueries :: Ptr RecPlayer -> Ptr DebugDraw -> Int -> Int -> IO ()
drawFrameQueries Ptr RecPlayer
a0 Ptr DebugDraw
a1 Int
a2 Int
a3 =
  Ptr RecPlayer -> Ptr DebugDraw -> CInt -> CInt -> IO ()
c_b3RecPlayer_DrawFrameQueries Ptr RecPlayer
a0 Ptr DebugDraw
a1 (Int -> CInt
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
a2) (Int -> CInt
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
a3)

{- | Returns: the number of spatial queries recorded for the most recently replayed frame

Binds @b3RecPlayer_GetFrameQueryCount@.
-}
getFrameQueryCount
  :: Ptr RecPlayer
  -> IO Int
getFrameQueryCount :: Ptr RecPlayer -> IO Int
getFrameQueryCount Ptr RecPlayer
a0 =
  CInt -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral (CInt -> Int) -> IO CInt -> IO Int
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> (Ptr RecPlayer -> IO CInt
c_b3RecPlayer_GetFrameQueryCount Ptr RecPlayer
a0)

{- | Get a recorded query from the most recently replayed frame by index.

Binds @b3RecPlayer_GetFrameQuery@.
-}
getFrameQuery
  :: Ptr RecPlayer
  -> Int
  -- ^ @index@
  -> Ptr RecQueryInfo
  -- ^ Result buffer.
  -> IO ()
getFrameQuery :: Ptr RecPlayer -> Int -> Ptr RecQueryInfo -> IO ()
getFrameQuery Ptr RecPlayer
a0 Int
a1 Ptr RecQueryInfo
out =
  Ptr RecPlayer -> CInt -> Ptr RecQueryInfo -> IO ()
c_b3RecPlayer_GetFrameQuery Ptr RecPlayer
a0 (Int -> CInt
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
a1) Ptr RecQueryInfo
out

{- | Get one result of a recorded query from the most recently replayed frame.

Binds @b3RecPlayer_GetFrameQueryHit@.
-}
getFrameQueryHit
  :: Ptr RecPlayer
  -> Int
  -- ^ @queryIndex@
  -> Int
  -- ^ @hitIndex@
  -> Ptr RecQueryHit
  -- ^ Result buffer.
  -> IO ()
getFrameQueryHit :: Ptr RecPlayer -> Int -> Int -> Ptr RecQueryHit -> IO ()
getFrameQueryHit Ptr RecPlayer
a0 Int
a1 Int
a2 Ptr RecQueryHit
out =
  Ptr RecPlayer -> CInt -> CInt -> Ptr RecQueryHit -> IO ()
c_b3RecPlayer_GetFrameQueryHit Ptr RecPlayer
a0 (Int -> CInt
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
a1) (Int -> CInt
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
a2) Ptr RecQueryHit
out