chiphunk-0.1.0.0: src/Chiphunk/Low/Space.chs
-- | Description: Manipulate space
-- Module defined utilities for manipulating spaces.
module Chiphunk.Low.Space
( Space
, spaceIterations
, spaceGravity
, spaceDamping
, spaceIdleSpeedThreshold
, spaceSleepTimeThreshold
, spaceCollisionSlop
, spaceCollisionBias
, spaceCollisionPersistence
, spaceCurrentTimeStep
, spaceIsLocked
, spaceUserData
, spaceStaticBody
, spaceNew
, spaceFree
, spaceAddShape
, spaceAddBody
, spaceAddConstraint
, spaceRemoveShape
, spaceRemoveBody
, spaceRemoveConstraint
, spaceContainsShape
, spaceContainsBody
, spaceContainsConstraint
, spaceReindexShape
, spaceReindexShapesForBody
, spaceReindexStatic
, SpaceBodyIteratorFunc
, spaceEachBody
, SpaceShapeIteratorFunc
, spaceEachShape
, SpaceConstraintIteratorFunc
, spaceEachConstraint
, spaceStep
) where
import Control.Exception.Safe
import Data.StateVar
import Foreign
import Chiphunk.Low.Vect
{# import Chiphunk.Low.Types #}
#include <chipmunk/chipmunk.h>
#include <wrapper.h>
{# fun unsafe cpSpaceGetIterations {`Space'} -> `Int' #}
{# fun unsafe cpSpaceSetIterations {`Space', `Int'} -> `()' #}
-- | Iterations allow you to control the accuracy of the solver.
-- Defaults to 10. See above for more information.
spaceIterations :: Space -> StateVar Int
spaceIterations = mkStateVar cpSpaceGetIterations cpSpaceSetIterations
{# fun unsafe w_cpSpaceGetGravity {`Space', alloca- `Vect' peek*} -> `()' #}
{# fun unsafe cpSpaceSetGravity {`Space', with* %`Vect'} -> `()' #}
-- | Global gravity applied to the space. Defaults to 'vZero'.
-- Can be overridden on a per body basis by writing custom integration functions.
-- Changing the gravity will activate all sleeping bodies in the space.
spaceGravity :: Space -> StateVar Vect
spaceGravity = mkStateVar w_cpSpaceGetGravity cpSpaceSetGravity
{# fun unsafe cpSpaceGetDamping {`Space'} -> `Double' #}
{# fun unsafe cpSpaceSetDamping {`Space', `Double'} -> `()' #}
-- | Amount of simple damping to apply to the space.
-- A value of 0.9 means that each body will lose 10% of its velocity per second.
-- Defaults to 1. Like gravity, it can be overridden on a per body basis.
spaceDamping :: Space -> StateVar Double
spaceDamping = mkStateVar cpSpaceGetDamping cpSpaceSetDamping
{# fun unsafe cpSpaceGetIdleSpeedThreshold {`Space'} -> `Double' #}
{# fun unsafe cpSpaceSetIdleSpeedThreshold {`Space', `Double'} -> `()' #}
-- | Speed threshold for a body to be considered idle.
-- The default value of 0 means the space estimates a good threshold based on gravity.
spaceIdleSpeedThreshold :: Space -> StateVar Double
spaceIdleSpeedThreshold = mkStateVar cpSpaceGetIdleSpeedThreshold cpSpaceSetIdleSpeedThreshold
{# fun unsafe cpSpaceGetSleepTimeThreshold {`Space'} -> `Double' #}
{# fun unsafe cpSpaceSetSleepTimeThreshold {`Space', `Double'} -> `()' #}
-- | Time a group of bodies must remain idle in order to fall asleep.
-- The default value of INFINITY disables the sleeping feature.
spaceSleepTimeThreshold :: Space -> StateVar Double
spaceSleepTimeThreshold = mkStateVar cpSpaceGetSleepTimeThreshold cpSpaceSetSleepTimeThreshold
{# fun unsafe cpSpaceGetCollisionSlop {`Space'} -> `Double' #}
{# fun unsafe cpSpaceSetCollisionSlop {`Space', `Double'} -> `()' #}
-- | Amount of overlap between shapes that is allowed.
-- To improve stability, set this as high as you can without noticable overlapping.
-- It defaults to @0.1@.
spaceCollisionSlop :: Space -> StateVar Double
spaceCollisionSlop = mkStateVar cpSpaceGetCollisionSlop cpSpaceSetCollisionSlop
{# fun unsafe cpSpaceGetCollisionBias {`Space'} -> `Double' #}
{# fun unsafe cpSpaceSetCollisionBias {`Space', `Double'} -> `()' #}
-- | Chipmunk allows fast moving objects to overlap, then fixes the overlap over time.
-- Overlapping objects are unavoidable even if swept collisions are supported,
-- and this is an efficient and stable way to deal with overlapping objects.
-- The bias value controls what percentage of overlap remains unfixed
-- after a second and defaults to ~0.2%.
--
-- Valid values are in the range from 0 to 1,
-- but using 0 is not recommended for stability reasons.
--
-- The default value is calculated as @(1.0 - 0.1) ^ 60@
-- meaning that Chipmunk attempts to correct 10% of error ever 1/60th of a second.
--
-- __Note__: Very very few games will need to change this value.
spaceCollisionBias :: Space -> StateVar Double
spaceCollisionBias = mkStateVar cpSpaceGetCollisionBias cpSpaceSetCollisionBias
{# fun unsafe cpSpaceGetCollisionPersistence {`Space'} -> `Word32' #}
{# fun unsafe cpSpaceSetCollisionPersistence {`Space', `Word32'} -> `()' #}
-- | The number of frames the space keeps collision solutions around for.
-- Helps prevent jittering contacts from getting worse.
-- This defaults to 3 and very very very few games will need to change this value.
spaceCollisionPersistence :: Space -> StateVar Word32
spaceCollisionPersistence = mkStateVar cpSpaceGetCollisionPersistence cpSpaceSetCollisionPersistence
{# fun unsafe cpSpaceGetCurrentTimeStep {`Space'} -> `Double' #}
-- | The current (if you are in a callback from 'spaceStep')
-- or most recent (outside of a 'spaceStep' call) timestep.
spaceCurrentTimeStep :: Space -> GettableStateVar Double
spaceCurrentTimeStep = makeGettableStateVar . cpSpaceGetCurrentTimeStep
-- | Returns true when you cannot add/remove objects from the space.
-- In particular, spaces are locked when in a collision callback.
-- Instead, run your code in a post-step callback instead.
{# fun unsafe cpSpaceIsLocked as spaceIsLocked {`Space'} -> `Bool' #}
{# fun unsafe cpSpaceGetUserData {`Space'} -> `DataPtr' #}
{# fun unsafe cpSpaceSetUserData {`Space', `DataPtr'} -> `()' #}
-- | A user definable data pointer.
-- It is often useful to point this at the gamestate object
-- or scene management object that owns the space.
spaceUserData :: Space -> StateVar DataPtr
spaceUserData = mkStateVar cpSpaceGetUserData cpSpaceSetUserData
{# fun unsafe cpSpaceGetStaticBody {`Space'} -> `Body' #}
-- | A dedicated static body for the space.
-- You don’t have to use it,
-- but because its memory is managed automatically with the space its very convenient.
-- You can set its user data pointer to something helpful if you want for callbacks.
spaceStaticBody :: Space -> GettableStateVar Body
spaceStaticBody = makeGettableStateVar . cpSpaceGetStaticBody
-- | Standard Chipmunk allocation function.
{# fun unsafe cpSpaceNew as spaceNew {} -> `Space' #}
-- | Standard Chipmunk deallocation function.
{# fun cpSpaceFree as spaceFree {`Space'} -> `()' #}
-- no "unsafe" qualifier because I think it may trigger separte callbacks
-- | Add shape to the space.
{# fun unsafe cpSpaceAddShape as spaceAddShape {`Space', `Shape'} -> `()' #}
-- | Add body to the space.
{# fun unsafe cpSpaceAddBody as spaceAddBody {`Space', `Body'} -> `()' #}
-- | Add constraint to the space.
{# fun unsafe cpSpaceAddConstraint as spaceAddConstraint {`Space', `Constraint'} -> `()' #}
-- | Remove shape from the space.
{# fun cpSpaceRemoveShape as spaceRemoveShape {`Space', `Shape'} -> `()' #}
-- no "unsafe" qualifier because I think it may trigger separte callbacks
-- | Remove body from the space.
{# fun cpSpaceRemoveBody as spaceRemoveBody {`Space', `Body'} -> `()' #}
-- no "unsafe" qualifier because I think it may trigger separte callbacks
-- | Remove constraint from the space.
{# fun cpSpaceRemoveConstraint as spaceRemoveConstraint {`Space', `Constraint'} -> `()' #}
-- no "unsafe" qualifier because I think it may trigger separte callbacks
-- | Check if shape is attached to the space.
{# fun unsafe cpSpaceContainsShape as spaceContainsShape {`Space', `Shape'} -> `Bool' #}
-- | Check if body is attached to the space.
{# fun unsafe cpSpaceContainsBody as spaceContainsBody {`Space', `Body'} -> `Bool' #}
-- | Check if constraint is attached to the space.
{# fun unsafe cpSpaceContainsConstraint as spaceContainsConstraint {`Space', `Constraint'} -> `Bool' #}
-- | Reindex a specific shape.
{# fun unsafe cpSpaceReindexShape as spaceReindexShape {`Space', `Shape'} -> `()' #}
-- | Reindex all the shapes for a certain body.
{# fun unsafe cpSpaceReindexShapesForBody as spaceReindexShapesForBody {`Space', `Body'} -> `()' #}
-- | Reindex all static shapes. Generally updating only the shapes that changed is faster.
{# fun unsafe cpSpaceReindexStatic as spaceReindexStatic {`Space'} -> `()' #}
-- | Type of callback which can be used to iterate all 'Body's in a 'Space'.
type SpaceBodyIteratorFunc = Body -> Ptr () -> IO ()
foreign import ccall unsafe "wrapper"
mkSpaceBodyIteratorFunc :: SpaceBodyIteratorFunc -> IO (FunPtr SpaceBodyIteratorFunc)
-- | Call @func@ for each body in the @space@ also passing along your @data@ pointer.
-- Sleeping bodies are included, but static and kinematic bodies are not as they aren’t added to the space.
{# fun cpSpaceEachBody as spaceEachBody
{ `Space' -- ^ space
, withIterator* `SpaceBodyIteratorFunc' -- ^ func
, `Ptr ()' -- ^ data
} -> `()' #}
where
withIterator i = mkSpaceBodyIteratorFunc i `bracket` freeHaskellFunPtr
-- | Type of callback which can be used to iterate all 'Shape's in a 'Space'.
type SpaceShapeIteratorFunc = Shape -> Ptr () -> IO ()
foreign import ccall unsafe "wrapper"
mkSpaceShapeIteratorFunc :: SpaceShapeIteratorFunc -> IO (FunPtr SpaceShapeIteratorFunc)
-- | Call @func@ for each shape in the @space@ also passing along your @data@ pointer.
-- Sleeping and static shapes are included.
{# fun cpSpaceEachShape as spaceEachShape
{ `Space' -- ^ space
, withIterator* `SpaceShapeIteratorFunc' -- ^ func
, `Ptr ()' -- ^ data
} -> `()' #}
where
withIterator i = mkSpaceShapeIteratorFunc i `bracket` freeHaskellFunPtr
-- | Type of callback which can be used to iterate all 'Constraint's in a 'Space'.
type SpaceConstraintIteratorFunc = Constraint -> Ptr () -> IO ()
foreign import ccall unsafe "wrapper"
mkSpaceConstraintIteratorFunc :: SpaceConstraintIteratorFunc -> IO (FunPtr SpaceConstraintIteratorFunc)
-- | Call func for each constraint in the space also passing along your data pointer.
{# fun cpSpaceEachConstraint as spaceEachConstraint
{ `Space' -- ^ space
, withIterator* `SpaceConstraintIteratorFunc' -- ^ func
, `Ptr ()' -- ^ data
} -> `()' #}
where
withIterator i = mkSpaceConstraintIteratorFunc i `bracket` freeHaskellFunPtr
-- | Update the space for the given time step. Using a fixed time step is highly recommended.
-- Doing so can greatly increase the quality of the simulation.
-- The easiest way to do constant timesteps is to simple step forward by 1/60th of a second
-- (or whatever your target framerate is) for each frame regardless of how long it took to render.
-- This works fine for many games, but a better way to do it is to separate your physics timestep and rendering.
{# fun cpSpaceStep as spaceStep {`Space', `Double'} -> `()' #}