packages feed

chiphunk-0.1.0.0: src/Chiphunk/Low/Constraint.chs

-- | Description: Dealing with joints/constraints
-- Module defines utilities for operations with constraints.
module Chiphunk.Low.Constraint
  ( Constraint
  , constraintBodyA
  , constraintBodyB
  , constraintMaxForce
  , constraintErrorBias
  , constraintMaxBias
  , constraintSpace
  , constraintCollideBodies
  , constraintUserData
  , constraintImpulse
  , constraintFree
  , pinJointNew
  , pinJointAnchorA
  , pinJointAnchorB
  , pinJointDist
  , slideJointNew
  , slideJointAnchorA
  , slideJointAnchorB
  , slideJointMin
  , slideJointMax
  , pivotJointNew
  , pivotJointNew2
  , pivotJointAnchorA
  , pivotJointAnchorB
  , grooveJointNew
  , grooveJointGrooveA
  , grooveJointGrooveB
  , grooveJointAnchorB
  , dampedSpringNew
  , dampedSpringAnchorA
  , dampedSpringAnchorB
  , dampedSpringRestLength
  , dampedSpringStiffness
  , dampedSpringDamping
  , dampedRotarySpringNew
  , dampedRotarySpringRestAngle
  , dampedRotarySpringStiffness
  , dampedRotarySpringDamping
  , rotaryLimitJointNew
  , rotaryLimitJointMin
  , rotaryLimitJointMax
  , ratchetJointNew
  , ratchetJointAngle
  , ratchetJointPhase
  , ratchetJointRatchet
  , gearJointNew
  , gearJointPhase
  , gearJointRatio

  , simpleMotorNew
  , simpleMotorRate
  ) where

import Data.StateVar
import Foreign

