never executed always true always false
    1 module Reanimate.Chiphunk
    2   ( simulate
    3   , BodyStore
    4   , newBodyStore
    5   , addToBodyStore
    6   , spaceFreeRecursive
    7   , polyShapesToBody
    8   , polygonsToBody
    9   ) where
   10 
   11 import           Chiphunk.Low
   12 import           Control.Monad
   13 import           Data.IORef
   14 import           Data.Map            (Map)
   15 import qualified Data.Map            as Map
   16 import qualified Data.Vector         as V
   17 import qualified Data.Vector.Mutable as V
   18 import           Foreign.Ptr
   19 import           Graphics.SvgTree    (Tree)
   20 import           Linear.V2 (V2(..))
   21 import           Reanimate.Animation
   22 import           Reanimate.PolyShape
   23 import           Reanimate.Svg.Constructors
   24 
   25 type BodyStore = IORef (Map WordPtr Tree)
   26 
   27 newBodyStore :: IO BodyStore
   28 newBodyStore = newIORef Map.empty
   29 
   30 addToBodyStore :: BodyStore -> Body -> Tree -> IO ()
   31 addToBodyStore store body svg = do
   32   key <- atomicModifyIORef' store $ \m ->
   33           case Map.maxViewWithKey m of
   34             Nothing -> (Map.singleton 1 svg, 1)
   35             Just ((maxKey,_),_) ->
   36               (Map.insert (maxKey+1) svg m, maxKey+1)
   37   bodyUserData body $= wordPtrToPtr key
   38 
   39 renderBodyStore :: Space -> BodyStore -> IO Tree
   40 renderBodyStore space store = do
   41   m <- readIORef store
   42   lst <- newIORef []
   43   spaceEachBody space (\body _dat -> do
   44     key <- get (bodyUserData body)
   45     case Map.lookup (ptrToWordPtr key) m of
   46       Nothing -> putStrLn "Body doesn't have an associated SVG"
   47       Just svg -> do
   48         Vect posX posY <- get $ bodyPosition body
   49         angle <- get $ bodyAngle body
   50         let bodySvg =
   51               translate posX posY $
   52               rotate (angle/pi*180)
   53               svg
   54         modifyIORef lst (bodySvg:)
   55     ) nullPtr
   56   result <- readIORef lst
   57   return $ mkGroup result
   58 
   59 
   60 simulate :: Space -> BodyStore -> Double -> Int -> Double -> IO Animation
   61 simulate space store fps stepsPerFrame dur = do
   62   let timeStep = 1/(fps*fromIntegral stepsPerFrame)
   63       frames = round (dur * fps)
   64   v <- V.new frames
   65   forM_ [0..frames-1] $ \nth -> do
   66     svg <- renderBodyStore space store
   67     V.write v nth svg
   68     replicateM_ stepsPerFrame $ spaceStep space timeStep
   69   frozen <- V.unsafeFreeze v
   70   return $ mkAnimation dur $ \t ->
   71     let key = round (t * fromIntegral (frames-1))
   72     in frozen V.! key
   73 
   74 polyShapesToBody :: Space -> [PolyShape] -> IO Body
   75 polyShapesToBody space poly =
   76     polygonsToBody space (map (map toVect) $ plDecompose poly)
   77   where
   78     toVect (V2 x y) = Vect x y
   79 
   80 polygonsToBody :: Space -> [[Vect]] -> IO Body
   81 polygonsToBody space polygons = do
   82   plBody <- bodyNew 0 0
   83   spaceAddBody space plBody
   84 
   85   forM_ polygons $ \vects -> do
   86     polyShape <- polyShapeNewRaw plBody vects 0.00
   87     shapeDensity polyShape $= 1
   88     spaceAddShape space polyShape
   89     shapeFriction polyShape $= 0.7
   90     shapeElasticity polyShape $= 0.5
   91   return plBody
   92 
   93 spaceFreeRecursive :: Space -> IO ()
   94 spaceFreeRecursive space = do
   95   spaceEachBody space (\body _ -> bodyFree body) nullPtr
   96   spaceEachShape space (\shape _ -> shapeFree shape) nullPtr
   97   spaceFree space