spice-0.5.0.0: src/FRP/Spice/Internal/Assets.hs
{-|
This module provides functions to load and manage the loading of assets.
-}
module FRP.Spice.Internal.Assets (performAssetLoads) where
--------------------
-- Global Imports --
import qualified Data.Map.Strict as Map
import Graphics.Rendering.OpenGL
import Graphics.UI.GLFW as GLFW
import Data.ByteString.Unsafe
import Control.Applicative
import Codec.Picture.Repa
import Codec.Picture
import Control.Monad
import Data.Default
import Foreign.Ptr
-------------------
-- Local Imports --
import FRP.Spice.Internal.Types
----------
-- Code --
{-|
Loading a @'Sprite'@ from the file system from the @'FilePath'@ specified.
-}
loadSprite :: FilePath -> IO Sprite
loadSprite path = do
wsize <- get windowSize
liftM (makeSprite wsize) $ loadTexture path
where getInfo :: DynamicImage -> Either String (Int, Int, PixelInternalFormat)
getInfo (ImageRGB8 (Image w h _)) = Right (w, h, RGB8)
getInfo (ImageRGB16 (Image w h _)) = Right (w, h, RGB16)
getInfo (ImageRGBA8 (Image w h _)) = Right (w, h, RGBA8)
getInfo (ImageRGBA16 (Image w h _)) = Right (w, h, RGBA16)
getInfo _ = Left "Unsupported image type."
loadTexture :: FilePath -> IO (TextureObject, Size)
loadTexture path = do
img <- either error id <$> readImageRGBA path
let dynimg = imgToImage img
(w, h, format) = either error id $ getInfo dynimg
glSize = TextureSize2D (fromIntegral w) (fromIntegral h)
bs = toByteString img
ptr <- unsafeUseAsCString bs $ \cstr ->
return $ castPtr cstr
[t] <- genObjectNames 1
textureBinding Texture2D $= Just t
texImage2D Texture2D NoProxy 0 format glSize 0 (PixelData ABGR UnsignedByte ptr)
return (t, Size (fromIntegral w) (fromIntegral h))
makeSprite :: Size -> (TextureObject, Size) -> Sprite
makeSprite (Size ww wh) (to, (Size w h)) =
Sprite { spriteTex = to
, spriteSize = Vector ((fromIntegral w) / (fromIntegral ww))
((fromIntegral h) / (fromIntegral wh))
}
{-|
Appending a @'Sprite'@ to an @'Assets'@.
-}
appendSprite :: Assets -> FilePath -> Sprite -> Assets
appendSprite assets path sprite =
assets { sprites = Map.insert path sprite $ sprites assets }
{-|
Performing all of the @'LoadAsset'@ commands contained in a @'LoadAssets'@.
-}
performAssetLoads :: LoadAssets -> IO Assets
performAssetLoads (DoListT las _) =
performAssetLoads' las def
where performAssetLoads' :: [LoadAsset] -> Assets -> IO Assets
performAssetLoads' [] assets = return assets
performAssetLoads' ((LoadSprite path):xs) assets = (liftM (appendSprite assets path) $ loadSprite path) >>= performAssetLoads' xs