{# import Chiphunk.Low.Types #}

#include <chipmunk/chipmunk.h>
#include <wrapper.h>

{# fun unsafe cpConstraintGetBodyA {`Constraint'} -> `Body' #}

-- | The first body constraint is attached to
constraintBodyA :: Constraint -> GettableStateVar Body
constraintBodyA = makeGettableStateVar . cpConstraintGetBodyA

{# fun unsafe cpConstraintGetBodyB {`Constraint'} -> `Body' #}

-- | The second body constraint is attached to
constraintBodyB :: Constraint -> GettableStateVar Body
constraintBodyB = makeGettableStateVar . cpConstraintGetBodyB

{# fun unsafe cpConstraintGetMaxForce {`Constraint'} -> `Double' #}

{# fun unsafe cpConstraintSetMaxForce {`Constraint', `Double'} -> `()' #}

-- | The maximum force that the constraint can use to act on the two bodies.
-- Defaults to INFINITY.
constraintMaxForce :: Constraint -> StateVar Double
constraintMaxForce = mkStateVar cpConstraintGetMaxForce cpConstraintSetMaxForce

{# fun unsafe cpConstraintGetErrorBias {`Constraint'} -> `Double' #}

{# fun unsafe cpConstraintSetErrorBias {`Constraint', `Double'} -> `()' #}

-- | The percentage of joint error that remains unfixed after a second.
-- This works exactly the same as the collision bias property of a space,
-- but applies to fixing error (stretching) of joints instead of overlapping collisions.
constraintErrorBias :: Constraint -> StateVar Double
constraintErrorBias = mkStateVar cpConstraintGetErrorBias cpConstraintSetErrorBias

{# fun unsafe cpConstraintGetMaxBias {`Constraint'} -> `Double' #}

{# fun unsafe cpConstraintSetMaxBias {`Constraint', `Double'} -> `()' #}

-- | Get the maximum speed at which the constraint can apply error correction.
-- Defaults to INFINITY.
constraintMaxBias :: Constraint -> StateVar Double
constraintMaxBias = mkStateVar cpConstraintGetMaxBias cpConstraintSetMaxBias

{# fun unsafe cpConstraintGetSpace {`Constraint'} -> `Space' #}

-- | The 'Space' that constraint has been added to.
constraintSpace :: Constraint -> GettableStateVar Space
constraintSpace = makeGettableStateVar . cpConstraintGetSpace

{# fun unsafe cpConstraintGetCollideBodies {`Constraint'} -> `Bool' #}

{# fun unsafe cpConstraintSetCollideBodies {`Constraint', `Bool'} -> `()' #}

-- | Constraints can be used for filtering collisions too.
-- When two bodies collide, Chipmunk ignores the collisions
-- if this property is set to @False@ on any constraint that connects the two bodies.
-- Defaults to @True@.
--
-- This can be used to create a chain that self collides,
-- but adjacent links in the chain do not collide.
constraintCollideBodies :: Constraint -> StateVar Bool
constraintCollideBodies = mkStateVar cpConstraintGetCollideBodies cpConstraintSetCollideBodies

{# fun unsafe cpConstraintGetUserData {`Constraint'} -> `DataPtr' #}

{# fun unsafe cpConstraintSetUserData {`Constraint', `DataPtr'} -> `()' #}

-- | A user definable data pointer.
-- Use this pointer to get a reference to the game object that owns this constraint
-- from callbacks.
constraintUserData :: Constraint -> StateVar DataPtr
constraintUserData = mkStateVar cpConstraintGetUserData cpConstraintSetUserData

{# fun unsafe cpConstraintGetImpulse {`Constraint'} -> `Double' #}

-- | The most recent impulse that constraint applied.
-- To convert this to a force, divide by the timestep passed to 'spaceStep'.
-- You can use this to implement breakable joints to check
-- if the force they attempted to apply exceeded a certain threshold.
constraintImpulse :: Constraint -> GettableStateVar Double
constraintImpulse = makeGettableStateVar . cpConstraintGetImpulse

-- | Free function is shared by all joint types. Allocation functions are specific to each joint type.
{# fun cpConstraintFree as constraintFree {`Constraint'} -> `()' #}
-- no "unsafe" qualifier because I think it may trigger separte callbacks

-- | Connect two bodies via anchor points on those bodies. The distance between the two anchor points is measured
-- when the joint is created. If you want to set a specific distance, use the setter function to override it.
{# fun unsafe cpPinJointNew as pinJointNew
  { `Body'        -- ^ First body to connect
  , `Body'        -- ^ Second body to connect
  , with* %`Vect' -- ^ First anchor
  , with* %`Vect' -- ^ Second anchor
  } -> `Constraint' #}

{# fun unsafe w_cpPinJointGetAnchorA {`Constraint', alloca- `Vect' peek*} -> `()' #}

{# fun unsafe cpPinJointSetAnchorA {`Constraint', with* %`Vect'} -> `()' #}

-- | Anchor on first body.
pinJointAnchorA :: Constraint -> StateVar Vect
pinJointAnchorA = mkStateVar w_cpPinJointGetAnchorA cpPinJointSetAnchorA

{# fun unsafe w_cpPinJointGetAnchorB {`Constraint', alloca- `Vect' peek*} -> `()' #}

{# fun unsafe cpPinJointSetAnchorB {`Constraint', with* %`Vect'} -> `()' #}

-- | Anchor on second body.
pinJointAnchorB :: Constraint -> StateVar Vect
pinJointAnchorB = mkStateVar w_cpPinJointGetAnchorB cpPinJointSetAnchorB

{# fun unsafe cpPinJointGetDist {`Constraint'} -> `Double' #}

{# fun unsafe cpPinJointSetDist {`Constraint', `Double'} -> `()' #}

-- | Desired distance the joint will try to enforce.
pinJointDist :: Constraint -> StateVar Double
pinJointDist = mkStateVar cpPinJointGetDist cpPinJointSetDist

-- | Connect two bodies via anchor points forcing distance to remain in range.
{# fun unsafe cpSlideJointNew as slideJointNew
  { `Body'        -- ^ First body to connect
  , `Body'        -- ^ Second body to connect
  , with* %`Vect' -- ^ First anchor
  , with* %`Vect' -- ^ Second anchor
  , `Double'      -- ^ Minimum allowed distance
  , `Double'      -- ^ Maximum allowed distance
  } -> `Constraint' #}

{# fun unsafe w_cpSlideJointGetAnchorA {`Constraint', alloca- `Vect' peek*} -> `()' #}

{# fun unsafe cpSlideJointSetAnchorA  {`Constraint', with* %`Vect'} -> `()' #}

-- | Anchor on first body.
slideJointAnchorA :: Constraint -> StateVar Vect
slideJointAnchorA = mkStateVar w_cpSlideJointGetAnchorA cpSlideJointSetAnchorA

{# fun unsafe w_cpSlideJointGetAnchorB {`Constraint', alloca- `Vect' peek*} -> `()' #}

{# fun unsafe cpSlideJointSetAnchorB {`Constraint', with* %`Vect'} -> `()' #}

-- | Anchor on second body.
slideJointAnchorB :: Constraint -> StateVar Vect
slideJointAnchorB = mkStateVar w_cpSlideJointGetAnchorB cpSlideJointSetAnchorB

{# fun unsafe cpSlideJointGetMin {`Constraint'} -> `Double' #}

{# fun unsafe cpSlideJointSetMin {`Constraint', `Double'} -> `()' #}

-- | The minimum distance the joint will try to enforce.
slideJointMin :: Constraint -> StateVar Double
slideJointMin = mkStateVar cpSlideJointGetMin cpSlideJointSetMin

{# fun unsafe cpSlideJointGetMax {`Constraint'} -> `Double' #}

{# fun unsafe cpSlideJointSetMax {`Constraint', `Double'} -> `()' #}

-- | The maximum distance the joint will try to enforce.
slideJointMax :: Constraint -> StateVar Double
slideJointMax = mkStateVar cpSlideJointGetMax cpSlideJointSetMax

-- | Because the pivot location is given in world coordinates,
-- you must have the bodies moved into the correct positions already.
{# fun unsafe cpPivotJointNew as pivotJointNew
  { `Body'        -- ^ First body to connect
  , `Body'        -- ^ Second body to connect
  , with* %`Vect' -- ^ Point in the world coordinates of the pivot
  } -> `Constraint' #}

-- | Alternatively you can specify the joint based on a pair of anchor points,
-- but make sure you have the bodies in the right place as the joint will fix itself
-- as soon as you start simulating the space.
{# fun unsafe cpPivotJointNew2 as pivotJointNew2
  { `Body'        -- ^ First body to connect
  , `Body'        -- ^ Second body to connect
  , with* %`Vect' -- ^ Anchor on first body
  , with* %`Vect' -- ^ Anchor on second body
  } -> `Constraint' #}

{# fun unsafe w_cpPivotJointGetAnchorA {`Constraint', alloca- `Vect' peek*} -> `()' #}

{# fun unsafe cpPivotJointSetAnchorA {`Constraint', with* %`Vect'} -> `()' #}

-- | Anchor on first body.
pivotJointAnchorA :: Constraint -> StateVar Vect
pivotJointAnchorA = mkStateVar w_cpPivotJointGetAnchorA cpPivotJointSetAnchorA

{# fun unsafe w_cpPivotJointGetAnchorB {`Constraint', alloca- `Vect' peek*} -> `()' #}

{# fun unsafe cpPivotJointSetAnchorB {`Constraint', with* %`Vect'} -> `()' #}

-- | Anchor on second body.
pivotJointAnchorB :: Constraint -> StateVar Vect
pivotJointAnchorB = mkStateVar w_cpPivotJointGetAnchorB cpPivotJointSetAnchorB

-- | Pivot is attached to groove on first body and to anchor on the second. All coordinates are body local.
{# fun unsafe cpGrooveJointNew as grooveJointNew
  { `Body'        -- ^ First body to connect
  , `Body'        -- ^ Second body to connect
  , with* %`Vect' -- ^ First endpoint of groove (on first body)
  , with* %`Vect' -- ^ Second endpoint of groove (on first body)
  , with* %`Vect' -- ^ Anchor (on second body)
  } -> `Constraint' #}

{# fun unsafe w_cpGrooveJointGetGrooveA {`Constraint', alloca- `Vect' peek*} -> `()' #}

{# fun unsafe cpGrooveJointSetGrooveA {`Constraint', with* %`Vect'} -> `()' #}

-- | First endpoint of groove (on first body).
grooveJointGrooveA :: Constraint -> StateVar Vect
grooveJointGrooveA = mkStateVar w_cpGrooveJointGetGrooveA cpGrooveJointSetGrooveA

{# fun unsafe w_cpGrooveJointGetGrooveB {`Constraint', alloca- `Vect' peek*} -> `()' #}

{# fun unsafe cpGrooveJointSetGrooveB {`Constraint', with* %`Vect'} -> `()' #}

-- | Second endpoint of groove (on first body).
grooveJointGrooveB :: Constraint -> StateVar Vect
grooveJointGrooveB = mkStateVar w_cpGrooveJointGetGrooveB cpGrooveJointSetGrooveB

{# fun unsafe w_cpGrooveJointGetAnchorB {`Constraint', alloca- `Vect' peek*} -> `()' #}

{# fun unsafe cpGrooveJointSetAnchorB {`Constraint', with* %`Vect'} -> `()' #}

-- | Anchor on second body.
grooveJointAnchorB :: Constraint -> StateVar Vect
grooveJointAnchorB = mkStateVar w_cpGrooveJointGetAnchorB cpGrooveJointSetAnchorB

-- | Defined much like a slide joint.
{# fun unsafe cpDampedSpringNew as dampedSpringNew
  { `Body'        -- ^ First body to connect
  , `Body'        -- ^ Second body to connect
  , with* %`Vect' -- ^ First anchor
  , with* %`Vect' -- ^ Second anchor
  , `Double'      -- ^ Distance the spring wants to be
  , `Double'      -- ^ Spring constant (<http://en.wikipedia.org/wiki/Young%27s_modulus Young's modulus>)
  , `Double'      -- ^ How soft to make damping of the spring
  } -> `Constraint' #}

{# fun unsafe w_cpDampedSpringGetAnchorA {`Constraint', alloca- `Vect' peek*} -> `()' #}

{# fun unsafe cpDampedSpringSetAnchorA {`Constraint', with* %`Vect'} -> `()' #}

-- | Anchor on first body.
dampedSpringAnchorA :: Constraint -> StateVar Vect
dampedSpringAnchorA = mkStateVar w_cpDampedSpringGetAnchorA cpDampedSpringSetAnchorA

{# fun unsafe w_cpDampedSpringGetAnchorB {`Constraint', alloca- `Vect' peek*} -> `()' #}

{# fun unsafe cpDampedSpringSetAnchorB {`Constraint', with* %`Vect'} -> `()' #}

-- | Anchor on second body.
dampedSpringAnchorB :: Constraint -> StateVar Vect
dampedSpringAnchorB = mkStateVar w_cpDampedSpringGetAnchorB cpDampedSpringSetAnchorB

{# fun unsafe cpDampedSpringGetRestLength {`Constraint'} -> `Double' #}

{# fun unsafe cpDampedSpringSetRestLength {`Constraint', `Double'} -> `()' #}

-- | Desired distance the spring will try to enforce.
dampedSpringRestLength :: Constraint -> StateVar Double
dampedSpringRestLength = mkStateVar cpDampedSpringGetRestLength cpDampedSpringSetRestLength

{# fun unsafe cpDampedSpringGetStiffness {`Constraint'} -> `Double' #}

{# fun unsafe cpDampedSpringSetStiffness {`Constraint', `Double'} -> `()' #}

-- | Spring stiffness
dampedSpringStiffness :: Constraint -> StateVar Double
dampedSpringStiffness = mkStateVar cpDampedSpringGetStiffness cpDampedSpringSetStiffness

{# fun unsafe cpDampedSpringGetDamping {`Constraint'} -> `Double' #}

{# fun unsafe cpDampedSpringSetDamping {`Constraint', `Double'} -> `()' #}

-- | Spring damping
dampedSpringDamping :: Constraint -> StateVar Double
dampedSpringDamping = mkStateVar cpDampedSpringGetDamping cpDampedSpringSetDamping

-- | Create new damped rotary spring constraint
{# fun unsafe cpDampedRotarySpringNew as dampedRotarySpringNew
  { `Body'    -- ^ First body to connect
  , `Body'    -- ^ Second body to connect
  , `Double'  -- ^ Relative angle in radians that the bodies want to have
  , `Double'  -- ^ Spring constant (stiffness)
  , `Double'  -- ^ Spring damping
  } -> `Constraint' #}

{# fun unsafe cpDampedRotarySpringGetRestAngle {`Constraint'} -> `Double' #}

{# fun unsafe cpDampedRotarySpringSetRestAngle {`Constraint', `Double'} -> `()' #}

-- | Set desired angle in radians the spring will try to enforce.
dampedRotarySpringRestAngle :: Constraint -> StateVar Double
dampedRotarySpringRestAngle = mkStateVar cpDampedRotarySpringGetRestAngle cpDampedRotarySpringSetRestAngle

{# fun unsafe cpDampedRotarySpringGetStiffness {`Constraint'} -> `Double' #}

{# fun unsafe cpDampedRotarySpringSetStiffness {`Constraint', `Double'} -> `()' #}

-- | Spring stiffness.
dampedRotarySpringStiffness :: Constraint -> StateVar Double
dampedRotarySpringStiffness = mkStateVar cpDampedRotarySpringGetStiffness cpDampedRotarySpringSetStiffness

{# fun unsafe cpDampedRotarySpringGetDamping {`Constraint'} -> `Double' #}

{# fun unsafe cpDampedRotarySpringSetDamping {`Constraint', `Double'} -> `()' #}

-- | Spring damping.
dampedRotarySpringDamping :: Constraint -> StateVar Double
dampedRotarySpringDamping = mkStateVar cpDampedRotarySpringGetDamping cpDampedRotarySpringSetDamping

-- | Create new rotation limiting joint
{# fun unsafe cpRotaryLimitJointNew as rotaryLimitJointNew
  { `Body'    -- ^ First body to connect
  , `Body'    -- ^ Second body to connect
  , `Double'  -- ^ Minimum angle in radians the joint will enforce
  , `Double'  -- ^ Maximum angle in radians the joint will enforce
  } -> `Constraint' #}

{# fun unsafe cpRotaryLimitJointGetMin {`Constraint'} -> `Double' #}

{# fun unsafe cpRotaryLimitJointSetMin {`Constraint', `Double'} -> `()' #}

-- | Minimum angle in radians the joint will try to enforce.
rotaryLimitJointMin :: Constraint -> StateVar Double
rotaryLimitJointMin = mkStateVar cpRotaryLimitJointGetMin cpRotaryLimitJointSetMin

{# fun unsafe cpRotaryLimitJointGetMax {`Constraint'} -> `Double' #}

{# fun unsafe cpRotaryLimitJointSetMax {`Constraint', `Double'} -> `()' #}

-- | Maximum angle in radians the joint will try to enforce.
rotaryLimitJointMax :: Constraint -> StateVar Double
rotaryLimitJointMax = mkStateVar cpRotaryLimitJointGetMax cpRotaryLimitJointSetMax

-- | Allocate and initialize a ratchet joint.
{# fun unsafe cpRatchetJointNew as ratchetJointNew
  { `Body'    -- ^ First body to connect
  , `Body'    -- ^ Second body to connect
  , `Double'  -- ^ The initial offset to use when deciding where the ratchet angles are.
  , `Double'  -- ^ The distance between “clicks”
  } -> `Constraint' #}

{# fun unsafe cpRatchetJointGetAngle {`Constraint'} -> `Double' #}

{# fun unsafe cpRatchetJointSetAngle {`Constraint', `Double'} -> `()' #}

-- | The angle of the current ratchet tooth.
ratchetJointAngle :: Constraint -> StateVar Double
ratchetJointAngle = mkStateVar cpRatchetJointGetAngle cpRatchetJointSetAngle

{# fun unsafe cpRatchetJointGetPhase {`Constraint'} -> `Double' #}

{# fun unsafe cpRatchetJointSetPhase {`Constraint', `Double'} -> `()' #}

-- | The phase offset of the ratchet.
ratchetJointPhase :: Constraint -> StateVar Double
ratchetJointPhase = mkStateVar cpRatchetJointGetPhase cpRatchetJointSetPhase

{# fun unsafe cpRatchetJointGetRatchet {`Constraint'} -> `Double' #}

{# fun unsafe cpRatchetJointSetRatchet {`Constraint', `Double'} -> `()' #}

-- | The angular distance of each ratchet.
ratchetJointRatchet :: Constraint -> StateVar Double
ratchetJointRatchet = mkStateVar cpRatchetJointGetRatchet cpRatchetJointSetRatchet

-- | Allocate and initialize a gear joint.
{# fun unsafe cpGearJointNew as gearJointNew
  { `Body'    -- ^ First body to connect
  , `Body'    -- ^ Second body to connect
  , `Double'  -- ^ The initial angular offset of the two bodies.
  , `Double'  -- ^ Ratio measures in absolute terms
  } -> `Constraint' #}

{# fun unsafe cpGearJointGetPhase {`Constraint'} -> `Double' #}

{# fun unsafe cpGearJointSetPhase {`Constraint', `Double'} -> `()' #}

-- | Phase offset of the ratchet.
gearJointPhase :: Constraint -> StateVar Double
gearJointPhase = mkStateVar cpGearJointGetPhase cpGearJointSetPhase

{# fun unsafe cpGearJointGetRatio {`Constraint'} -> `Double' #}

{# fun unsafe cpGearJointSetRatio {`Constraint', `Double'} -> `()' #}

-- | Ratio of the ratchet
gearJointRatio :: Constraint -> StateVar Double
gearJointRatio = mkStateVar cpGearJointGetRatio cpGearJointSetRatio

-- | Allocate and initialize a simple motor.
{# fun unsafe cpSimpleMotorNew as simpleMotorNew
  { `Body'    -- ^ First body to connect
  , `Body'    -- ^ Second body to connect
  , `Double'  -- ^ The desired relative angular velocity.
  } -> `Constraint' #}

{# fun unsafe cpSimpleMotorGetRate {`Constraint'} -> `Double' #}

{# fun unsafe cpSimpleMotorSetRate {`Constraint', `Double'} -> `()' #}

-- | Ratio of angular velocities.
simpleMotorRate :: Constraint -> StateVar Double
simpleMotorRate = mkStateVar cpSimpleMotorGetRate cpSimpleMotorSetRate