{-# LANGUAGE BangPatterns #-}
{-# LANGUAGE MagicHash #-}
{-# LANGUAGE PatternGuards #-}
{-# LANGUAGE ScopedTypeVariables #-}
module Graphics.Gloss.Raster.Array
(
module Graphics.Gloss.Data.Color
, rgb, rgbI, rgb8w
, rgb', rgbI'
, Display (..)
, animateArray
, playArray
, animateArrayIO
, playArrayIO)
where
import Graphics.Gloss.Data.Color
import Graphics.Gloss.Data.Picture
import Graphics.Gloss.Data.Display
import Graphics.Gloss.Data.Bitmap
import Graphics.Gloss.Interface.Pure.Game
import Graphics.Gloss.Interface.IO.Animate
import Graphics.Gloss.Interface.IO.Game
import Graphics.Gloss.Interface.Environment
import Graphics.Gloss.Rendering
import Data.Word
import System.IO.Unsafe
import Unsafe.Coerce
import Debug.Trace
import Data.Bits
import Data.Array.Repa as R
import Data.Array.Repa.Repr.ForeignPtr as R
import Prelude as P
rgb :: Float -> Float -> Float -> Color
rgb r g b = makeColor r g b 1.0
{-# INLINE rgb #-}
rgbI :: Int -> Int -> Int -> Color
rgbI r g b = makeColorI r g b 255
{-# INLINE rgbI #-}
rgb8w :: Word8 -> Word8 -> Word8 -> Color
rgb8w r g b = makeRawColorI (fromIntegral r) (fromIntegral g) (fromIntegral b) 255
{-# INLINE rgb8w #-}
rgb' :: Float -> Float -> Float -> Color
rgb' r g b = makeRawColor r g b 1.0
{-# INLINE rgb' #-}
rgbI' :: Int -> Int -> Int -> Color
rgbI' r g b = makeRawColorI r g b 255
{-# INLINE rgbI' #-}
animateArray
:: Display
-> (Int, Int)
-> (Float -> Array D DIM2 Color)
-> IO ()
animateArray display scale@(scaleX, scaleY) makeArray
= scaleX `seq` scaleY `seq`
if scaleX < 1 || scaleY < 1
then error $ "Graphics.Gloss.Raster.Array: invalid pixel scale factor "
P.++ show (scaleX, scaleY)
else let {-# INLINE frame #-}
frame !time = return $ makeFrame scale (makeArray time)
in animateFixedIO display black frame (const $ return ())
{-# INLINE animateArray #-}
animateArrayIO
:: Display
-> (Int, Int)
-> (Float -> IO (Array D DIM2 Color))
-> IO ()
animateArrayIO display scale@(scaleX, scaleY) makeArray
= scaleX `seq` scaleY `seq`
if scaleX < 1 || scaleY < 1
then error $ "Graphics.Gloss.Raster.Array: invalid pixel scale factor "
P.++ show (scaleX, scaleY)
else let {-# INLINE frame #-}
frame !time = fmap (makeFrame scale) (makeArray time)
in animateFixedIO display black frame (const $ return ())
{-# INLINE animateArrayIO #-}
playArray
:: Display
-> (Int, Int)
-> Int
-> world
-> (world -> Array D DIM2 Color)
-> (Event -> world -> world)
-> (Float -> world -> world)
-> IO ()
playArray !display scale@(scaleX, scaleY) !stepRate
!initWorld !makeArray !handleEvent !stepWorld
= scaleX `seq` scaleY `seq`
if scaleX < 1 || scaleY < 1
then error $ "Graphics.Gloss.Raster.Array: invalid pixel scale factor "
P.++ show scale
else let {-# INLINE frame #-}
frame !world = makeFrame scale (makeArray world)
in play display black
stepRate
initWorld
frame
handleEvent
stepWorld
{-# INLINE playArray #-}
playArrayIO
:: Display
-> (Int, Int)
-> Int
-> world
-> (world -> IO (Array D DIM2 Color))
-> (Event -> world -> IO world)
-> (Float -> world -> IO world)
-> IO ()
playArrayIO !display scale@(scaleX, scaleY) !stepRate
!initWorld !makeArray !handleEvent !stepWorld
= scaleX `seq` scaleY `seq`
if scaleX < 1 || scaleY < 1
then error $ "Graphics.Gloss.Raster.Array: invalid pixel scale factor "
P.++ show scale
else let {-# INLINE frame #-}
frame !world = fmap (makeFrame scale) (makeArray world)
in playIO display black
stepRate
initWorld
frame
handleEvent
stepWorld
{-# INLINE playArrayIO #-}
makeFrame :: (Int, Int) -> Array D DIM2 Color -> Picture
makeFrame (scaleX, scaleY) !array
= let
_ :. sizeY :. sizeX
= R.extent array
convColor :: Color -> Word32
convColor color
= let (r, g, b) = unpackColor color
r' = fromIntegral r
g' = fromIntegral g
b' = fromIntegral b
a = 255
!w = unsafeShiftL r' 24
.|. unsafeShiftL g' 16
.|. unsafeShiftL b' 8
.|. a
in w
{-# INLINE convColor #-}
in unsafePerformIO $ do
traceEventIO "Gloss.Raster[makeFrame]: start frame evaluation."
(arrRGB :: Array F DIM2 Word32)
<- R.computeP $ R.map convColor array
traceEventIO "Gloss.Raster[makeFrame]: done, returning picture."
let picture
= Scale (fromIntegral scaleX) (fromIntegral scaleY)
$ bitmapOfForeignPtr
sizeX sizeY
(BitmapFormat BottomToTop PxABGR)
(R.toForeignPtr $ unsafeCoerce arrRGB)
False
return picture
{-# INLINE makeFrame #-}
word8OfFloat :: Float -> Word8
word8OfFloat f
= fromIntegral (truncate f :: Int)
{-# INLINE word8OfFloat #-}
unpackColor :: Color -> (Word8, Word8, Word8)
unpackColor c
| (r, g, b, _) <- rgbaOfColor c
= ( word8OfFloat (r * 255)
, word8OfFloat (g * 255)
, word8OfFloat (b * 255))
{-# INLINE unpackColor #-}
sizeOfDisplay :: Display -> IO (Int, Int)
sizeOfDisplay display
= case display of
InWindow _ s _ -> return s
FullScreen -> getScreenSize
{-# INLINE sizeOfDisplay #-}