packages feed

call 0.1.2 → 0.1.3

raw patch · 16 files changed

+1768/−1767 lines, 16 filesdep +extensibledep ~OpenGLdep ~elevatordep ~objective

Dependencies added: extensible

Dependency ranges changed: OpenGL, elevator, objective

Files

call.cabal view
@@ -1,93 +1,94 @@-name:                call
-version:             0.1.2
-synopsis:            The call game engine
-description:         Call is a minimalistic game engine that supports 2D/3D graphics and sounds.
-homepage:            https://github.com/fumieval/call
-license:             BSD3
-license-file:        LICENSE
-author:              Fumiaki Kinoshita
-maintainer:          Fumiaki Kinoshita <fumiexcel@gmail.com>
-copyright:           (c) Fumiaki Kinoshita 2014
-category:            Game
-build-type:          Simple
-data-files:
-  shaders/*.glsl
-  data/*.ttf
-cabal-version:       >=1.10
-
-flag BuildHelloWorld
-  default: False
-
-flag GLForwardCompat
-  default: True
-
-flag GLCoreProfile
-  default: True
-
-source-repository head
-  type: git
-  location: https://github.com/fumieval/call.git
-
-library
-  exposed-modules:
-    Call
-    Call.Types
-    Call.TH
-    Call.System
-    Call.Sight
-    Call.Internal.GLFW
-    Call.Internal.PortAudio
-    Call.Data.Wave
-    Call.Data.Font
-    Call.Data.Bitmap
-    Call.Util.Deck
-    Call.Util.Sampler
-    Call.Util.Text
-  other-modules:
-    Paths_call
-  ghc-options: -Wall -fexcess-precision -O2
-  other-extensions:    Rank2Types, DeriveFunctor, DeriveFoldable, DeriveTraversable, DeriveDataTypeable, TemplateHaskell, CPP, GeneralizedNewtypeDeriving, MultiParamTypeClasses, TypeSynonymInstances, ScopedTypeVariables, FlexibleInstances, FlexibleContexts, KindSignatures, TypeFamilies, BangPatterns, ViewPatterns, LambdaCase, DataKinds, GADTs
-  build-depends:
-    base >=4.5 && <5,
-    bindings-portaudio,
-    boundingboxes >=0.2 && <0.4,
-    clean-unions >= 0.1 && <0.3,
-    colors >=0.3 && <0.4,
-    containers >=0.5 && <0.7,
-    control-bool >=0.2 && <0.4,
-    directory,
-    distributive == 0.4.*,
-    elevator,
-    filepath,
-    freetype2 >=0.1 && <0.2,
-    GLFW-b >=1.3 && <2,
-    hashable >=1.2 && <1.3,
-    JuicyPixels == 3.*,
-    JuicyPixels-util >= 0.2 && <0.4,
-    lens >=4.0 && <5,
-    linear >=1.13 && <2,
-    mtl >=2.0 && <2.7,
-    objective >= 0.6.2 && <0.7,
-    OpenGL == 2.9.*,
-    OpenGLRaw >=1.4 && <1.7,
-    random ==1.*,
-    reflection >=1.4 && <1.7,
-    template-haskell == 2.*,
-    text >= 1.0 && <1.5,
-    transformers >=0.3 && <0.5,
-    vector >=0.9 && <0.13,
-    WAVE >=0.1 && <0.2,
-    minioperational >= 0.4.7 && <0.6,
-    deepseq
-  hs-source-dirs:      src
-  default-language:    Haskell2010
-
-executable hello-world
-  ghc-options: -threaded
-  main-is: examples/hello-world.hs
-  if flag(BuildHelloWorld)
-    buildable: True
-  else
-    buildable: False
-  build-depends: base == 4.*, call <= 0.2, lens == 4.*
-  default-language:    Haskell2010
+name:                call+version:             0.1.3+synopsis:            The call game engine+description:         Call is a minimalistic game engine that supports 2D/3D graphics and sounds.+homepage:            https://github.com/fumieval/call+license:             BSD3+license-file:        LICENSE+author:              Fumiaki Kinoshita+maintainer:          Fumiaki Kinoshita <fumiexcel@gmail.com>+copyright:           (c) Fumiaki Kinoshita 2014+category:            Game+build-type:          Simple+data-files:+  shaders/*.glsl+  data/*.ttf+cabal-version:       >=1.10++flag BuildHelloWorld+  default: False++flag GLForwardCompat+  default: True++flag GLCoreProfile+  default: True++source-repository head+  type: git+  location: https://github.com/fumieval/call.git++library+  exposed-modules:+    Call+    Call.Types+    Call.TH+    Call.System+    Call.Sight+    Call.Internal.GLFW+    Call.Internal.PortAudio+    Call.Data.Wave+    Call.Data.Font+    Call.Data.Bitmap+    Call.Util.Deck+    Call.Util.Sampler+    Call.Util.Text+  other-modules:+    Paths_call+  ghc-options: -Wall -fexcess-precision -O2 -optc-ffast-math+  other-extensions:    Rank2Types, DeriveFunctor, DeriveFoldable, DeriveTraversable, DeriveDataTypeable, TemplateHaskell, CPP, GeneralizedNewtypeDeriving, MultiParamTypeClasses, TypeSynonymInstances, ScopedTypeVariables, FlexibleInstances, FlexibleContexts, KindSignatures, TypeFamilies, BangPatterns, ViewPatterns, LambdaCase, DataKinds, GADTs+  build-depends:+    base >=4.5 && <5,+    bindings-portaudio,+    boundingboxes >=0.2 && <0.4,+    clean-unions >= 0.1 && <0.3,+    colors >=0.3 && <0.4,+    containers >=0.5 && <0.7,+    control-bool >=0.2 && <0.4,+    directory,+    distributive == 0.4.*,+    elevator >= 0.2 && <0.3,+    extensible >= 0.2.6 && <0.3,+    filepath,+    freetype2 >=0.1 && <0.2,+    GLFW-b >=1.3 && <2,+    hashable >=1.2 && <1.3,+    JuicyPixels == 3.*,+    JuicyPixels-util >= 0.2 && <0.4,+    lens >=4.0 && <5,+    linear >=1.13 && <2,+    mtl >=2.0 && <2.7,+    objective >= 0.6.5 && <0.7,+    OpenGL >= 2.9 && <2.12,+    OpenGLRaw >=1.4 && <1.7,+    random ==1.*,+    reflection >=1.4 && <1.7,+    template-haskell == 2.*,+    text >= 1.0 && <1.5,+    transformers >=0.3 && <0.5,+    vector >=0.9 && <0.13,+    WAVE >=0.1 && <0.2,+    minioperational >= 0.4.7 && <0.6,+    deepseq+  hs-source-dirs:      src+  default-language:    Haskell2010++executable hello-world+  ghc-options: -threaded+  main-is: examples/hello-world.hs+  if flag(BuildHelloWorld)+    buildable: True+  else+    buildable: False+  build-depends: base == 4.*, call <= 0.2, lens == 4.*+  default-language:    Haskell2010
examples/hello-world.hs view
@@ -37,4 +37,4 @@     _ -> return ()
   deck .- playing .= True
   stand
- +
shaders/fragment.glsl view
@@ -1,30 +1,30 @@-#version 330
-out vec4 fragColor;
-
-// Texture
-in vec2 UV;
-in vec2 envUV;
-
-in vec3 normal;
-in vec3 lightDir;
-
-uniform sampler2D env;
-uniform sampler2D tex;
-
-uniform vec4 diffuse;
-uniform float normalMix;
-uniform float textureMix;
-uniform float envAdd;
-uniform float envMul;
-
-void main(void){
-  // vec3 n = mix(normal, texture(normalMap, UV).rgb * 2 - 1, normalMix);
-
-  vec4 d = mix(vec4(1.0), texture(tex, UV).rgba, textureMix) * diffuse;
-
-  fragColor = vec4(d.rgb, d.a);
-
-  fragColor += texture(env, envUV).rgba * envAdd;
-  fragColor *= mix(vec4(1.0), texture(env, envUV).rgba, envMul);
-
-}
+#version 330+out vec4 fragColor;++// Texture+in vec2 UV;+in vec2 envUV;++in vec3 normal;+in vec3 lightDir;++uniform sampler2D env;+uniform sampler2D tex;++uniform vec4 diffuse;+uniform float normalMix;+uniform float textureMix;+uniform float envAdd;+uniform float envMul;++void main(void){+  // vec3 n = mix(normal, texture(normalMap, UV).rgb * 2 - 1, normalMix);++  vec4 d = mix(vec4(1.0), texture(tex, UV).rgba, textureMix) * diffuse;++  fragColor = vec4(d.rgb, d.a);++  fragColor += texture(env, envUV).rgba * envAdd;+  fragColor *= mix(vec4(1.0), texture(env, envUV).rgba, envMul);++}
src/Call.hs view
@@ -1,47 +1,47 @@-{-# LANGUAGE Rank2Types #-}
-module Call ( -- * System
-    runSystemDefault,
-    readBitmap,
-    module Call.Sight,
-    module Call.System,
-    module Call.Types,
-    module Call.TH,
-    module Call.Data.Wave,
-    module Call.Data.Font,
-    -- * Reexports
-    module Control.Monad,
-    module Control.Applicative,
-    module Control.Bool,
-    module Data.Monoid,
-    module Data.Color,
-    module Data.Color.Names,
-    module Linear,
-    module Control.Object,
-    module Control.Monad.Objective.Class,
-    module Control.Monad.IO.Class
-) where
-
-import Call.TH
-import Call.Types
-import Call.Data.Wave
-import Call.Data.Font
-import Call.Sight
-import Call.System
-import Control.Monad.IO.Class
-import Control.Monad
-import Control.Applicative
-import Control.Bool
-import Control.Object
-import Control.Monad.Objective.Class
-import Data.Color
-import Data.Color.Names
-import Data.Monoid
-import Linear
-import Data.BoundingBox
-import qualified Call.Data.Bitmap as Bitmap
-
-runSystemDefault :: (forall s. System s a) -> IO (Maybe a)
-runSystemDefault = runSystem Windowed (Box (V2 0 0) (V2 640 480))
-
-readBitmap :: MonadIO m => FilePath -> m Bitmap.Bitmap
-readBitmap = Bitmap.readFile
+{-# LANGUAGE Rank2Types #-}+module Call ( -- * System+    runSystemDefault,+    readBitmap,+    module Call.Sight,+    module Call.System,+    module Call.Types,+    module Call.TH,+    module Call.Data.Wave,+    module Call.Data.Font,+    -- * Reexports+    module Control.Monad,+    module Control.Applicative,+    module Control.Bool,+    module Data.Monoid,+    module Data.Color,+    module Data.Color.Names,+    module Linear,+    module Control.Object,+    module Control.Monad.Objective.Class,+    module Control.Monad.IO.Class+) where++import Call.TH+import Call.Types+import Call.Data.Wave+import Call.Data.Font+import Call.Sight+import Call.System+import Control.Monad.IO.Class+import Control.Monad+import Control.Applicative+import Control.Bool+import Control.Object hiding (invoke)+import Control.Monad.Objective.Class+import Data.Color+import Data.Color.Names+import Data.Monoid+import Linear+import Data.BoundingBox+import qualified Call.Data.Bitmap as Bitmap++runSystemDefault :: (forall s. System s a) -> IO (Maybe a)+runSystemDefault = runSystem Windowed (Box (V2 0 0) (V2 640 480))++readBitmap :: MonadIO m => FilePath -> m Bitmap.Bitmap+readBitmap = Bitmap.readFile
src/Call/Data/Bitmap.hs view
@@ -1,101 +1,101 @@-{-# LANGUAGE TemplateHaskell #-}
------------------------------------------------------------------------------
--- |
--- Module      :  Call.Data.Bitmap
--- Copyright   :  (c) Fumiaki Kinoshita 2014
--- License     :  BSD3
---
--- Maintainer  :  Fumiaki Kinoshita <fumiexcel@gmail.com>
--- Stability   :  experimental
--- Portability :  non-portable
---
------------------------------------------------------------------------------
-module Call.Data.Bitmap (
-  Bitmap(Blank, Bitmap)
-  ,image
-  ,offset
-  ,hash
-  ,liftImage
-  ,liftImage'
-  ,size
-  ,clip
-  ,bbox
-  ,readFile
-  ,writeFile
-  ) where
-import Prelude hiding (readFile, writeFile)
-import qualified Codec.Picture as C
-import qualified Codec.Picture.Types as C
-import qualified Codec.Picture.RGBA8 as C
-import Control.Monad.IO.Class
-import qualified Data.BoundingBox as B
-import Linear
-import System.Random
-import Control.Applicative
-import qualified Data.Hashable as H
-import qualified Data.Vector.Storable as V
-import Data.Monoid
-import Control.Lens
-import Control.Monad.ST
-
-data Bitmap = Blank | Bitmap { _image :: !(C.Image C.PixelRGBA8), _offset :: !(V2 Int), _hash :: !Int }
-
-image :: Traversal' Bitmap (C.Image C.PixelRGBA8)
-image _ Blank = pure Blank
-image f (Bitmap i o h) = f i <&> \i' -> Bitmap i' o h
-
-offset :: Traversal' Bitmap (V2 Int)
-offset _ Blank = pure Blank
-offset f (Bitmap i o h) = f o <&> \o' -> Bitmap i o' h
-
-hash :: Traversal' Bitmap Int
-hash _ Blank = pure Blank
-hash f (Bitmap i o h) = f h <&> \h' -> Bitmap i o h'
-
--- | `mappend` stitches the right operand to the left
-instance Monoid Bitmap where
-  mempty = Blank
-  mappend base@(Bitmap b (V2 x0 y0) h0) lay@(Bitmap l (V2 x1 y1) h1) = runST $ do
-    let box = B.union (bbox base) (bbox lay)
-    let V2 w h = box ^. B.size 0
-    img <- C.createMutableImage w h (C.PixelRGBA8 0 0 0 0) >>= C.unsafeFreezeImage
-    let ox = max 0 (x0 - x1)
-    let oy = max 0 (y0 - y1)
-    return $ Bitmap
-      (C.patchImage (C.patchImage img (ox, oy) b) (max 0 (x1 - x0), max 0 (y1 - y0)) l)
-      (V2 (x0 + ox) (y0 + oy))
-      (H.hash (h0, h1))
-  mappend Blank b = b
-  mappend b Blank = b
-
-clip :: Bitmap -> B.Box V2 Int -> Bitmap
-clip (Bitmap b (V2 ox oy) k) (B.Box (V2 x0 y0) (V2 x1 y1)) = Bitmap
-  (C.trimImage b (x1 - x0, y1 - y0) (x0 - ox, y0 - oy))
-  (V2 ox oy)
-  (H.hash (x0, y0, x1, y1, k))
-
-clip Blank _ = Blank
-
-bbox :: Bitmap -> B.Box V2 Int
-bbox (Bitmap (C.Image w h _) (V2 x y) _) = B.Box (V2 x y) (V2 (x+w) (y+h))
-bbox Blank = B.Box zero zero
-
-size :: Bitmap -> V2 Int
-size (Bitmap (C.Image w h _) _ _) = V2 w h
-size Blank = zero
-
-liftImage :: C.Image C.PixelRGBA8 -> Bitmap
-liftImage b@(C.Image _ _ r) = Bitmap b zero (V.foldl H.hashWithSalt 0 r)
-
-liftImage' :: MonadIO m => C.Image C.PixelRGBA8 -> m Bitmap
-liftImage' b = liftIO $ Bitmap b zero <$> randomIO
-
--- | Load an image file.
-readFile :: MonadIO m => FilePath -> m Bitmap
-readFile path = liftIO $ Bitmap <$> C.readImageRGBA8 path <*> pure zero <*> randomIO
-
--- | Save 'Bitmap' into a file.
-writeFile :: MonadIO m => FilePath -> Bitmap -> m ()
-writeFile path (Bitmap p _ _) = liftIO $ C.writePng path p
-writeFile _ Blank = fail "Blank bitmap"
-
+{-# LANGUAGE TemplateHaskell #-}+-----------------------------------------------------------------------------+-- |+-- Module      :  Call.Data.Bitmap+-- Copyright   :  (c) Fumiaki Kinoshita 2014+-- License     :  BSD3+--+-- Maintainer  :  Fumiaki Kinoshita <fumiexcel@gmail.com>+-- Stability   :  experimental+-- Portability :  non-portable+--+-----------------------------------------------------------------------------+module Call.Data.Bitmap (+  Bitmap(Blank, Bitmap)+  ,image+  ,offset+  ,hash+  ,liftImage+  ,liftImage'+  ,size+  ,clip+  ,bbox+  ,readFile+  ,writeFile+  ) where+import Prelude hiding (readFile, writeFile)+import qualified Codec.Picture as C+import qualified Codec.Picture.Types as C+import qualified Codec.Picture.RGBA8 as C+import Control.Monad.IO.Class+import qualified Data.BoundingBox as B+import Linear+import System.Random+import Control.Applicative+import qualified Data.Hashable as H+import qualified Data.Vector.Storable as V+import Data.Monoid+import Control.Lens+import Control.Monad.ST++data Bitmap = Blank | Bitmap { _image :: !(C.Image C.PixelRGBA8), _offset :: !(V2 Int), _hash :: !Int }++image :: Traversal' Bitmap (C.Image C.PixelRGBA8)+image _ Blank = pure Blank+image f (Bitmap i o h) = f i <&> \i' -> Bitmap i' o h++offset :: Traversal' Bitmap (V2 Int)+offset _ Blank = pure Blank+offset f (Bitmap i o h) = f o <&> \o' -> Bitmap i o' h++hash :: Traversal' Bitmap Int+hash _ Blank = pure Blank+hash f (Bitmap i o h) = f h <&> \h' -> Bitmap i o h'++-- | `mappend` stitches the right operand to the left+instance Monoid Bitmap where+  mempty = Blank+  mappend base@(Bitmap b (V2 x0 y0) h0) lay@(Bitmap l (V2 x1 y1) h1) = runST $ do+    let box = B.union (bbox base) (bbox lay)+    let V2 w h = box ^. B.size 0+    img <- C.createMutableImage w h (C.PixelRGBA8 0 0 0 0) >>= C.unsafeFreezeImage+    let ox = max 0 (x0 - x1)+    let oy = max 0 (y0 - y1)+    return $ Bitmap+      (C.patchImage (C.patchImage img (ox, oy) b) (max 0 (x1 - x0), max 0 (y1 - y0)) l)+      (V2 (x0 + ox) (y0 + oy))+      (H.hash (h0, h1))+  mappend Blank b = b+  mappend b Blank = b++clip :: Bitmap -> B.Box V2 Int -> Bitmap+clip (Bitmap b (V2 ox oy) k) (B.Box (V2 x0 y0) (V2 x1 y1)) = Bitmap+  (C.trimImage b (x1 - x0, y1 - y0) (x0 - ox, y0 - oy))+  (V2 ox oy)+  (H.hash (x0, y0, x1, y1, k))++clip Blank _ = Blank++bbox :: Bitmap -> B.Box V2 Int+bbox (Bitmap (C.Image w h _) (V2 x y) _) = B.Box (V2 x y) (V2 (x+w) (y+h))+bbox Blank = B.Box zero zero++size :: Bitmap -> V2 Int+size (Bitmap (C.Image w h _) _ _) = V2 w h+size Blank = zero++liftImage :: C.Image C.PixelRGBA8 -> Bitmap+liftImage b@(C.Image _ _ r) = Bitmap b zero (V.foldl H.hashWithSalt 0 r)++liftImage' :: MonadIO m => C.Image C.PixelRGBA8 -> m Bitmap+liftImage' b = liftIO $ Bitmap b zero <$> randomIO++-- | Load an image file.+readFile :: MonadIO m => FilePath -> m Bitmap+readFile path = liftIO $ Bitmap <$> C.readImageRGBA8 path <*> pure zero <*> randomIO++-- | Save 'Bitmap' into a file.+writeFile :: MonadIO m => FilePath -> Bitmap -> m ()+writeFile path (Bitmap p _ _) = liftIO $ C.writePng path p+writeFile _ Blank = fail "Blank bitmap"+
src/Call/Data/Font.hs view
@@ -1,120 +1,120 @@------------------------------------------------------------------------------
--- |
--- Module      :  Call.Data.Font
--- Copyright   :  (c) Fumiaki Kinoshita 2014
--- License     :  BSD3
---
--- Maintainer  :  Fumiaki Kinoshita <fumiexcel@gmail.com>
--- Stability   :  experimental
--- Portability :  non-portable
---
--- Font rendering
---
------------------------------------------------------------------------------
-module Call.Data.Font 
-  ( Font
-  , readFont
-  , defaultFont
-  , fontBoundingBox
-  , metricsAscent
-  , metricsDescent
-  , renderChar
-  ) where
-
-import Control.Applicative
-import Control.Monad.IO.Class
-import Control.Monad
-import Data.BoundingBox
-import qualified Data.Vector.Storable as V
-import Linear
-import Call.Data.Bitmap
-import Graphics.Rendering.FreeType.Internal
-import qualified Graphics.Rendering.FreeType.Internal.GlyphSlot as GS
-import qualified Graphics.Rendering.FreeType.Internal.Vector as V
-import Graphics.Rendering.FreeType.Internal.Bitmap as B
-import Graphics.Rendering.FreeType.Internal.PrimitiveTypes as PT
-import Graphics.Rendering.FreeType.Internal.Face as F
-import Graphics.Rendering.FreeType.Internal.Library as L
-import Graphics.Rendering.FreeType.Internal.BBox as BB
-import Foreign.Marshal.Alloc
-import Foreign.C.Types
-import Foreign.C.String
-import Foreign.Storable
-import Foreign.ForeignPtr
-import Foreign.Ptr
-import System.IO.Unsafe
-import Codec.Picture
-import Codec.Picture.RGBA8
-import Paths_call
-
--- | Font object
-data Font = Font FT_Face (Float, Float) (Box V2 Float)
-
-defaultFont :: Font
-defaultFont = unsafePerformIO $ do
-  path <- getDataFileName "data/VL-PGothic-Regular.ttf"
-  readFont path
-
--- | Create a 'Font' from the given file.
-readFont :: MonadIO m => FilePath -> m Font
-readFont path = liftIO $ alloca $ \p -> do
-    runFreeType $ withCString path $ \str -> ft_New_Face freeType str 0 p
-    f <- peek p
-    b <- peek (F.bbox f)
-    asc <- peek (ascender f)
-    desc <- peek (descender f)
-    u <- fromIntegral <$> peek (units_per_EM f)
-    let box = fmap ((/u).fromIntegral) $ Box
-            (V2 (xMin b) (yMin b))
-            (V2 (xMax b) (yMax b))
-    return $ Font f (fromIntegral asc/u, fromIntegral desc/u) box
-
--- | Get the font's metrics.
-metricsAscent :: Font -> Float
-metricsAscent (Font _ (a, _) _) = a
-
--- | Get the font's metrics.
-metricsDescent :: Font -> Float
-metricsDescent (Font _ (_, d) _) = d
-
--- | Get the font's bounding box.
-fontBoundingBox :: Font -> Box V2 Float
-fontBoundingBox (Font _ _ b) = b
-
-runFreeType :: IO CInt -> IO ()
-runFreeType m = do
-    r <- m
-    unless (r == 0) $ fail $ "FreeType Error:" Prelude.++ show r
-
-freeType :: FT_Library
-freeType = unsafePerformIO $ alloca $ \p -> do
-  runFreeType $ ft_Init_FreeType p
-  peek p
-
-renderChar :: Font -> Float -> Char -> IO (Bitmap, V2 Float, V2 Float)
-renderChar (Font face _ _) pixel ch = do
-  let dpi = 300
-
-  runFreeType $ ft_Set_Char_Size face 0 (floor $ pixel * 72 / fromIntegral dpi * 64) dpi dpi
-  
-  ix <- ft_Get_Char_Index face (fromIntegral $ fromEnum ch)
-  runFreeType $ ft_Load_Glyph face ix ft_LOAD_DEFAULT
-
-  slot <- peek $ glyph face
-  runFreeType $ ft_Render_Glyph slot ft_RENDER_MODE_NORMAL
-
-  bmp <- peek $ GS.bitmap slot
-  left <- fmap fromIntegral $ peek $ GS.bitmap_left slot
-  top <- fmap fromIntegral $ peek $ GS.bitmap_top slot
-
-  let h = fromIntegral $ B.rows bmp
-      w = fromIntegral $ B.width bmp
-  
-  fptr <- newForeignPtr_ $ castPtr $ buffer bmp
-
-  adv <- peek $ GS.advance slot
-  b <- liftImage' $ fromColorAndOpacity (PixelRGB8 255 255 255)
-        $ Image w h $ V.unsafeFromForeignPtr0 fptr $ h * w
-  return (b
-    , V2 (left + fromIntegral w / 2) (-top + fromIntegral h / 2)
-    , V2 (fromIntegral (V.x adv) / 64) 0)
+-----------------------------------------------------------------------------+-- |+-- Module      :  Call.Data.Font+-- Copyright   :  (c) Fumiaki Kinoshita 2014+-- License     :  BSD3+--+-- Maintainer  :  Fumiaki Kinoshita <fumiexcel@gmail.com>+-- Stability   :  experimental+-- Portability :  non-portable+--+-- Font rendering+--+-----------------------------------------------------------------------------+module Call.Data.Font +  ( Font+  , readFont+  , defaultFont+  , fontBoundingBox+  , metricsAscent+  , metricsDescent+  , renderChar+  ) where++import Control.Applicative+import Control.Monad.IO.Class+import Control.Monad+import Data.BoundingBox+import qualified Data.Vector.Storable as V+import Linear+import Call.Data.Bitmap+import Graphics.Rendering.FreeType.Internal+import qualified Graphics.Rendering.FreeType.Internal.GlyphSlot as GS+import qualified Graphics.Rendering.FreeType.Internal.Vector as V+import Graphics.Rendering.FreeType.Internal.Bitmap as B+import Graphics.Rendering.FreeType.Internal.PrimitiveTypes as PT+import Graphics.Rendering.FreeType.Internal.Face as F+import Graphics.Rendering.FreeType.Internal.Library as L+import Graphics.Rendering.FreeType.Internal.BBox as BB+import Foreign.Marshal.Alloc+import Foreign.C.Types+import Foreign.C.String+import Foreign.Storable+import Foreign.ForeignPtr+import Foreign.Ptr+import System.IO.Unsafe+import Codec.Picture+import Codec.Picture.RGBA8+import Paths_call++-- | Font object+data Font = Font FT_Face (Float, Float) (Box V2 Float)++defaultFont :: Font+defaultFont = unsafePerformIO $ do+  path <- getDataFileName "data/VL-PGothic-Regular.ttf"+  readFont path++-- | Create a 'Font' from the given file.+readFont :: MonadIO m => FilePath -> m Font+readFont path = liftIO $ alloca $ \p -> do+    runFreeType $ withCString path $ \str -> ft_New_Face freeType str 0 p+    f <- peek p+    b <- peek (F.bbox f)+    asc <- peek (ascender f)+    desc <- peek (descender f)+    u <- fromIntegral <$> peek (units_per_EM f)+    let box = fmap ((/u).fromIntegral) $ Box+            (V2 (xMin b) (yMin b))+            (V2 (xMax b) (yMax b))+    return $ Font f (fromIntegral asc/u, fromIntegral desc/u) box++-- | Get the font's metrics.+metricsAscent :: Font -> Float+metricsAscent (Font _ (a, _) _) = a++-- | Get the font's metrics.+metricsDescent :: Font -> Float+metricsDescent (Font _ (_, d) _) = d++-- | Get the font's bounding box.+fontBoundingBox :: Font -> Box V2 Float+fontBoundingBox (Font _ _ b) = b++runFreeType :: IO CInt -> IO ()+runFreeType m = do+    r <- m+    unless (r == 0) $ fail $ "FreeType Error:" Prelude.++ show r++freeType :: FT_Library+freeType = unsafePerformIO $ alloca $ \p -> do+  runFreeType $ ft_Init_FreeType p+  peek p++renderChar :: Font -> Float -> Char -> IO (Bitmap, V2 Float, V2 Float)+renderChar (Font face _ _) pixel ch = do+  let dpi = 300++  runFreeType $ ft_Set_Char_Size face 0 (floor $ pixel * 72 / fromIntegral dpi * 64) dpi dpi+  +  ix <- ft_Get_Char_Index face (fromIntegral $ fromEnum ch)+  runFreeType $ ft_Load_Glyph face ix ft_LOAD_DEFAULT++  slot <- peek $ glyph face+  runFreeType $ ft_Render_Glyph slot ft_RENDER_MODE_NORMAL++  bmp <- peek $ GS.bitmap slot+  left <- fmap fromIntegral $ peek $ GS.bitmap_left slot+  top <- fmap fromIntegral $ peek $ GS.bitmap_top slot++  let h = fromIntegral $ B.rows bmp+      w = fromIntegral $ B.width bmp+  +  fptr <- newForeignPtr_ $ castPtr $ buffer bmp++  adv <- peek $ GS.advance slot+  b <- liftImage' $ fromColorAndOpacity (PixelRGB8 255 255 255)+        $ Image w h $ V.unsafeFromForeignPtr0 fptr $ h * w+  return (b+    , V2 (left + fromIntegral w / 2) (-top + fromIntegral h / 2)+    , V2 (fromIntegral (V.x adv) / 64) 0)
src/Call/Data/Wave.hs view
@@ -1,45 +1,45 @@-{-# LANGUAGE BangPatterns #-}
------------------------------------------------------------------------------
--- |
--- Module      :  Call.Data.Wave
--- Copyright   :  (c) Fumiaki Kinoshita 2014
--- License     :  BSD3
---
--- Maintainer  :  Fumiaki Kinoshita <fumiexcel@gmail.com>
--- Stability   :  experimental
--- Portability :  non-portable
---
------------------------------------------------------------------------------
-module Call.Data.Wave (
-  Source(..),
-  Sample(..),
-  Stereo,
-  readWAVE
-) where
-
-import Data.WAVE
-import Linear
-import Call.Types
-import Control.Monad.IO.Class
-import qualified Data.Vector.Unboxed as V
-import GHC.Float
-
-newtype Source a = Source (Time -> a)
-
-readWAVE :: MonadIO m => FilePath -> m (Sample Stereo)
-readWAVE path = liftIO $ do
-  WAVE h ss <- getWAVEFile path
-  let vec = V.fromList (map fr ss)
-      rate = fromIntegral (waveFrameRate h)
-      !dur = fromIntegral (V.length vec) / rate
-      sample t
-        | t < 0 || t >= dur - (1/rate) = zero
-        | otherwise = vec V.! round (t * rate)
-  return $ Sample dur (Source sample)
-  where
-    fr [a, b] = V2 (double2Float $ sampleToDouble a) (double2Float $ sampleToDouble b)
-    fr _ = zero
-
-data Sample a = Sample { sampleLength :: Time ,sampleSource :: Source a}
-
--- TODO: Lazy processing
+{-# LANGUAGE BangPatterns #-}+-----------------------------------------------------------------------------+-- |+-- Module      :  Call.Data.Wave+-- Copyright   :  (c) Fumiaki Kinoshita 2014+-- License     :  BSD3+--+-- Maintainer  :  Fumiaki Kinoshita <fumiexcel@gmail.com>+-- Stability   :  experimental+-- Portability :  non-portable+--+-----------------------------------------------------------------------------+module Call.Data.Wave (+  Source(..),+  Sample(..),+  Stereo,+  readWAVE+) where++import Data.WAVE+import Linear+import Call.Types+import Control.Monad.IO.Class+import qualified Data.Vector.Unboxed as V+import GHC.Float++newtype Source a = Source (Time -> a)++readWAVE :: MonadIO m => FilePath -> m (Sample Stereo)+readWAVE path = liftIO $ do+  WAVE h ss <- getWAVEFile path+  let vec = V.fromList (map fr ss)+      rate = fromIntegral (waveFrameRate h)+      !dur = fromIntegral (V.length vec) / rate+      sample t+        | t < 0 || t >= dur - (1/rate) = zero+        | otherwise = vec V.! round (t * rate)+  return $ Sample dur (Source sample)+  where+    fr [a, b] = V2 (double2Float $ sampleToDouble a) (double2Float $ sampleToDouble b)+    fr _ = zero++data Sample a = Sample { sampleLength :: Time ,sampleSource :: Source a}++-- TODO: Lazy processing
src/Call/Internal/GLFW.hs view
@@ -1,227 +1,226 @@-{-# LANGUAGE BangPatterns #-}
------------------------------------------------------------------------------
--- |
--- Module      :  Call.Internal.GLFW
--- Copyright   :  (c) Fumiaki Kinoshita 2014
--- License     :  BSD3
---
--- Maintainer  :  Fumiaki Kinoshita <fumiexcel@gmail.com>
--- Stability   :  experimental
--- Portability :  non-portable
---
------------------------------------------------------------------------------
-module Call.Internal.GLFW where
-import Control.Bool
-import Control.Applicative
-import Control.Lens
-import Data.IORef
-import Call.Types
-import Data.BoundingBox
-import Control.Monad
-import Graphics.Rendering.OpenGL.GL.StateVar
-import Linear
-import qualified Graphics.Rendering.OpenGL.Raw as GL
-import qualified Graphics.Rendering.OpenGL.GL as GL
-import qualified Graphics.UI.GLFW as GLFW
-import Unsafe.Coerce
-import qualified Data.Vector.Storable as V
-import qualified Data.Vector.Storable.Mutable as MV
-import Codec.Picture
-import Codec.Picture.RGBA8
-import qualified GHC.IO.Encoding as Encoding
-import qualified Data.Text.IO as Text
-import qualified Data.Text.Encoding as Text
-import Foreign.C (CFloat)
-import Foreign (nullPtr, plusPtr, sizeOf)
-import Paths_call
-data System = System
-  { refRegion :: IORef (Box V2 Float)
-  , theWindow :: GLFW.Window
-  , theProgram :: GL.Program
-  }
-
-type Texture = (GL.TextureObject, Double, Double)
-
-gf :: Float -> GL.GLfloat
-{-# INLINE gf #-}
-gf = unsafeCoerce
-
-gsizei :: Int -> GL.GLsizei
-{-# INLINE gsizei #-}
-gsizei = unsafeCoerce
-
-installTexture :: Image PixelRGBA8 -> IO Texture
-installTexture (Image w h v) = do
-  [tex] <- GL.genObjectNames 1
-  GL.textureBinding GL.Texture2D GL.$= Just tex
-  let siz = GL.TextureSize2D (gsizei w) (gsizei h)
-  V.unsafeWith v
-    $ GL.texImage2D GL.Texture2D GL.NoProxy 0 GL.RGBA8 siz 0
-    . GL.PixelData GL.ABGR GL.UnsignedInt8888
-  return (tex, fromIntegral w / 2, fromIntegral h / 2)
-
-releaseTexture :: Texture -> IO ()
-releaseTexture (tex, _, _) = GL.deleteObjectNames [tex]
-
-beginFrame :: System -> IO ()
-beginFrame _ = do
-  GL.clear [GL.ColorBuffer, GL.DepthBuffer]
-
-endFrame :: System -> IO Bool
-endFrame sys = do
-  GLFW.swapBuffers $ theWindow sys
-  GLFW.pollEvents
-  GLFW.windowShouldClose (theWindow sys)
-
-beginGLFW :: WindowMode -> Box V2 Float -> IO System
-beginGLFW mode bbox@(Box (V2 x0 y0) (V2 x1 y1)) = do
-  Encoding.setForeignEncoding Encoding.utf8
-  let title = "call"
-      ww = floor $ x1 - x0
-      wh = floor $ y1 - y0
-  () <- unlessM GLFW.init (fail "Failed to initialize")
-
-  mon <- case mode of
-    FullScreen -> GLFW.getPrimaryMonitor
-    _ -> return Nothing
-
-  GLFW.windowHint $ GLFW.WindowHint'ContextVersionMajor 3
-  GLFW.windowHint $ GLFW.WindowHint'ContextVersionMinor 3
-  GLFW.windowHint $ GLFW.WindowHint'OpenGLProfile GLFW.OpenGLProfile'Core
-  GLFW.windowHint $ GLFW.WindowHint'OpenGLForwardCompat True
-
-  GLFW.windowHint $ GLFW.WindowHint'Resizable $ mode == Resizable
-  win <- GLFW.createWindow ww wh title mon Nothing >>= maybe (fail "Failed to create a window") return
-  GLFW.makeContextCurrent (Just win)
-  prog <- initializeGL
-
-  GLFW.swapInterval 1
-  -- GL.clearColor $= GL.Color4 1 1 1 1
-
-  (fw, fh) <- GLFW.getFramebufferSize win
-
-  rbox <- newIORef $ bbox & size zero .~ fmap fromIntegral (V2 fw fh)
-
-  GLFW.setFramebufferSizeCallback win $ Just $ \_ w h -> do
-      modifyIORef rbox $ size zero .~ fmap fromIntegral (V2 w h)
-
-  return $ System rbox win prog
-
-compileShader :: FilePath -> GL.Shader -> IO ()
-compileShader path shader = do
-  src <- getDataFileName path >>= Text.readFile
-  GL.shaderSourceBS shader $= Text.encodeUtf8 src
-  GL.compileShader shader
-  GL.get (GL.shaderInfoLog shader) >>= putStrLn
-
-initializeGL :: IO GL.Program
-initializeGL = do
-  let vertexAttribute = GL.AttribLocation 0
-  let uvAttribute = GL.AttribLocation 1
-  let normalAttribute = GL.AttribLocation 2
-
-  cubeVao <- GL.genObjectName
-  cubeVbo <- GL.genObjectName
-
-  GL.bindVertexArrayObject $= Just cubeVao
-  GL.bindBuffer GL.ArrayBuffer $= Just cubeVbo
-
-  let stride = fromIntegral $ sizeOf (undefined :: Vertex)
-
-  GL.vertexAttribPointer vertexAttribute $=
-    (GL.ToFloat,GL.VertexArrayDescriptor 3 GL.Float stride nullPtr)
-
-  GL.vertexAttribArray vertexAttribute $= GL.Enabled
-  GL.bindBuffer GL.ArrayBuffer $= Just cubeVbo
-
-  GL.vertexAttribPointer uvAttribute $=
-    (GL.ToFloat
-    ,GL.VertexArrayDescriptor 2 GL.Float stride (nullPtr `plusPtr` sizeOf (0 :: V3 CFloat)))
-  GL.vertexAttribArray uvAttribute $= GL.Enabled
-
-  GL.vertexAttribPointer normalAttribute $=
-    (GL.ToFloat
-    ,GL.VertexArrayDescriptor 3 GL.Float stride
-      (nullPtr `plusPtr` sizeOf (0 :: V3 CFloat) `plusPtr` sizeOf (0 :: V2 CFloat)))
-  GL.vertexAttribArray normalAttribute $= GL.Enabled
-
-  vertexShader <- GL.createShader GL.VertexShader
-  fragmentShader <- GL.createShader GL.FragmentShader
-  compileShader "shaders/vertex.glsl" vertexShader
-  compileShader "shaders/fragment.glsl" fragmentShader
-  shaderProg <- GL.createProgram
-  GL.attachShader shaderProg vertexShader
-  GL.attachShader shaderProg fragmentShader
-  GL.attribLocation shaderProg "in_Position" $= vertexAttribute
-  GL.attribLocation shaderProg "in_UV" $= uvAttribute
-  GL.attribLocation shaderProg "in_Normal" $= normalAttribute
-  GL.linkProgram shaderProg
-  GL.currentProgram $= Just shaderProg
-
-  -- GL.blend $= GL.Disabled
-  GL.depthMask $= GL.Enabled
-  GL.depthFunc $= Just GL.Lequal
-  GL.colorMask $= GL.Color4 GL.Enabled GL.Enabled GL.Enabled GL.Enabled
-  {-
-  GL.depthMask $= GL.Disabled
-  GL.depthFunc $= Nothing
-
-  GL.colorMask $= GL.Color4 GL.Enabled GL.Enabled GL.Enabled GL.Enabled
-  -}
-  -- GL.cullFace $= GL.Back
-  GL.blend      $= GL.Enabled
-  GL.blendFunc  $= (GL.SrcAlpha, GL.OneMinusSrcAlpha)
-  linked <- GL.get (GL.linkStatus shaderProg)
-  unless linked $ do
-    GL.get (GL.programInfoLog shaderProg) >>= putStrLn
-
-  GL.lineSmooth $= GL.Enabled
-  GL.textureFunction $= GL.Combine
-  GL.clearColor $= GL.Color4 1 1 1 1
-  GL.UniformLocation loc0 <- GL.get $ GL.uniformLocation shaderProg "useEnv"
-  GL.glUniform1i loc0 0
-  GL.UniformLocation loc1 <- GL.get $ GL.uniformLocation shaderProg "tex"
-  GL.glUniform1i loc1 0
-  GL.UniformLocation loc2 <- GL.get $ GL.uniformLocation shaderProg "env"
-  GL.glUniform1i loc2 1
-  GL.UniformLocation loc3 <- GL.get $ GL.uniformLocation shaderProg "envAdd"
-  GL.glUniform1f loc3 0
-  GL.UniformLocation loc4 <- GL.get $ GL.uniformLocation shaderProg "envMul"
-  GL.glUniform1f loc4 0
-
-  GL.glPixelStorei GL.gl_UNPACK_ALIGNMENT 4
-  return shaderProg
-
-endGLFW :: System -> IO ()
-endGLFW sys = do
-  GLFW.destroyWindow (theWindow sys)
-  GLFW.terminate
-
-screenshotFlipped :: System -> IO (Image PixelRGBA8)
-screenshotFlipped sys = do
-  V2 w h <- fmap floor <$> view (size zero) <$> readIORef (refRegion sys)
-  mv <- MV.unsafeNew (w * h * 4)
-  GL.readBuffer $= GL.FrontBuffers
-  MV.unsafeWith mv
-      $ \ptr -> GL.readPixels (GL.Position 0 0) (GL.Size (gsizei w) (gsizei h))
-          (GL.PixelData GL.RGBA GL.UnsignedByte ptr)
-
-  Image w h <$> V.unsafeFreeze mv
-
-screenshot :: System -> IO (Image PixelRGBA8)
-screenshot sys = flipVertically <$> screenshotFlipped sys
-
-blendMode2BlendingFactors :: BlendMode -> (GL.BlendingFactor, GL.BlendingFactor)
-blendMode2BlendingFactors Normal = (GL.SrcAlpha, GL.OneMinusSrcAlpha)
-blendMode2BlendingFactors Inverse = (GL.OneMinusDstColor, GL.Zero)
-blendMode2BlendingFactors Add = (GL.SrcAlpha, GL.One)
-blendMode2BlendingFactors Multiply = (GL.Zero, GL.SrcColor)
-blendMode2BlendingFactors Screen = (GL.One, GL.OneMinusSrcColor)
-
-blendMode :: BlendMode -> IO a -> IO a
-blendMode mode m = do
-  oldFunc <- get GL.blendFunc
-  GL.blendFunc $= blendMode2BlendingFactors mode
-  a <- m
-  GL.blendFunc $= oldFunc
-  return a
+{-# LANGUAGE BangPatterns #-}+-----------------------------------------------------------------------------+-- |+-- Module      :  Call.Internal.GLFW+-- Copyright   :  (c) Fumiaki Kinoshita 2014+-- License     :  BSD3+--+-- Maintainer  :  Fumiaki Kinoshita <fumiexcel@gmail.com>+-- Stability   :  experimental+-- Portability :  non-portable+--+-----------------------------------------------------------------------------+module Call.Internal.GLFW where+import Control.Bool+import Control.Applicative+import Control.Lens+import Data.IORef+import Call.Types+import Data.BoundingBox+import Control.Monad+import Graphics.Rendering.OpenGL.GL.StateVar+import Linear+import qualified Graphics.Rendering.OpenGL.Raw as GL+import qualified Graphics.Rendering.OpenGL.GL as GL+import qualified Graphics.UI.GLFW as GLFW+import Unsafe.Coerce+import qualified Data.Vector.Storable as V+import qualified Data.Vector.Storable.Mutable as MV+import Codec.Picture+import Codec.Picture.RGBA8+import qualified GHC.IO.Encoding as Encoding+import qualified Data.Text.IO as Text+import qualified Data.Text.Encoding as Text+import Foreign.C (CFloat)+import Foreign (nullPtr, plusPtr, sizeOf)+import Paths_call+data System = System+  { refRegion :: IORef (Box V2 Float)+  , theWindow :: GLFW.Window+  , theProgram :: GL.Program+  }++type Texture = (GL.TextureObject, Double, Double)++gf :: Float -> GL.GLfloat+{-# INLINE gf #-}+gf = unsafeCoerce++gsizei :: Int -> GL.GLsizei+{-# INLINE gsizei #-}+gsizei = unsafeCoerce++installTexture :: Image PixelRGBA8 -> IO Texture+installTexture (Image w h v) = do+  [tex] <- GL.genObjectNames 1+  GL.textureBinding GL.Texture2D GL.$= Just tex+  let siz = GL.TextureSize2D (gsizei w) (gsizei h)+  V.unsafeWith v+    $ GL.texImage2D GL.Texture2D GL.NoProxy 0 GL.RGBA8 siz 0+    . GL.PixelData GL.ABGR GL.UnsignedInt8888+  return (tex, fromIntegral w / 2, fromIntegral h / 2)++releaseTexture :: Texture -> IO ()+releaseTexture (tex, _, _) = GL.deleteObjectNames [tex]++beginFrame :: System -> IO ()+beginFrame _ = do+  GL.clear [GL.ColorBuffer, GL.DepthBuffer]++endFrame :: System -> IO Bool+endFrame sys = do+  GLFW.swapBuffers $ theWindow sys+  GLFW.pollEvents+  GLFW.windowShouldClose (theWindow sys)++beginGLFW :: WindowMode -> Box V2 Float -> IO System+beginGLFW mode bbox@(Box (V2 x0 y0) (V2 x1 y1)) = do+  Encoding.setForeignEncoding Encoding.utf8+  let title = "call"+      ww = floor $ x1 - x0+      wh = floor $ y1 - y0+  () <- unlessM GLFW.init (fail "Failed to initialize")++  mon <- case mode of+    FullScreen -> GLFW.getPrimaryMonitor+    _ -> return Nothing++  GLFW.windowHint $ GLFW.WindowHint'ContextVersionMajor 3+  GLFW.windowHint $ GLFW.WindowHint'ContextVersionMinor 3+  GLFW.windowHint $ GLFW.WindowHint'OpenGLProfile GLFW.OpenGLProfile'Core+  GLFW.windowHint $ GLFW.WindowHint'OpenGLForwardCompat True++  GLFW.windowHint $ GLFW.WindowHint'Resizable $ mode == Resizable+  win <- GLFW.createWindow ww wh title mon Nothing >>= maybe (fail "Failed to create a window") return+  GLFW.makeContextCurrent (Just win)+  prog <- initializeGL++  GLFW.swapInterval 1+  -- GL.clearColor $= GL.Color4 1 1 1 1++  (fw, fh) <- GLFW.getFramebufferSize win++  rbox <- newIORef $ bbox & size zero .~ fmap fromIntegral (V2 fw fh)++  GLFW.setFramebufferSizeCallback win $ Just $ \_ w h -> do+      modifyIORef rbox $ size zero .~ fmap fromIntegral (V2 w h)++  return $ System rbox win prog++compileShader :: FilePath -> GL.Shader -> IO ()+compileShader path shader = do+  src <- getDataFileName path >>= Text.readFile+  GL.shaderSourceBS shader $= Text.encodeUtf8 src+  GL.compileShader shader+  GL.get (GL.shaderInfoLog shader) >>= putStrLn++initializeGL :: IO GL.Program+initializeGL = do+  let vertexAttribute = GL.AttribLocation 0+  let uvAttribute = GL.AttribLocation 1+  let normalAttribute = GL.AttribLocation 2++  cubeVao <- GL.genObjectName+  cubeVbo <- GL.genObjectName++  GL.bindVertexArrayObject $= Just cubeVao+  GL.bindBuffer GL.ArrayBuffer $= Just cubeVbo++  let stride = fromIntegral $ sizeOf (undefined :: Vertex)++  GL.vertexAttribPointer vertexAttribute $=+    (GL.ToFloat,GL.VertexArrayDescriptor 3 GL.Float stride nullPtr)++  GL.vertexAttribArray vertexAttribute $= GL.Enabled+  GL.bindBuffer GL.ArrayBuffer $= Just cubeVbo++  GL.vertexAttribPointer uvAttribute $=+    (GL.ToFloat+    ,GL.VertexArrayDescriptor 2 GL.Float stride (nullPtr `plusPtr` sizeOf (0 :: V3 CFloat)))+  GL.vertexAttribArray uvAttribute $= GL.Enabled++  GL.vertexAttribPointer normalAttribute $=+    (GL.ToFloat+    ,GL.VertexArrayDescriptor 3 GL.Float stride+      (nullPtr `plusPtr` sizeOf (0 :: V3 CFloat) `plusPtr` sizeOf (0 :: V2 CFloat)))+  GL.vertexAttribArray normalAttribute $= GL.Enabled++  vertexShader <- GL.createShader GL.VertexShader+  fragmentShader <- GL.createShader GL.FragmentShader+  compileShader "shaders/vertex.glsl" vertexShader+  compileShader "shaders/fragment.glsl" fragmentShader+  shaderProg <- GL.createProgram+  GL.attachShader shaderProg vertexShader+  GL.attachShader shaderProg fragmentShader+  GL.attribLocation shaderProg "in_Position" $= vertexAttribute+  GL.attribLocation shaderProg "in_UV" $= uvAttribute+  GL.attribLocation shaderProg "in_Normal" $= normalAttribute+  GL.linkProgram shaderProg+  GL.currentProgram $= Just shaderProg++  -- GL.blend $= GL.Disabled+  GL.depthMask $= GL.Enabled+  GL.depthFunc $= Just GL.Lequal+  GL.colorMask $= GL.Color4 GL.Enabled GL.Enabled GL.Enabled GL.Enabled+  {-+  GL.depthMask $= GL.Disabled+  GL.depthFunc $= Nothing++  GL.colorMask $= GL.Color4 GL.Enabled GL.Enabled GL.Enabled GL.Enabled+  -}+  -- GL.cullFace $= GL.Back+  GL.blend      $= GL.Enabled+  GL.blendFunc  $= (GL.SrcAlpha, GL.OneMinusSrcAlpha)+  linked <- GL.get (GL.linkStatus shaderProg)+  unless linked $ do+    GL.get (GL.programInfoLog shaderProg) >>= putStrLn++  GL.lineSmooth $= GL.Enabled+  GL.textureFunction $= GL.Combine+  GL.clearColor $= GL.Color4 1 1 1 1+  GL.UniformLocation loc0 <- GL.get $ GL.uniformLocation shaderProg "useEnv"+  GL.glUniform1i loc0 0+  GL.UniformLocation loc1 <- GL.get $ GL.uniformLocation shaderProg "tex"+  GL.glUniform1i loc1 0+  GL.UniformLocation loc2 <- GL.get $ GL.uniformLocation shaderProg "env"+  GL.glUniform1i loc2 1+  GL.UniformLocation loc3 <- GL.get $ GL.uniformLocation shaderProg "envAdd"+  GL.glUniform1f loc3 0+  GL.UniformLocation loc4 <- GL.get $ GL.uniformLocation shaderProg "envMul"+  GL.glUniform1f loc4 0++  return shaderProg++endGLFW :: System -> IO ()+endGLFW sys = do+  GLFW.destroyWindow (theWindow sys)+  GLFW.terminate++screenshotFlipped :: System -> IO (Image PixelRGBA8)+screenshotFlipped sys = do+  V2 w h <- fmap floor <$> view (size zero) <$> readIORef (refRegion sys)+  mv <- MV.unsafeNew (w * h * 4)+  GL.readBuffer $= GL.FrontBuffers+  MV.unsafeWith mv+      $ \ptr -> GL.readPixels (GL.Position 0 0) (GL.Size (gsizei w) (gsizei h))+          (GL.PixelData GL.RGBA GL.UnsignedByte ptr)++  Image w h <$> V.unsafeFreeze mv++screenshot :: System -> IO (Image PixelRGBA8)+screenshot sys = flipVertically <$> screenshotFlipped sys++blendMode2BlendingFactors :: BlendMode -> (GL.BlendingFactor, GL.BlendingFactor)+blendMode2BlendingFactors Normal = (GL.SrcAlpha, GL.OneMinusSrcAlpha)+blendMode2BlendingFactors Inverse = (GL.OneMinusDstColor, GL.Zero)+blendMode2BlendingFactors Add = (GL.SrcAlpha, GL.One)+blendMode2BlendingFactors Multiply = (GL.Zero, GL.SrcColor)+blendMode2BlendingFactors Screen = (GL.One, GL.OneMinusSrcColor)++blendMode :: BlendMode -> IO a -> IO a+blendMode mode m = do+  oldFunc <- get GL.blendFunc+  GL.blendFunc $= blendMode2BlendingFactors mode+  a <- m+  GL.blendFunc $= oldFunc+  return a
src/Call/Internal/PortAudio.hs view
@@ -69,7 +69,7 @@ with rate buf f m = do
   w c'Pa_Initialize
   cb <- liftIO $ mk'PaStreamCallback $ callback f
-  
+
   ps <- liftIO malloc
   w $ c'Pa_OpenDefaultStream ps
       0
src/Call/Sight.hs view
@@ -1,183 +1,183 @@-{-# LANGUAGE TypeFamilies
-  , FlexibleContexts
-  , BangPatterns
-  , DeriveFunctor
-  , Rank2Types
-  , FlexibleInstances
-  , UndecidableInstances
-  , ViewPatterns
-  , ScopedTypeVariables
-  , GeneralizedNewtypeDeriving #-}
------------------------------------------------------------------------------
--- |
--- Module      :  Call.Scene
--- Copyright   :  (c) Fumiaki Kinoshita 2014
--- License     :  BSD3
---
--- Maintainer  :  Fumiaki Kinoshita <fumiexcel@gmail.com>
--- Stability   :  experimental
--- Portability :  non-portable
---
------------------------------------------------------------------------------
-module Call.Sight (Affine(..)
-    , Figure(..)
-    , Picture(..)
-    , opacity
-    , bitmap
-    , toward
-    , Scene(..)
-    , transformScene
-    , vertices
-    , Sight(..)
-    , viewPicture
-    , viewScene
-    , fromPerspective
-    , VFX(..)
-    , applyVFX
-    , GL.PrimitiveMode(..)
-    ) where
-import qualified Call.Data.Bitmap as B
-import qualified Data.BoundingBox as X
-import Data.Monoid
-import Linear
-import qualified Data.Vector.Storable as V
-import Control.Lens
-import qualified Graphics.Rendering.OpenGL.GL as GL
-import Data.Color
-import Call.Types
-
-class Affine a where
-  type Vec a :: *
-  type Normal a :: *
-  rotateOn :: Normal a -> a -> a
-  scale :: Vec a -> a -> a
-  translate :: Vec a -> a -> a
-
-class Affine a => Figure a where
-  primitive :: GL.PrimitiveMode -> [Vec a] -> a
-  color :: RGBA Float -> a -> a
-  line :: [Vec a] -> a
-  polygon :: [Vec a] -> a
-  polygonOutline :: [Vec a] -> a
-  circle :: Normal a -> a
-  circleOutline :: Normal a -> a
-
-opacity :: Figure a => Float -> a -> a
-opacity p = color (V4 1 1 1 p)
-
-bitmap :: B.Bitmap -> Picture
-bitmap bmp = Picture $ Scene
-  $ \_ _ f _ _ -> f bmp GL.TriangleStrip
-    (V.fromList [V3 (-w/2) (-h/2) 0 `positionUV` V2 0 0
-        , V3 (w/2) (-h/2) 0 `positionUV` V2 1 0
-        , V3 (-w/2) (h/2) 0 `positionUV` V2 0 1
-        , V3 (w/2) (h/2) 0 `positionUV` V2 1 1]) where
-  V2 w h = fmap fromIntegral $ B.size bmp
-
-toward :: Vec3 -> Picture -> Scene
-toward n@((^/norm n) -> V3 x y z) (Picture s) = transformScene
-  (m33_to_m44 $ fromQuaternion $ axisAngle (V3 (-y) x 0) $ acos $ z / norm n)
-  s
-
-newtype Scene = Scene { unScene :: forall r.
-  r
-  -> (r -> r -> r)
-  -> (B.Bitmap -> GL.PrimitiveMode -> V.Vector Vertex -> r)
-  -> (VFX r -> r)
-  -> (M44 Float -> r -> r)
-  -> r
-  }
-
-data VFX r = SphericalAdd Bitmap r
-  | SphericalMultiply Bitmap r
-  | Diffuse (V4 Float) r
---  | Specular (V3 Float) r
---  | Ambient (V3 Float) r
---  | NormalMap Bitmap r
-  | EmbedIO (IO r)
-  deriving Functor
-
-instance Affine Scene where
-  type Vec Scene = V3 Float
-  type Normal Scene = V3 Float
-  rotateOn v = transformScene $ m33_to_m44 $ fromQuaternion $ axisAngle v (norm v)
-  scale (V3 x y z) = transformScene $ V4
-    (V4 x 0 0 0)
-    (V4 0 y 0 0)
-    (V4 0 0 z 0)
-    (V4 0 0 0 1)
-  translate v = transformScene $ translation .~ v $ eye4
-
-instance Figure Scene where
-  primitive m vs = Scene $ \_ _ f _ _ -> f Blank m (V.fromList $ map positionOnly vs)
-  color col (Scene s) = Scene $ \e a f b t -> b (Diffuse col (s e a f b t))
-  line = primitive GL.LineStrip
-  polygon = primitive GL.TriangleFan
-  polygonOutline = primitive GL.LineLoop
-  circle v = toward v $ circle $ norm v
-  circleOutline v = toward v $ circleOutline $ norm v
-
-unit_circle :: Int -> [V2 Float]
-unit_circle n = map angle [0,2*pi/fromIntegral n..2*pi]
-
-instance Monoid Scene where
-  mempty = Scene $ \e _ _ _ _ -> e
-  mappend (Scene x) (Scene y) = Scene $ \e a f b t -> a (x e a f b t) (y e a f b t)
-
-v2ToV3 :: Num a => V2 a -> V3 a
-v2ToV3 (V2 x y) = V3 x y 0
-
-vertices :: B.Bitmap -> GL.PrimitiveMode -> V.Vector Vertex -> Scene
-vertices b m v = Scene $ \_ _ f _ _ -> f b m v
-
-transformScene :: M44 Float -> Scene -> Scene
-transformScene m (Scene pic) = Scene $ \e a f b t -> t m (pic e a f b t)
-
-applyVFX :: VFX Scene -> Scene
-applyVFX vf = Scene $ \e a f b t -> b $ fmap (\(Scene s) -> s e a f b t) vf
-
-newtype Picture = Picture { unPicture :: Scene } deriving Monoid
-
-instance Affine Picture where
-  type Vec Picture = V2 Float
-  type Normal Picture = Float
-  rotateOn t (Picture s) = Picture (transformScene m s) where
-    m = V4 (V4 (cos t) (-sin t) 0 0) (V4 (sin t) (cos t) 0 0) (V4 0 0 1 0) (V4 0 0 0 1)
-  translate (V2 x y) (Picture s) = Picture $ transformScene (translation .~ V3 x y 0 $ eye4) s
-  scale (V2 x y) (Picture s) = Picture (transformScene m s) where
-    m = V4 (V4 x 0 0 0) (V4 0 y 0 0) (V4 0 0 1 0) (V4 0 0 0 1)
-
-instance Figure Picture where
-  primitive m v = Picture $ primitive m $ map v2ToV3 v
-  color col (Picture s) = Picture (color col s)
-  line = primitive GL.LineStrip
-  polygon = primitive GL.TriangleFan
-  polygonOutline = primitive GL.LineLoop
-  circle r = polygon $ map (^*r) $ unit_circle 33
-  circleOutline r = polygonOutline $ map (^*r) $ unit_circle 33
-
-newtype Sight = Sight { unSight
-  :: forall r.
-  X.Box V2 Float
-  -> r
-  -> (r -> r -> r)
-  -> (X.Box V2 Float -> M44 Float -> Bool -> Scene -> r)
-  -> r
-  }
-
-instance Monoid Sight where
-  mempty = Sight $ \_ e _ _ -> e
-  mappend (Sight x) (Sight y) = Sight $ \b e a f -> a (x b e a f) (y b e a f)
-
-viewPicture :: Picture -> Sight
-viewPicture (Picture s) = Sight $ \box@(X.Box (V2 x0 y0) (V2 x1 y1)) _ _ f -> f box (ortho x0 x1 y1 y0 (-1) 1) False s
-
-viewScene :: Float -- ^ FOV
-  -> Float -- ^ Near plane
-  -> Float -- ^ Far plane
-  -> Scene -- ^ The scene
-  -> Sight
-viewScene fov near far = fromPerspective $ \box -> perspective fov (let V2 w h = box ^. X.size 0 in w/h) near far
-
-fromPerspective :: (X.Box V2 Float -> M44 Float) -> Scene -> Sight
-fromPerspective mat s = Sight $ \box _ _ f -> f box (mat box) True s
+{-# LANGUAGE TypeFamilies+  , FlexibleContexts+  , BangPatterns+  , DeriveFunctor+  , Rank2Types+  , FlexibleInstances+  , UndecidableInstances+  , ViewPatterns+  , ScopedTypeVariables+  , GeneralizedNewtypeDeriving #-}+-----------------------------------------------------------------------------+-- |+-- Module      :  Call.Scene+-- Copyright   :  (c) Fumiaki Kinoshita 2014+-- License     :  BSD3+--+-- Maintainer  :  Fumiaki Kinoshita <fumiexcel@gmail.com>+-- Stability   :  experimental+-- Portability :  non-portable+--+-----------------------------------------------------------------------------+module Call.Sight (Affine(..)+    , Figure(..)+    , Picture(..)+    , opacity+    , bitmap+    , toward+    , Scene(..)+    , transformScene+    , vertices+    , Sight(..)+    , viewPicture+    , viewScene+    , fromPerspective+    , VFX(..)+    , applyVFX+    , GL.PrimitiveMode(..)+    ) where+import qualified Call.Data.Bitmap as B+import qualified Data.BoundingBox as X+import Data.Monoid+import Linear+import qualified Data.Vector.Storable as V+import Control.Lens+import qualified Graphics.Rendering.OpenGL.GL as GL+import Data.Color+import Call.Types++class Affine a where+  type Vec a :: *+  type Normal a :: *+  rotateOn :: Normal a -> a -> a+  scale :: Vec a -> a -> a+  translate :: Vec a -> a -> a++class Affine a => Figure a where+  primitive :: GL.PrimitiveMode -> [Vec a] -> a+  color :: RGBA Float -> a -> a+  line :: [Vec a] -> a+  polygon :: [Vec a] -> a+  polygonOutline :: [Vec a] -> a+  circle :: Normal a -> a+  circleOutline :: Normal a -> a++opacity :: Figure a => Float -> a -> a+opacity p = color (V4 1 1 1 p)++bitmap :: B.Bitmap -> Picture+bitmap bmp = Picture $ Scene+  $ \_ _ f _ _ -> f bmp GL.TriangleStrip+    (V.fromList [V3 (-w/2) (-h/2) 0 `positionUV` V2 0 0+        , V3 (w/2) (-h/2) 0 `positionUV` V2 1 0+        , V3 (-w/2) (h/2) 0 `positionUV` V2 0 1+        , V3 (w/2) (h/2) 0 `positionUV` V2 1 1]) where+  V2 w h = fmap fromIntegral $ B.size bmp++toward :: Vec3 -> Picture -> Scene+toward n@((^/norm n) -> V3 x y z) (Picture s) = transformScene+  (m33_to_m44 $ fromQuaternion $ axisAngle (V3 (-y) x 0) $ acos $ z / norm n)+  s++newtype Scene = Scene { unScene :: forall r.+  r+  -> (r -> r -> r)+  -> (B.Bitmap -> GL.PrimitiveMode -> V.Vector Vertex -> r)+  -> (VFX r -> r)+  -> (M44 Float -> r -> r)+  -> r+  }++data VFX r = SphericalAdd Bitmap r+  | SphericalMultiply Bitmap r+  | Diffuse (V4 Float) r+--  | Specular (V3 Float) r+--  | Ambient (V3 Float) r+--  | NormalMap Bitmap r+  | EmbedIO (IO r)+  deriving Functor++instance Affine Scene where+  type Vec Scene = V3 Float+  type Normal Scene = V3 Float+  rotateOn v = transformScene $ m33_to_m44 $ fromQuaternion $ axisAngle v (norm v)+  scale (V3 x y z) = transformScene $ V4+    (V4 x 0 0 0)+    (V4 0 y 0 0)+    (V4 0 0 z 0)+    (V4 0 0 0 1)+  translate v = transformScene $ translation .~ v $ eye4++instance Figure Scene where+  primitive m vs = Scene $ \_ _ f _ _ -> f Blank m (V.fromList $ map positionOnly vs)+  color col (Scene s) = Scene $ \e a f b t -> b (Diffuse col (s e a f b t))+  line = primitive GL.LineStrip+  polygon = primitive GL.TriangleFan+  polygonOutline = primitive GL.LineLoop+  circle v = toward v $ circle $ norm v+  circleOutline v = toward v $ circleOutline $ norm v++unit_circle :: Int -> [V2 Float]+unit_circle n = map angle [0,2*pi/fromIntegral n..2*pi]++instance Monoid Scene where+  mempty = Scene $ \e _ _ _ _ -> e+  mappend (Scene x) (Scene y) = Scene $ \e a f b t -> a (x e a f b t) (y e a f b t)++v2ToV3 :: Num a => V2 a -> V3 a+v2ToV3 (V2 x y) = V3 x y 0++vertices :: B.Bitmap -> GL.PrimitiveMode -> V.Vector Vertex -> Scene+vertices b m v = Scene $ \_ _ f _ _ -> f b m v++transformScene :: M44 Float -> Scene -> Scene+transformScene m (Scene pic) = Scene $ \e a f b t -> t m (pic e a f b t)++applyVFX :: VFX Scene -> Scene+applyVFX vf = Scene $ \e a f b t -> b $ fmap (\(Scene s) -> s e a f b t) vf++newtype Picture = Picture { unPicture :: Scene } deriving Monoid++instance Affine Picture where+  type Vec Picture = V2 Float+  type Normal Picture = Float+  rotateOn t (Picture s) = Picture (transformScene m s) where+    m = V4 (V4 (cos t) (-sin t) 0 0) (V4 (sin t) (cos t) 0 0) (V4 0 0 1 0) (V4 0 0 0 1)+  translate (V2 x y) (Picture s) = Picture $ transformScene (translation .~ V3 x y 0 $ eye4) s+  scale (V2 x y) (Picture s) = Picture (transformScene m s) where+    m = V4 (V4 x 0 0 0) (V4 0 y 0 0) (V4 0 0 1 0) (V4 0 0 0 1)++instance Figure Picture where+  primitive m v = Picture $ primitive m $ map v2ToV3 v+  color col (Picture s) = Picture (color col s)+  line = primitive GL.LineStrip+  polygon = primitive GL.TriangleFan+  polygonOutline = primitive GL.LineLoop+  circle r = polygon $ map (^*r) $ unit_circle 33+  circleOutline r = polygonOutline $ map (^*r) $ unit_circle 33++newtype Sight = Sight { unSight+  :: forall r.+  X.Box V2 Float+  -> r+  -> (r -> r -> r)+  -> (X.Box V2 Float -> M44 Float -> Bool -> Scene -> r)+  -> r+  }++instance Monoid Sight where+  mempty = Sight $ \_ e _ _ -> e+  mappend (Sight x) (Sight y) = Sight $ \b e a f -> a (x b e a f) (y b e a f)++viewPicture :: Picture -> Sight+viewPicture (Picture s) = Sight $ \box@(X.Box (V2 x0 y0) (V2 x1 y1)) _ _ f -> f box (ortho x0 x1 y1 y0 (-1) 1) False s++viewScene :: Float -- ^ FOV+  -> Float -- ^ Near plane+  -> Float -- ^ Far plane+  -> Scene -- ^ The scene+  -> Sight+viewScene fov near far = fromPerspective $ \box -> perspective fov (let V2 w h = box ^. X.size 0 in w/h) near far++fromPerspective :: (X.Box V2 Float -> M44 Float) -> Scene -> Sight+fromPerspective mat s = Sight $ \box _ _ f -> f box (mat box) True s
src/Call/System.hs view
@@ -1,453 +1,453 @@-{-# LANGUAGE GeneralizedNewtypeDeriving #-}
-{-# LANGUAGE MultiParamTypeClasses #-}
-{-# LANGUAGE UndecidableInstances #-}
-{-# LANGUAGE ScopedTypeVariables #-}
-{-# LANGUAGE FlexibleInstances #-}
-{-# LANGUAGE FlexibleContexts #-}
-{-# LANGUAGE TemplateHaskell #-}
-{-# LANGUAGE KindSignatures #-}
-{-# LANGUAGE FunctionalDependencies #-}
-{-# LANGUAGE ExistentialQuantification #-}
-{-# LANGUAGE ConstraintKinds #-}
-{-# LANGUAGE TypeOperators #-}
-{-# LANGUAGE TypeFamilies #-}
-{-# LANGUAGE BangPatterns #-}
-{-# LANGUAGE ViewPatterns #-}
-{-# LANGUAGE LambdaCase #-}
-{-# LANGUAGE Rank2Types #-}
-{-# LANGUAGE DataKinds #-}
-{-# LANGUAGE GADTs #-}
-{-# LANGUAGE CPP #-}
-{-# OPTIONS_GHC -fno-warn-orphans #-}
------------------------------------------------------------------------------
--- |
--- Module      :  Call.System
--- Copyright   :  (c) Fumiaki Kinoshita 2014
--- License     :  BSD3
---
--- Maintainer  :  Fumiaki Kinoshita <fumiexcel@gmail.com>
--- Stability   :  experimental
--- Portability :  non-portable
---
------------------------------------------------------------------------------
-module Call.System (
-  -- * The system
-  System
-  , runSystem
-  , forkSystem
-  -- * Time
-  , stand
-  , wait
-  , getTime
-  , setFPS
-  -- * Raw input
-  , keyPress
-  , mousePosition
-  , mouseButton
-  , enableCursor
-  , hideCursor
-  , disableCursor
-  , getGamepads
-  , gamepadButtons
-  , gamepadAxes
-  -- * Component
-  , linkGraphic
-  , linkPicture
-  , linkAudio
-  , linkKeyboard
-  , linkMouse
-  , linkGamepad
-  -- * Others
-  , setTitle
-  , clearColor
-  , getBoundingBox
-  , setBoundingBox
-  , takeScreenshot
-  ) where
-
-import Call.Data.Bitmap
-import Call.Sight
-import Call.Types
-import Control.Applicative
-import Control.Concurrent
-import Control.Exception
-import Control.Elevator
-import Control.Lens
-import Control.Monad.Objective
-import Control.Monad.Reader
-import Control.Object
-import Data.BoundingBox (Box(..))
-import Data.OpenUnion1.Clean
-import Data.IORef
-import Data.Maybe
-import Data.Monoid
-import Foreign (castPtr, sizeOf, with)
-import Graphics.Rendering.OpenGL.GL.StateVar
-import Linear
-import qualified Call.Internal.GLFW as G
-import qualified Call.Internal.PortAudio as PA
-import qualified Codec.Picture as C
-import qualified Data.IntMap.Strict as IM
-import qualified Data.Vector.Storable as V
-import qualified Graphics.Rendering.OpenGL.GL as GL
-import qualified Graphics.Rendering.OpenGL.Raw as GL
-import qualified Graphics.UI.GLFW as GLFW
-import Unsafe.Coerce
-
-setFPS :: Float -> System s ()
-setFPS f = mkSystem $ \fo -> writeIORef (targetFPS fo) f
-
-newtype System s a = System (ReaderT (Foundation s) IO a) deriving (Functor, Applicative, Monad)
-
-instance Affine a => Affine (System s a) where
-  type Vec (System s a) = Vec a
-  type Normal (System s a) = Normal a
-  translate t = fmap (translate t)
-  scale t = fmap (scale t)
-  rotateOn t = fmap (rotateOn t)
-
-instance Figure a => Figure (System s a) where
-  primitive p v = return $ primitive p v
-  color c = fmap (color c)
-  line = return . line
-  polygon = return . polygon
-  polygonOutline = return . polygonOutline
-  circle = return . circle
-  circleOutline = return . circleOutline
-
-instance Monoid a => Monoid (System s a) where
-  mempty = return mempty
-  mappend = liftA2 mappend
-
-instance ObjectiveBase (System s) where
-  data Inst (System s) f g = InstS (MVar (Object f g))
-  invoke mr gr (InstS m) e = do
-    c <- mr $ liftIO $ takeMVar m
-    (a, c') <- gr (runObject c e)
-    mr $ liftIO $ putMVar m c'
-    return a
-  new v = liftIO $ InstS `fmap` newMVar v
-
-instance Tower (System s) where
-  type Floors (System s) = IO :> Empty
-  toLoft = liftIO ||> exhaust
-
-unSystem :: Foundation s -> System s a -> IO a
-unSystem f m = unsafeCoerce m f
-
-mkSystem :: (Foundation s -> IO a) -> System s a
-mkSystem = unsafeCoerce
-
-forkSystem :: System s () -> System s ThreadId
-forkSystem m = mkSystem $ \fo -> forkIO (unSystem fo m)
-
-linkGraphic :: (Time -> System s Sight) -> System s ()
-linkGraphic f = mkSystem $ \fo -> do
-  g <- readIORef $ coreGraphic fo
-  writeIORef (coreGraphic fo) $ \dt -> liftA2 (<>) (f dt) (g dt)
-
-linkPicture :: (Time -> System s Picture) -> System s ()
-linkPicture f = linkGraphic (fmap viewPicture . f)
-
-linkAudio :: (Time -> Int -> System s (V.Vector Stereo)) -> System s ()
-linkAudio f = mkSystem $ \fo -> do
-  g <- readIORef $ coreAudio fo
-  writeIORef (coreAudio fo) $ \dt n -> liftA2 (V.zipWith (+)) (f dt n) (g dt n)
-
-linkKeyboard :: (Chatter Key -> System s ()) -> System s ()
-linkKeyboard f = mkSystem $ \fo -> do
-  g <- readIORef $ coreKeyboard fo
-  writeIORef (coreKeyboard fo) $ \k -> f k >> g k
-
-linkMouse :: (MouseEvent -> System s ()) -> System s ()
-linkMouse f = mkSystem $ \fo -> do
-  g <- readIORef $ coreMouse fo
-  writeIORef (coreMouse fo) $ \k -> f k >> g k
-
-linkGamepad :: (GamepadEvent -> System s ()) -> System s ()
-linkGamepad f = mkSystem $ \fo -> do
-  g <- readIORef $ coreJoypad fo
-  writeIORef (coreJoypad fo) $ \k -> f k >> g k
-
-data Foundation s = Foundation
-  { sampleRate :: Float
-  , coreGraphic :: IORef (Time -> System s Sight)
-  , coreAudio :: IORef (Time -> Int -> System s (V.Vector (V2 Float)))
-  , coreKeyboard :: IORef (Chatter Key -> System s ())
-  , coreMouse :: IORef (MouseEvent -> System s ())
-  , coreJoypad :: IORef (GamepadEvent -> System s ())
-  , theTime :: MVar Time
-  , theSystem :: G.System
-  , targetFPS :: IORef Float
-  , textures :: IORef (IM.IntMap G.Texture)
-  , theEnd :: MVar ()
-  , theGamepadButtons :: IORef (IM.IntMap (String, IM.IntMap Bool))
-  }
-
-runSystem :: WindowMode -> Box V2 Float -> (forall s. System s a) -> IO (Maybe a)
-runSystem mode box m = do
-  sys <- G.beginGLFW mode box
-  f <- Foundation
-    <$> pure 44100 -- FIX THIS
-    <*> newIORef (const $ return mempty)
-    <*> newIORef (\_ n -> return $ V.replicate n zero)
-    <*> newIORef (const $ return ())
-    <*> newIORef (const $ return ())
-    <*> newIORef (const $ return ())
-    <*> newMVar 0
-    <*> pure sys
-    <*> newIORef 60
-    <*> newIORef IM.empty
-    <*> newEmptyMVar
-    <*> newIORef IM.empty
-  let win = G.theWindow sys
-  GLFW.setKeyCallback win $ Just $ keyCallback f
-  GLFW.setMouseButtonCallback win $ Just $ mouseButtonCallback f
-  GLFW.setCursorPosCallback win $ Just $ cursorPosCallback f
-  GLFW.setScrollCallback win $ Just $ scrollCallback f
-  GL.UniformLocation loc <- GL.get $ GL.uniformLocation (G.theProgram sys) "color"
-  with (V4 1 1 1 1 :: V4 Float) $ \ptr -> GL.glUniform4fv loc 1 (castPtr ptr)
-
-  print =<< GLFW.getWindowClientAPI win
-  putStr "OpenGL Version: "
-  cv0 <- GLFW.getWindowContextVersionMajor    win
-  cv1 <- GLFW.getWindowContextVersionMinor    win
-  cv2 <- GLFW.getWindowContextVersionRevision win
-  putStrLn $ show cv0 ++ "." ++ show cv1 ++ "." ++ show cv2
-  print =<< GLFW.getWindowContextRobustness win
-  putStr "Forward compat: "
-  print =<< GLFW.getWindowOpenGLForwardCompat win
-  putStr "Debug context: "
-  print =<< GLFW.getWindowOpenGLDebugContext win
-  print =<< GLFW.getWindowOpenGLProfile win
-
-  ref <- newEmptyMVar
-  _ <- flip forkFinally (either throwIO (putMVar ref)) $ unSystem f m
-  PA.with 44100 512 (audioProcess f) $ liftIO $ do
-    GLFW.setTime 0
-    runGraphic f 0
-  G.endGLFW sys
-  tryTakeMVar ref
-
-stand :: System s ()
-stand = mkSystem $ \fo -> takeMVar (theEnd fo)
-
-wait :: Time -> System s ()
-wait dt = mkSystem $ \fo -> do
-  t0 <- takeMVar (theTime fo)
-  Just t <- GLFW.getTime
-  threadDelay $ floor $ (t0 - realToFrac t + dt) * 1000 * 1000
-  putMVar (theTime fo) $ t0 + dt
-
-getTime :: System s Time
-getTime = mkSystem $ \fo -> readMVar (theTime fo)
-
-keyPress :: Key -> System s Bool
-keyPress k = mkSystem $ \fo -> fmap (/=GLFW.KeyState'Released)
-  $ GLFW.getKey (G.theWindow $ theSystem fo) (toEnum . fromEnum $ k)
-
-mousePosition :: System s (V2 Float)
-mousePosition = mkSystem $ \fo -> do
-  (x, y) <- GLFW.getCursorPos (G.theWindow $ theSystem fo)
-  return $ V2 (realToFrac x) (realToFrac y)
-
-hideCursor :: System s ()
-hideCursor = mkSystem $ \fo -> GLFW.setCursorInputMode (G.theWindow $ theSystem fo) GLFW.CursorInputMode'Hidden
-
-disableCursor :: System s ()
-disableCursor = mkSystem $ \fo -> GLFW.setCursorInputMode (G.theWindow $ theSystem fo) GLFW.CursorInputMode'Disabled
-
-enableCursor :: System s ()
-enableCursor = mkSystem $ \fo -> GLFW.setCursorInputMode (G.theWindow $ theSystem fo) GLFW.CursorInputMode'Normal
-
-mouseButton :: Int -> System s Bool
-mouseButton b = mkSystem $ \fo -> fmap (/=GLFW.MouseButtonState'Released)
-  $ GLFW.getMouseButton (G.theWindow $ theSystem fo) (toEnum b)
-
-getGamepads :: System s [Gamepad]
-getGamepads = mkSystem $ const $ fmap catMaybes $ forM [(GLFW.Joystick'1)..]
-  $ \j -> fmap (Gamepad (fromEnum j)) <$> GLFW.getJoystickName j
-
-gamepadAxes :: Gamepad -> System s [Float]
-gamepadAxes (Gamepad i _) = mkSystem $ const $ maybe [] (map realToFrac) <$> GLFW.getJoystickAxes (toEnum i)
-
-gamepadButtons :: Gamepad -> System s [Bool]
-gamepadButtons (Gamepad i _) = mkSystem $ const
-  $ maybe [] (map (==GLFW.JoystickButtonState'Pressed)) <$> GLFW.getJoystickButtons (toEnum i)
-
-clearColor :: V4 Float -> System s ()
-clearColor col = liftIO $ GL.clearColor $= unsafeCoerce col
-
-setBoundingBox :: Box V2 Float -> System s ()
-setBoundingBox box@(Box (V2 x0 y0) (V2 x1 y1)) = mkSystem $ \fo -> do
-  GLFW.setWindowSize (G.theWindow $ theSystem fo) (floor (x1 - x0)) (floor (y1 - y0))
-  writeIORef (G.refRegion $ theSystem fo) box
-
-getBoundingBox :: System s (Box V2 Float)
-getBoundingBox = mkSystem $ \fo -> readIORef (G.refRegion $ theSystem fo)
-
-takeScreenshot :: System s Bitmap
-takeScreenshot = mkSystem $ \fo -> G.screenshot (theSystem fo) >>= liftImage'
-
-setTitle :: String -> System s ()
-setTitle str = mkSystem $ \fo -> GLFW.setWindowTitle (G.theWindow $ theSystem fo) str
-
-instance MonadIO (System s) where
-  liftIO m = mkSystem $ const m
-  {-# INLINE liftIO #-}
-
-pollGamepad :: Foundation s -> IO ()
-pollGamepad fo = do
-  m <- readIORef (coreJoypad fo)
-  ps <- IM.fromList <$> map (\p@(Gamepad i _) -> (i, p)) <$> unSystem fo getGamepads
-  bs0 <- readIORef (theGamepadButtons fo)
-
-  bs0' <- forM (IM.toList $ ps IM.\\ bs0) $ \(i, p@(Gamepad _ s)) -> do
-    unSystem fo $ m $ PadConnection $ Up p
-    return (i, (s, IM.empty))
-
-  bs0_ <- forM (IM.toList $ bs0 IM.\\ ps) $ \(i, (s, _)) -> do
-    unSystem fo $ m $ PadConnection $ Down $ Gamepad i s
-    return (i, ())
-
-  let bs1 = bs0 `IM.union` IM.fromList bs0' IM.\\ IM.fromList bs0_
-
-  ls <- forM (IM.toList ps) $ \(j, p@(Gamepad _ s)) -> do
-    bs <- zip [0..] <$> unSystem fo (gamepadButtons p)
-    forM_ bs $ \(i, v) -> case (v, maybe False id (bs1 ^? ix j . _2 . ix i)) of
-        (False, True) -> unSystem fo $ m $ PadButton p (Up i)
-        (True, False) -> unSystem fo $ m $ PadButton p (Down i)
-        _ -> return ()
-    return (j, (s, IM.fromList bs))
-
-  writeIORef (theGamepadButtons fo) $ foldr (uncurry IM.insert) bs1 ls
-
-runGraphic :: Foundation s -> Time -> IO ()
-runGraphic fo t0 = do
-  pollGamepad fo
-  fps <- readIORef (targetFPS fo)
-  let t1 = t0 + 1/fps
-  G.beginFrame (theSystem fo)
-  m <- readIORef (coreGraphic fo)
-  pic <- unSystem fo $ m (1/fps) -- is it appropriate?
-  drawSight fo pic
-  b <- G.endFrame (theSystem fo)
-
-  Just t' <- GLFW.getTime
-  threadDelay $ floor $ (t1 - realToFrac t') * 1000 * 1000
-
-  tryTakeMVar (theEnd fo) >>= \case
-      Just _ -> return ()
-      _ | b -> putMVar (theEnd fo) ()
-        | otherwise -> runGraphic fo t1
-
-audioProcess :: Foundation s -> Int -> IO (V.Vector Stereo)
-audioProcess fo n = do
-  let dt = fromIntegral n / sampleRate fo
-  m <- readIORef (coreAudio fo)
-  unSystem fo $ m dt n
-
-keyCallback :: Foundation s -> GLFW.KeyCallback
-keyCallback fo _ k _ st _ = do
-  m <- readIORef (coreKeyboard fo)
-  unSystem fo $ m $ case st of
-    GLFW.KeyState'Released -> Up (toEnum . fromEnum $ k :: Key)
-    _ -> Down (toEnum . fromEnum $ k :: Key)
-
-mouseButtonCallback :: Foundation s -> GLFW.MouseButtonCallback
-mouseButtonCallback fo _ btn st _ = do
-  m <- readIORef (coreMouse fo)
-  unSystem fo $ m $ case st of
-    GLFW.MouseButtonState'Released -> Button $ Up (fromEnum btn)
-    _ -> Button $ Down (fromEnum btn)
-
-cursorPosCallback :: Foundation s -> GLFW.CursorPosCallback
-cursorPosCallback fo _ x y = do
-  m <- readIORef (coreMouse fo)
-  unSystem fo $ m $ Cursor $ fmap realToFrac $ V2 x y
-
-scrollCallback :: Foundation s -> GLFW.ScrollCallback
-scrollCallback fo _ x y = do
-  m <- readIORef (coreMouse fo)
-  unSystem fo $ m $ Scroll $ fmap realToFrac $ V2 x y
-
-fetchTexture :: Foundation s -> C.Image C.PixelRGBA8 -> Int -> IO G.Texture
-fetchTexture fo bmp h = do
-  st <- readIORef (textures fo)
-  case IM.lookup h st of
-    Just t -> return t
-    Nothing -> do
-      t <- G.installTexture bmp
-      writeIORef (textures fo) $ IM.insert h t st
-      return t
-
-drawScene :: Foundation s -> Box V2 Float -> M44 Float -> Bool -> Scene -> IO ()
-drawScene fo (fmap round -> Box (V2 x0 y0) (V2 x1 y1)) proj _ (Scene s) = do
-  GL.viewport $= (GL.Position x0 y0, GL.Size (x1 - x0) (y1 - y0))
-
-  GL.currentProgram $= Just shaderProg
-  GL.UniformLocation loc <- GL.get (GL.uniformLocation shaderProg "projection")
-  with proj $ \ptr -> GL.glUniformMatrix4fv loc 1 1 $ castPtr ptr
-  GL.UniformLocation locT <- GL.get $ GL.uniformLocation shaderProg "textureMix"
-  s (pure $ return ()) (liftA2 (>>)) (prim locT) fx trans (V4 1 1 1 1, 0)
-  where
-    shaderProg = G.theProgram $ theSystem fo
-    prim locT Blank mode vs _ = do
-      GL.glUniform1f locT 0
-      V.unsafeWith vs $ \v -> GL.bufferData GL.ArrayBuffer $=
-        (fromIntegral $ V.length vs * sizeOf (undefined :: Vertex), v, GL.StaticDraw)
-      GL.drawArrays mode 0 $ fromIntegral $ V.length vs
-    prim locT (Bitmap bmp _ h) mode vs _ = do
-      GL.glUniform1f locT 1
-      (tex, _, _) <- fetchTexture fo bmp h
-      GL.activeTexture $= GL.TextureUnit 0
-      GL.textureBinding GL.Texture2D $= Just tex
-      GL.textureFilter GL.Texture2D $= ((GL.Linear', Nothing), GL.Linear')
-      V.unsafeWith vs $ \v -> GL.bufferData GL.ArrayBuffer $=
-        (fromIntegral $ V.length vs * sizeOf (undefined :: Vertex), v, GL.StaticDraw)
-      GL.drawArrays mode 0 $ fromIntegral $ V.length vs
-    trans f m (color0, n) = do
-      GL.UniformLocation loc <- GL.get $ GL.uniformLocation shaderProg "matrices"
-      GL.UniformLocation locN <- GL.get $ GL.uniformLocation shaderProg "level"
-      with f $ \ptr -> GL.glUniformMatrix4fv (loc+n) 1 1 (castPtr ptr)
-      GL.glUniform1i locN (unsafeCoerce $ n + 1)
-      m (color0, n + 1)
-      GL.glUniform1i locN (unsafeCoerce n)
-    fx (EmbedIO m) c = m >>= ($ c)
-    fx (Diffuse col m) (color0, n) = do
-      GL.UniformLocation loc <- GL.get $ GL.uniformLocation shaderProg "diffuse"
-      let c = col * color0
-      with c $ \ptr -> GL.glUniform4fv loc 1 (castPtr ptr)
-      m (c, n)
-      with color0 $ \ptr -> GL.glUniform4fv loc 1 (castPtr ptr)
-    fx (SphericalAdd (Bitmap bmp _ h) m) c = do
-      withLoc "useEnv" $ \loc -> GL.glUniform1i loc 1
-      withLoc "envAdd" $ \loc -> GL.glUniform1f loc 1
-      (tex, _, _) <- fetchTexture fo bmp h
-      GL.activeTexture $= GL.TextureUnit 1
-      GL.textureFilter GL.Texture2D $= ((GL.Linear', Nothing), GL.Linear')
-      GL.textureBinding GL.Texture2D $= Just tex
-      m c
-      withLoc "useEnv" $ \loc -> GL.glUniform1i loc 0
-      withLoc "envAdd" $ \loc -> GL.glUniform1f loc 0
-    fx (SphericalAdd Blank m) c = m c
-    fx (SphericalMultiply (Bitmap bmp _ h) m) c = do
-      withLoc "useEnv" $ \loc -> GL.glUniform1i loc 1
-      withLoc "envMul" $ \loc -> GL.glUniform1f loc 1
-      (tex, _, _) <- fetchTexture fo bmp h
-
-      GL.activeTexture $= GL.TextureUnit 1
-      GL.textureFilter GL.Texture2D $= ((GL.Linear', Nothing), GL.Linear')
-      GL.textureBinding GL.Texture2D $= Just tex
-      m c
-      withLoc "useEnv" $ \loc -> GL.glUniform1i loc 0
-      withLoc "envMul" $ \loc -> GL.glUniform1f loc 0
-    fx (SphericalMultiply Blank m) c = m c
-    withLoc str m = do
-      GL.UniformLocation loc <- GL.get $ GL.uniformLocation shaderProg str
-      m loc
-
-drawSight :: Foundation s -> Sight -> IO ()
-drawSight fo (Sight s) = do
-  b <- readIORef $ G.refRegion $ theSystem fo
-  s b (return ()) (>>) (drawScene fo)
+{-# LANGUAGE GeneralizedNewtypeDeriving #-}+{-# LANGUAGE MultiParamTypeClasses #-}+{-# LANGUAGE UndecidableInstances #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE TemplateHaskell #-}+{-# LANGUAGE KindSignatures #-}+{-# LANGUAGE FunctionalDependencies #-}+{-# LANGUAGE ExistentialQuantification #-}+{-# LANGUAGE ConstraintKinds #-}+{-# LANGUAGE TypeOperators #-}+{-# LANGUAGE TypeFamilies #-}+{-# LANGUAGE BangPatterns #-}+{-# LANGUAGE ViewPatterns #-}+{-# LANGUAGE LambdaCase #-}+{-# LANGUAGE Rank2Types #-}+{-# LANGUAGE DataKinds #-}+{-# LANGUAGE GADTs #-}+{-# LANGUAGE CPP #-}+{-# OPTIONS_GHC -fno-warn-orphans #-}+-----------------------------------------------------------------------------+-- |+-- Module      :  Call.System+-- Copyright   :  (c) Fumiaki Kinoshita 2014+-- License     :  BSD3+--+-- Maintainer  :  Fumiaki Kinoshita <fumiexcel@gmail.com>+-- Stability   :  experimental+-- Portability :  non-portable+--+-----------------------------------------------------------------------------+module Call.System (+  -- * The system+  System+  , runSystem+  , forkSystem+  -- * Time+  , stand+  , wait+  , getTime+  , setFPS+  -- * Raw input+  , keyPress+  , mousePosition+  , mouseButton+  , enableCursor+  , hideCursor+  , disableCursor+  , getGamepads+  , gamepadButtons+  , gamepadAxes+  -- * Component+  , linkGraphic+  , linkPicture+  , linkAudio+  , linkKeyboard+  , linkMouse+  , linkGamepad+  -- * Others+  , setTitle+  , clearColor+  , getBoundingBox+  , setBoundingBox+  , takeScreenshot+  ) where++import Call.Data.Bitmap+import Call.Sight+import Call.Types+import Control.Applicative+import Control.Concurrent+import Control.Exception+import Control.Elevator+import Control.Lens+import Control.Monad.Objective+import Control.Monad.Reader+import Control.Object+import Data.BoundingBox (Box(..))+import Data.IORef+import Data.Maybe+import Data.Monoid+import Foreign (castPtr, sizeOf, with)+import Graphics.Rendering.OpenGL.GL.StateVar+import Linear+import qualified Call.Internal.GLFW as G+import qualified Call.Internal.PortAudio as PA+import qualified Codec.Picture as C+import qualified Data.IntMap.Strict as IM+import qualified Data.Vector.Storable as V+import qualified Graphics.Rendering.OpenGL.GL as GL+import qualified Graphics.Rendering.OpenGL.Raw as GL+import qualified Graphics.UI.GLFW as GLFW+import Unsafe.Coerce+import Data.Extensible++setFPS :: Float -> System s ()+setFPS f = mkSystem $ \fo -> writeIORef (targetFPS fo) f++newtype System s a = System (ReaderT (Foundation s) IO a) deriving (Functor, Applicative, Monad)++instance Affine a => Affine (System s a) where+  type Vec (System s a) = Vec a+  type Normal (System s a) = Normal a+  translate t = fmap (translate t)+  scale t = fmap (scale t)+  rotateOn t = fmap (rotateOn t)++instance Figure a => Figure (System s a) where+  primitive p v = return $ primitive p v+  color c = fmap (color c)+  line = return . line+  polygon = return . polygon+  polygonOutline = return . polygonOutline+  circle = return . circle+  circleOutline = return . circleOutline++instance Monoid a => Monoid (System s a) where+  mempty = return mempty+  mappend = liftA2 mappend++instance ObjectiveBase (System s) where+  data Inst (System s) f g = InstS (MVar (Object f g))+  invoke mr gr (InstS m) e = do+    c <- mr $ liftIO $ takeMVar m+    (a, c') <- gr (runObject c e)+    mr $ liftIO $ putMVar m c'+    return a+  new v = liftIO $ InstS `fmap` newMVar v++instance Tower (System s) where+  type Floors (System s) = Floors IO+  stairs = hmap (\(Gondola f) -> Gondola (liftIO . f)) stairs++unSystem :: Foundation s -> System s a -> IO a+unSystem f m = unsafeCoerce m f++mkSystem :: (Foundation s -> IO a) -> System s a+mkSystem = unsafeCoerce++forkSystem :: System s () -> System s ThreadId+forkSystem m = mkSystem $ \fo -> forkIO (unSystem fo m)++linkGraphic :: (Time -> System s Sight) -> System s ()+linkGraphic f = mkSystem $ \fo -> do+  g <- readIORef $ coreGraphic fo+  writeIORef (coreGraphic fo) $ \dt -> liftA2 (<>) (f dt) (g dt)++linkPicture :: (Time -> System s Picture) -> System s ()+linkPicture f = linkGraphic (fmap viewPicture . f)++linkAudio :: (Time -> Int -> System s (V.Vector Stereo)) -> System s ()+linkAudio f = mkSystem $ \fo -> do+  g <- readIORef $ coreAudio fo+  writeIORef (coreAudio fo) $ \dt n -> liftA2 (V.zipWith (+)) (f dt n) (g dt n)++linkKeyboard :: (Chatter Key -> System s ()) -> System s ()+linkKeyboard f = mkSystem $ \fo -> do+  g <- readIORef $ coreKeyboard fo+  writeIORef (coreKeyboard fo) $ \k -> f k >> g k++linkMouse :: (MouseEvent -> System s ()) -> System s ()+linkMouse f = mkSystem $ \fo -> do+  g <- readIORef $ coreMouse fo+  writeIORef (coreMouse fo) $ \k -> f k >> g k++linkGamepad :: (GamepadEvent -> System s ()) -> System s ()+linkGamepad f = mkSystem $ \fo -> do+  g <- readIORef $ coreJoypad fo+  writeIORef (coreJoypad fo) $ \k -> f k >> g k++data Foundation s = Foundation+  { sampleRate :: Float+  , coreGraphic :: IORef (Time -> System s Sight)+  , coreAudio :: IORef (Time -> Int -> System s (V.Vector (V2 Float)))+  , coreKeyboard :: IORef (Chatter Key -> System s ())+  , coreMouse :: IORef (MouseEvent -> System s ())+  , coreJoypad :: IORef (GamepadEvent -> System s ())+  , theTime :: MVar Time+  , theSystem :: G.System+  , targetFPS :: IORef Float+  , textures :: IORef (IM.IntMap G.Texture)+  , theEnd :: MVar ()+  , theGamepadButtons :: IORef (IM.IntMap (String, IM.IntMap Bool))+  }++runSystem :: WindowMode -> Box V2 Float -> (forall s. System s a) -> IO (Maybe a)+runSystem mode box m = do+  sys <- G.beginGLFW mode box+  f <- Foundation+    <$> pure 44100 -- FIX THIS+    <*> newIORef (const $ return mempty)+    <*> newIORef (\_ n -> return $ V.replicate n zero)+    <*> newIORef (const $ return ())+    <*> newIORef (const $ return ())+    <*> newIORef (const $ return ())+    <*> newMVar 0+    <*> pure sys+    <*> newIORef 60+    <*> newIORef IM.empty+    <*> newEmptyMVar+    <*> newIORef IM.empty+  let win = G.theWindow sys+  GLFW.setKeyCallback win $ Just $ keyCallback f+  GLFW.setMouseButtonCallback win $ Just $ mouseButtonCallback f+  GLFW.setCursorPosCallback win $ Just $ cursorPosCallback f+  GLFW.setScrollCallback win $ Just $ scrollCallback f+  GL.UniformLocation loc <- GL.get $ GL.uniformLocation (G.theProgram sys) "color"+  with (V4 1 1 1 1 :: V4 Float) $ \ptr -> GL.glUniform4fv loc 1 (castPtr ptr)++  print =<< GLFW.getWindowClientAPI win+  putStr "OpenGL Version: "+  cv0 <- GLFW.getWindowContextVersionMajor    win+  cv1 <- GLFW.getWindowContextVersionMinor    win+  cv2 <- GLFW.getWindowContextVersionRevision win+  putStrLn $ show cv0 ++ "." ++ show cv1 ++ "." ++ show cv2+  print =<< GLFW.getWindowContextRobustness win+  putStr "Forward compat: "+  print =<< GLFW.getWindowOpenGLForwardCompat win+  putStr "Debug context: "+  print =<< GLFW.getWindowOpenGLDebugContext win+  print =<< GLFW.getWindowOpenGLProfile win++  ref <- newEmptyMVar+  _ <- flip forkFinally (either throwIO (putMVar ref)) $ unSystem f m+  PA.with 44100 512 (audioProcess f) $ liftIO $ do+    GLFW.setTime 0+    runGraphic f 0+  G.endGLFW sys+  tryTakeMVar ref++stand :: System s ()+stand = mkSystem $ \fo -> takeMVar (theEnd fo)++wait :: Time -> System s ()+wait dt = mkSystem $ \fo -> do+  t0 <- takeMVar (theTime fo)+  Just t <- GLFW.getTime+  threadDelay $ floor $ (t0 - realToFrac t + dt) * 1000 * 1000+  putMVar (theTime fo) $ t0 + dt++getTime :: System s Time+getTime = mkSystem $ \fo -> readMVar (theTime fo)++keyPress :: Key -> System s Bool+keyPress k = mkSystem $ \fo -> fmap (/=GLFW.KeyState'Released)+  $ GLFW.getKey (G.theWindow $ theSystem fo) (toEnum . fromEnum $ k)++mousePosition :: System s (V2 Float)+mousePosition = mkSystem $ \fo -> do+  (x, y) <- GLFW.getCursorPos (G.theWindow $ theSystem fo)+  return $ V2 (realToFrac x) (realToFrac y)++hideCursor :: System s ()+hideCursor = mkSystem $ \fo -> GLFW.setCursorInputMode (G.theWindow $ theSystem fo) GLFW.CursorInputMode'Hidden++disableCursor :: System s ()+disableCursor = mkSystem $ \fo -> GLFW.setCursorInputMode (G.theWindow $ theSystem fo) GLFW.CursorInputMode'Disabled++enableCursor :: System s ()+enableCursor = mkSystem $ \fo -> GLFW.setCursorInputMode (G.theWindow $ theSystem fo) GLFW.CursorInputMode'Normal++mouseButton :: Int -> System s Bool+mouseButton b = mkSystem $ \fo -> fmap (/=GLFW.MouseButtonState'Released)+  $ GLFW.getMouseButton (G.theWindow $ theSystem fo) (toEnum b)++getGamepads :: System s [Gamepad]+getGamepads = mkSystem $ const $ fmap catMaybes $ forM [(GLFW.Joystick'1)..]+  $ \j -> fmap (Gamepad (fromEnum j)) <$> GLFW.getJoystickName j++gamepadAxes :: Gamepad -> System s [Float]+gamepadAxes (Gamepad i _) = mkSystem $ const $ maybe [] (map realToFrac) <$> GLFW.getJoystickAxes (toEnum i)++gamepadButtons :: Gamepad -> System s [Bool]+gamepadButtons (Gamepad i _) = mkSystem $ const+  $ maybe [] (map (==GLFW.JoystickButtonState'Pressed)) <$> GLFW.getJoystickButtons (toEnum i)++clearColor :: V4 Float -> System s ()+clearColor col = liftIO $ GL.clearColor $= unsafeCoerce col++setBoundingBox :: Box V2 Float -> System s ()+setBoundingBox box@(Box (V2 x0 y0) (V2 x1 y1)) = mkSystem $ \fo -> do+  GLFW.setWindowSize (G.theWindow $ theSystem fo) (floor (x1 - x0)) (floor (y1 - y0))+  writeIORef (G.refRegion $ theSystem fo) box++getBoundingBox :: System s (Box V2 Float)+getBoundingBox = mkSystem $ \fo -> readIORef (G.refRegion $ theSystem fo)++takeScreenshot :: System s Bitmap+takeScreenshot = mkSystem $ \fo -> G.screenshot (theSystem fo) >>= liftImage'++setTitle :: String -> System s ()+setTitle str = mkSystem $ \fo -> GLFW.setWindowTitle (G.theWindow $ theSystem fo) str++instance MonadIO (System s) where+  liftIO m = mkSystem $ const m+  {-# INLINE liftIO #-}++pollGamepad :: Foundation s -> IO ()+pollGamepad fo = do+  m <- readIORef (coreJoypad fo)+  ps <- IM.fromList <$> map (\p@(Gamepad i _) -> (i, p)) <$> unSystem fo getGamepads+  bs0 <- readIORef (theGamepadButtons fo)++  bs0' <- forM (IM.toList $ ps IM.\\ bs0) $ \(i, p@(Gamepad _ s)) -> do+    unSystem fo $ m $ PadConnection $ Up p+    return (i, (s, IM.empty))++  bs0_ <- forM (IM.toList $ bs0 IM.\\ ps) $ \(i, (s, _)) -> do+    unSystem fo $ m $ PadConnection $ Down $ Gamepad i s+    return (i, ())++  let bs1 = bs0 `IM.union` IM.fromList bs0' IM.\\ IM.fromList bs0_++  ls <- forM (IM.toList ps) $ \(j, p@(Gamepad _ s)) -> do+    bs <- zip [0..] <$> unSystem fo (gamepadButtons p)+    forM_ bs $ \(i, v) -> case (v, maybe False id (bs1 ^? ix j . _2 . ix i)) of+        (False, True) -> unSystem fo $ m $ PadButton p (Up i)+        (True, False) -> unSystem fo $ m $ PadButton p (Down i)+        _ -> return ()+    return (j, (s, IM.fromList bs))++  writeIORef (theGamepadButtons fo) $ foldr (uncurry IM.insert) bs1 ls++runGraphic :: Foundation s -> Time -> IO ()+runGraphic fo t0 = do+  pollGamepad fo+  fps <- readIORef (targetFPS fo)+  let t1 = t0 + 1/fps+  G.beginFrame (theSystem fo)+  m <- readIORef (coreGraphic fo)+  pic <- unSystem fo $ m (1/fps) -- is it appropriate?+  drawSight fo pic+  b <- G.endFrame (theSystem fo)++  Just t' <- GLFW.getTime+  threadDelay $ floor $ (t1 - realToFrac t') * 1000 * 1000++  tryTakeMVar (theEnd fo) >>= \case+      Just _ -> return ()+      _ | b -> putMVar (theEnd fo) ()+        | otherwise -> runGraphic fo t1++audioProcess :: Foundation s -> Int -> IO (V.Vector Stereo)+audioProcess fo n = do+  let dt = fromIntegral n / sampleRate fo+  m <- readIORef (coreAudio fo)+  unSystem fo $ m dt n++keyCallback :: Foundation s -> GLFW.KeyCallback+keyCallback fo _ k _ st _ = do+  m <- readIORef (coreKeyboard fo)+  unSystem fo $ m $ case st of+    GLFW.KeyState'Released -> Up (toEnum . fromEnum $ k :: Key)+    _ -> Down (toEnum . fromEnum $ k :: Key)++mouseButtonCallback :: Foundation s -> GLFW.MouseButtonCallback+mouseButtonCallback fo _ btn st _ = do+  m <- readIORef (coreMouse fo)+  unSystem fo $ m $ case st of+    GLFW.MouseButtonState'Released -> Button $ Up (fromEnum btn)+    _ -> Button $ Down (fromEnum btn)++cursorPosCallback :: Foundation s -> GLFW.CursorPosCallback+cursorPosCallback fo _ x y = do+  m <- readIORef (coreMouse fo)+  unSystem fo $ m $ Cursor $ fmap realToFrac $ V2 x y++scrollCallback :: Foundation s -> GLFW.ScrollCallback+scrollCallback fo _ x y = do+  m <- readIORef (coreMouse fo)+  unSystem fo $ m $ Scroll $ fmap realToFrac $ V2 x y++fetchTexture :: Foundation s -> C.Image C.PixelRGBA8 -> Int -> IO G.Texture+fetchTexture fo bmp h = do+  st <- readIORef (textures fo)+  case IM.lookup h st of+    Just t -> return t+    Nothing -> do+      t <- G.installTexture bmp+      writeIORef (textures fo) $ IM.insert h t st+      return t++drawScene :: Foundation s -> Box V2 Float -> M44 Float -> Bool -> Scene -> IO ()+drawScene fo (fmap round -> Box (V2 x0 y0) (V2 x1 y1)) proj _ (Scene s) = do+  GL.viewport $= (GL.Position x0 y0, GL.Size (x1 - x0) (y1 - y0))++  GL.currentProgram $= Just shaderProg+  GL.UniformLocation loc <- GL.get (GL.uniformLocation shaderProg "projection")+  with proj $ \ptr -> GL.glUniformMatrix4fv loc 1 1 $ castPtr ptr+  GL.UniformLocation locT <- GL.get $ GL.uniformLocation shaderProg "textureMix"+  s (pure $ return ()) (liftA2 (>>)) (prim locT) fx trans (V4 1 1 1 1, 0)+  where+    shaderProg = G.theProgram $ theSystem fo+    prim locT Blank mode vs _ = do+      GL.glUniform1f locT 0+      V.unsafeWith vs $ \v -> GL.bufferData GL.ArrayBuffer $=+        (fromIntegral $ V.length vs * sizeOf (undefined :: Vertex), v, GL.StaticDraw)+      GL.drawArrays mode 0 $ fromIntegral $ V.length vs+    prim locT (Bitmap bmp _ h) mode vs _ = do+      GL.glUniform1f locT 1+      (tex, _, _) <- fetchTexture fo bmp h+      GL.activeTexture $= GL.TextureUnit 0+      GL.textureBinding GL.Texture2D $= Just tex+      GL.textureFilter GL.Texture2D $= ((GL.Linear', Nothing), GL.Linear')+      V.unsafeWith vs $ \v -> GL.bufferData GL.ArrayBuffer $=+        (fromIntegral $ V.length vs * sizeOf (undefined :: Vertex), v, GL.StaticDraw)+      GL.drawArrays mode 0 $ fromIntegral $ V.length vs+    trans f m (color0, n) = do+      GL.UniformLocation loc <- GL.get $ GL.uniformLocation shaderProg "matrices"+      GL.UniformLocation locN <- GL.get $ GL.uniformLocation shaderProg "level"+      with f $ \ptr -> GL.glUniformMatrix4fv (loc+n) 1 1 (castPtr ptr)+      GL.glUniform1i locN (unsafeCoerce $ n + 1)+      m (color0, n + 1)+      GL.glUniform1i locN (unsafeCoerce n)+    fx (EmbedIO m) c = m >>= ($ c)+    fx (Diffuse col m) (color0, n) = do+      GL.UniformLocation loc <- GL.get $ GL.uniformLocation shaderProg "diffuse"+      let c = col * color0+      with c $ \ptr -> GL.glUniform4fv loc 1 (castPtr ptr)+      m (c, n)+      with color0 $ \ptr -> GL.glUniform4fv loc 1 (castPtr ptr)+    fx (SphericalAdd (Bitmap bmp _ h) m) c = do+      withLoc "useEnv" $ \loc -> GL.glUniform1i loc 1+      withLoc "envAdd" $ \loc -> GL.glUniform1f loc 1+      (tex, _, _) <- fetchTexture fo bmp h+      GL.activeTexture $= GL.TextureUnit 1+      GL.textureFilter GL.Texture2D $= ((GL.Linear', Nothing), GL.Linear')+      GL.textureBinding GL.Texture2D $= Just tex+      m c+      withLoc "useEnv" $ \loc -> GL.glUniform1i loc 0+      withLoc "envAdd" $ \loc -> GL.glUniform1f loc 0+    fx (SphericalAdd Blank m) c = m c+    fx (SphericalMultiply (Bitmap bmp _ h) m) c = do+      withLoc "useEnv" $ \loc -> GL.glUniform1i loc 1+      withLoc "envMul" $ \loc -> GL.glUniform1f loc 1+      (tex, _, _) <- fetchTexture fo bmp h++      GL.activeTexture $= GL.TextureUnit 1+      GL.textureFilter GL.Texture2D $= ((GL.Linear', Nothing), GL.Linear')+      GL.textureBinding GL.Texture2D $= Just tex+      m c+      withLoc "useEnv" $ \loc -> GL.glUniform1i loc 0+      withLoc "envMul" $ \loc -> GL.glUniform1f loc 0+    fx (SphericalMultiply Blank m) c = m c+    withLoc str m = do+      GL.UniformLocation loc <- GL.get $ GL.uniformLocation shaderProg str+      m loc++drawSight :: Foundation s -> Sight -> IO ()+drawSight fo (Sight s) = do+  b <- readIORef $ G.refRegion $ theSystem fo+  s b (return ()) (>>) (drawScene fo)
src/Call/TH.hs view
@@ -1,67 +1,67 @@-{-# LANGUAGE TemplateHaskell, CPP #-}
------------------------------------------------------------------------------
--- |
--- Module      :  Call.TH
--- Copyright   :  (c) Fumiaki Kinoshita 2014
--- License     :  BSD3
---
--- Maintainer  :  Fumiaki Kinoshita <fumiexcel@gmail.com>
--- Stability   :  experimental
--- Portability :  non-portable
---
--- Utilities that use Template Haskell
---
------------------------------------------------------------------------------
-module Call.TH (
-    loadBitmapsWith
-    ) where
-
-import Control.Applicative
-import Control.Monad
-import Data.Char
-import qualified Call.Data.Bitmap as Bitmap
-import Language.Haskell.TH
-import System.Directory
-import System.FilePath
-import System.IO.Unsafe
-
--- | The type of the given 'ExpQ' must be @FilePath -> IO FilePath@
--- FIXME: This may cause name duplication if there are multiple non-alphanumeric file names.
-loadBitmapsWith :: ExpQ -> FilePath -> Q [Dec]
-loadBitmapsWith getFullPath path = do
-    loc <- (</>path) <$> takeDirectory <$> loc_filename <$> location
-    paths <- runIO $ getFileList loc
-    
-    sequence $ do
-        p <- paths
-        let name = pathToName p
-        [ return $ SigD (mkName name) (ConT ''Bitmap.Bitmap)
-            , funD (mkName name) [clause [] (normalB $ load name $ loc </> p) []]
-            ]
-    where
-        load name fp = do
-            runIO $ putStrLn $ "Defined: " ++ fp ++ " as `" ++ name ++ "'"
-
-            appE (varE 'unsafePerformIO) $ uInfixE (appE getFullPath $ litE $ StringL fp)
-                (varE '(>>=))
-                (varE 'Bitmap.readFile)
-
--- | Load and define all pictures in the specified directory.
--- On base >= 4.6, file paths to actually load will be respect to the directory of the executable. Otherwise it will be based on the current directory.
-
-
-getFileList :: FilePath -> IO [FilePath]
-getFileList path = do
-    allContents <- filter notHidden `fmap` getDirectoryContents path
-
-    files <- filterM (doesFileExist . (path</>)) allContents
-    dirs <- filterM (doesDirectoryExist . (path</>)) allContents
-    fmap ((files++).concat) $ forM dirs $ \i -> map (i</>) `fmap` getFileList (path</>i)
-    where
-        notHidden ('.':_) = False
-        notHidden _ = True
-
-pathToName :: FilePath -> String
-pathToName = ('_':) . map p where
-    p c | isAlphaNum c = c
-        | otherwise = '_'
+{-# LANGUAGE TemplateHaskell, CPP #-}+-----------------------------------------------------------------------------+-- |+-- Module      :  Call.TH+-- Copyright   :  (c) Fumiaki Kinoshita 2014+-- License     :  BSD3+--+-- Maintainer  :  Fumiaki Kinoshita <fumiexcel@gmail.com>+-- Stability   :  experimental+-- Portability :  non-portable+--+-- Utilities that use Template Haskell+--+-----------------------------------------------------------------------------+module Call.TH (+    loadBitmapsWith+    ) where++import Control.Applicative+import Control.Monad+import Data.Char+import qualified Call.Data.Bitmap as Bitmap+import Language.Haskell.TH+import System.Directory+import System.FilePath+import System.IO.Unsafe++-- | The type of the given 'ExpQ' must be @FilePath -> IO FilePath@+-- FIXME: This may cause name duplication if there are multiple non-alphanumeric file names.+loadBitmapsWith :: ExpQ -> FilePath -> Q [Dec]+loadBitmapsWith getFullPath path = do+    loc <- (</>path) <$> takeDirectory <$> loc_filename <$> location+    paths <- runIO $ getFileList loc+    +    sequence $ do+        p <- paths+        let name = pathToName p+        [ return $ SigD (mkName name) (ConT ''Bitmap.Bitmap)+            , funD (mkName name) [clause [] (normalB $ load name $ loc </> p) []]+            ]+    where+        load name fp = do+            runIO $ putStrLn $ "Defined: " ++ fp ++ " as `" ++ name ++ "'"++            appE (varE 'unsafePerformIO) $ uInfixE (appE getFullPath $ litE $ StringL fp)+                (varE '(>>=))+                (varE 'Bitmap.readFile)++-- | Load and define all pictures in the specified directory.+-- On base >= 4.6, file paths to actually load will be respect to the directory of the executable. Otherwise it will be based on the current directory.+++getFileList :: FilePath -> IO [FilePath]+getFileList path = do+    allContents <- filter notHidden `fmap` getDirectoryContents path++    files <- filterM (doesFileExist . (path</>)) allContents+    dirs <- filterM (doesDirectoryExist . (path</>)) allContents+    fmap ((files++).concat) $ forM dirs $ \i -> map (i</>) `fmap` getFileList (path</>i)+    where+        notHidden ('.':_) = False+        notHidden _ = True++pathToName :: FilePath -> String+pathToName = ('_':) . map p where+    p c | isAlphaNum c = c+        | otherwise = '_'
src/Call/Types.hs view
@@ -1,233 +1,233 @@-{-# LANGUAGE DeriveFunctor, DeriveFoldable, DeriveTraversable, DeriveDataTypeable #-}
------------------------------------------------------------------------------
--- |
--- Module      :  Call.Types
--- Copyright   :  (c) Fumiaki Kinoshita 2014
--- License     :  BSD3
---
--- Maintainer  :  Fumiaki Kinoshita <fumiexcel@gmail.com>
--- Stability   :  experimental
--- Portability :  non-portable
---
------------------------------------------------------------------------------
-module Call.Types (
-    Time
-    , Vec2
-    , Vec3
-    , Stereo
-    , WindowMode(..)
-    , MouseEvent(..)
-    , Gamepad(..)
-    , GamepadEvent(..)
-    , Chatter(..)
-    , Key(..)
-    , charToKey
-    , BlendMode(..)
-    , Vertex(..)
-    , positionUV
-    , positionOnly
-    , Bitmap(..)
-    ) where
-
-import Control.Applicative
-import Linear
-import Data.Typeable
-import Data.Char
-import Foreign.Storable
-import Foreign.Ptr
-import Call.Data.Bitmap
-
-type Time = Float
-type Stereo = V2 Float
-type Vec2 = V2 Float
-type Vec3 = V3 Float
-data WindowMode = Windowed | Resizable | FullScreen deriving (Show, Eq, Ord, Read, Typeable)
-
-data Chatter a = Up a | Down a deriving (Show, Eq, Ord, Read, Typeable)
-
-data MouseEvent = Button (Chatter Int) | Cursor Vec2 | Scroll Vec2 deriving (Show, Eq, Ord, Read, Typeable)
-
-data Gamepad = Gamepad Int String deriving (Show, Eq, Ord, Read, Typeable)
-
-data GamepadEvent = PadButton Gamepad (Chatter Int) | PadConnection (Chatter Gamepad) deriving (Show, Eq, Ord, Read, Typeable)
-
-data Key =
-      KeyUnknown
-    | KeySpace
-    | KeyApostrophe
-    | KeyComma
-    | KeyMinus
-    | KeyPeriod
-    | KeySlash
-    | Key0
-    | Key1
-    | Key2
-    | Key3
-    | Key4
-    | Key5
-    | Key6
-    | Key7
-    | Key8
-    | Key9
-    | KeySemicolon
-    | KeyEqual
-    | KeyA
-    | KeyB
-    | KeyC
-    | KeyD
-    | KeyE
-    | KeyF
-    | KeyG
-    | KeyH
-    | KeyI
-    | KeyJ
-    | KeyK
-    | KeyL
-    | KeyM
-    | KeyN
-    | KeyO
-    | KeyP
-    | KeyQ
-    | KeyR
-    | KeyS
-    | KeyT
-    | KeyU
-    | KeyV
-    | KeyW
-    | KeyX
-    | KeyY
-    | KeyZ
-    | KeyLeftBracket
-    | KeyBackslash
-    | KeyRightBracket
-    | KeyGraveAccent
-    | KeyWorld1
-    | KeyWorld2
-    | KeyEscape
-    | KeyEnter
-    | KeyTab
-    | KeyBackspace
-    | KeyInsert
-    | KeyDelete
-    | KeyRight
-    | KeyLeft
-    | KeyDown
-    | KeyUp
-    | KeyPageUp
-    | KeyPageDown
-    | KeyHome
-    | KeyEnd
-    | KeyCapsLock
-    | KeyScrollLock
-    | KeyNumLock
-    | KeyPrintScreen
-    | KeyPause
-    | KeyF1
-    | KeyF2
-    | KeyF3
-    | KeyF4
-    | KeyF5
-    | KeyF6
-    | KeyF7
-    | KeyF8
-    | KeyF9
-    | KeyF10
-    | KeyF11
-    | KeyF12
-    | KeyF13
-    | KeyF14
-    | KeyF15
-    | KeyF16
-    | KeyF17
-    | KeyF18
-    | KeyF19
-    | KeyF20
-    | KeyF21
-    | KeyF22
-    | KeyF23
-    | KeyF24
-    | KeyF25
-    | KeyPad0
-    | KeyPad1
-    | KeyPad2
-    | KeyPad3
-    | KeyPad4
-    | KeyPad5
-    | KeyPad6
-    | KeyPad7
-    | KeyPad8
-    | KeyPad9
-    | KeyPadDecimal
-    | KeyPadDivide
-    | KeyPadMultiply
-    | KeyPadSubtract
-    | KeyPadAdd
-    | KeyPadEnter
-    | KeyPadEqual
-    | KeyLeftShift
-    | KeyLeftControl
-    | KeyLeftAlt
-    | KeyLeftSuper
-    | KeyRightShift
-    | KeyRightControl
-    | KeyRightAlt
-    | KeyRightSuper
-    | KeyMenu
-    deriving (Enum, Eq, Ord, Read, Show, Typeable, Bounded)
-
-charToKey :: Char -> Key
-charToKey ch
-    | isAlpha ch = toEnum $ fromEnum KeyA + fromEnum ch - fromEnum 'A'
-    | isDigit ch = toEnum $ fromEnum Key0 + fromEnum ch - fromEnum '0'
-charToKey '-' = KeyMinus
-charToKey ',' = KeyComma
-charToKey '.' = KeyPeriod
-charToKey '/' = KeySlash
-charToKey ' ' = KeySpace
-charToKey '\'' = KeyApostrophe
-charToKey '\\' = KeyBackslash
-charToKey '=' = KeyEqual
-charToKey ';' = KeySemicolon
-charToKey '[' = KeyLeftBracket
-charToKey ']' = KeyRightBracket
-charToKey '`' = KeyGraveAccent
-charToKey '\n' = KeyEnter
-charToKey '\r' = KeyEnter
-charToKey '\t' = KeyTab
-charToKey _ = KeyUnknown
-
-data BlendMode = Normal
-    | Inverse
-    | Add
-    | Multiply
-    | Screen
-    deriving (Enum, Eq, Ord, Read, Show, Typeable)
-
-data Vertex = Vertex { vPos :: {-# UNPACK #-} !Vec3
-  , vUV :: {-# UNPACK #-} !Vec2
-  , vNormal :: {-# UNPACK #-} !Vec3 }
-  deriving (Show, Eq, Ord, Read, Typeable)
-
-align1 :: Int
-align1 = sizeOf (vPos undefined)
-
-align2 :: Int
-align2 = align1 + sizeOf (vUV undefined)
-
-instance Storable Vertex where
-  sizeOf _ = sizeOf (undefined :: Vec3) + sizeOf (undefined :: Vec2) + sizeOf (undefined :: Vec3)
-  alignment _ = 0
-  peek ptr = Vertex
-    <$> peek (castPtr ptr)
-    <*> peek (castPtr $ ptr `plusPtr` align1)
-    <*> peek (castPtr $ ptr `plusPtr` align2)
-  poke ptr (Vertex v t n) = do
-    poke (castPtr ptr) v
-    poke (castPtr ptr `plusPtr` align1) t
-    poke (castPtr ptr `plusPtr` align2) n
-
-positionUV :: Vec3 -> Vec2 -> Vertex
-positionUV v p = Vertex v p zero
-
-positionOnly :: Vec3 -> Vertex
+{-# LANGUAGE DeriveFunctor, DeriveFoldable, DeriveTraversable, DeriveDataTypeable #-}+-----------------------------------------------------------------------------+-- |+-- Module      :  Call.Types+-- Copyright   :  (c) Fumiaki Kinoshita 2014+-- License     :  BSD3+--+-- Maintainer  :  Fumiaki Kinoshita <fumiexcel@gmail.com>+-- Stability   :  experimental+-- Portability :  non-portable+--+-----------------------------------------------------------------------------+module Call.Types (+    Time+    , Vec2+    , Vec3+    , Stereo+    , WindowMode(..)+    , MouseEvent(..)+    , Gamepad(..)+    , GamepadEvent(..)+    , Chatter(..)+    , Key(..)+    , charToKey+    , BlendMode(..)+    , Vertex(..)+    , positionUV+    , positionOnly+    , Bitmap(..)+    ) where++import Control.Applicative+import Linear+import Data.Typeable+import Data.Char+import Foreign.Storable+import Foreign.Ptr+import Call.Data.Bitmap++type Time = Float+type Stereo = V2 Float+type Vec2 = V2 Float+type Vec3 = V3 Float+data WindowMode = Windowed | Resizable | FullScreen deriving (Show, Eq, Ord, Read, Typeable)++data Chatter a = Up a | Down a deriving (Show, Eq, Ord, Read, Typeable)++data MouseEvent = Button (Chatter Int) | Cursor Vec2 | Scroll Vec2 deriving (Show, Eq, Ord, Read, Typeable)++data Gamepad = Gamepad Int String deriving (Show, Eq, Ord, Read, Typeable)++data GamepadEvent = PadButton Gamepad (Chatter Int) | PadConnection (Chatter Gamepad) deriving (Show, Eq, Ord, Read, Typeable)++data Key =+      KeyUnknown+    | KeySpace+    | KeyApostrophe+    | KeyComma+    | KeyMinus+    | KeyPeriod+    | KeySlash+    | Key0+    | Key1+    | Key2+    | Key3+    | Key4+    | Key5+    | Key6+    | Key7+    | Key8+    | Key9+    | KeySemicolon+    | KeyEqual+    | KeyA+    | KeyB+    | KeyC+    | KeyD+    | KeyE+    | KeyF+    | KeyG+    | KeyH+    | KeyI+    | KeyJ+    | KeyK+    | KeyL+    | KeyM+    | KeyN+    | KeyO+    | KeyP+    | KeyQ+    | KeyR+    | KeyS+    | KeyT+    | KeyU+    | KeyV+    | KeyW+    | KeyX+    | KeyY+    | KeyZ+    | KeyLeftBracket+    | KeyBackslash+    | KeyRightBracket+    | KeyGraveAccent+    | KeyWorld1+    | KeyWorld2+    | KeyEscape+    | KeyEnter+    | KeyTab+    | KeyBackspace+    | KeyInsert+    | KeyDelete+    | KeyRight+    | KeyLeft+    | KeyDown+    | KeyUp+    | KeyPageUp+    | KeyPageDown+    | KeyHome+    | KeyEnd+    | KeyCapsLock+    | KeyScrollLock+    | KeyNumLock+    | KeyPrintScreen+    | KeyPause+    | KeyF1+    | KeyF2+    | KeyF3+    | KeyF4+    | KeyF5+    | KeyF6+    | KeyF7+    | KeyF8+    | KeyF9+    | KeyF10+    | KeyF11+    | KeyF12+    | KeyF13+    | KeyF14+    | KeyF15+    | KeyF16+    | KeyF17+    | KeyF18+    | KeyF19+    | KeyF20+    | KeyF21+    | KeyF22+    | KeyF23+    | KeyF24+    | KeyF25+    | KeyPad0+    | KeyPad1+    | KeyPad2+    | KeyPad3+    | KeyPad4+    | KeyPad5+    | KeyPad6+    | KeyPad7+    | KeyPad8+    | KeyPad9+    | KeyPadDecimal+    | KeyPadDivide+    | KeyPadMultiply+    | KeyPadSubtract+    | KeyPadAdd+    | KeyPadEnter+    | KeyPadEqual+    | KeyLeftShift+    | KeyLeftControl+    | KeyLeftAlt+    | KeyLeftSuper+    | KeyRightShift+    | KeyRightControl+    | KeyRightAlt+    | KeyRightSuper+    | KeyMenu+    deriving (Enum, Eq, Ord, Read, Show, Typeable, Bounded)++charToKey :: Char -> Key+charToKey ch+    | isAlpha ch = toEnum $ fromEnum KeyA + fromEnum ch - fromEnum 'A'+    | isDigit ch = toEnum $ fromEnum Key0 + fromEnum ch - fromEnum '0'+charToKey '-' = KeyMinus+charToKey ',' = KeyComma+charToKey '.' = KeyPeriod+charToKey '/' = KeySlash+charToKey ' ' = KeySpace+charToKey '\'' = KeyApostrophe+charToKey '\\' = KeyBackslash+charToKey '=' = KeyEqual+charToKey ';' = KeySemicolon+charToKey '[' = KeyLeftBracket+charToKey ']' = KeyRightBracket+charToKey '`' = KeyGraveAccent+charToKey '\n' = KeyEnter+charToKey '\r' = KeyEnter+charToKey '\t' = KeyTab+charToKey _ = KeyUnknown++data BlendMode = Normal+    | Inverse+    | Add+    | Multiply+    | Screen+    deriving (Enum, Eq, Ord, Read, Show, Typeable)++data Vertex = Vertex { vPos :: {-# UNPACK #-} !Vec3+  , vUV :: {-# UNPACK #-} !Vec2+  , vNormal :: {-# UNPACK #-} !Vec3 }+  deriving (Show, Eq, Ord, Read, Typeable)++align1 :: Int+align1 = sizeOf (vPos undefined)++align2 :: Int+align2 = align1 + sizeOf (vUV undefined)++instance Storable Vertex where+  sizeOf _ = sizeOf (undefined :: Vec3) + sizeOf (undefined :: Vec2) + sizeOf (undefined :: Vec3)+  alignment _ = 0+  peek ptr = Vertex+    <$> peek (castPtr ptr)+    <*> peek (castPtr $ ptr `plusPtr` align1)+    <*> peek (castPtr $ ptr `plusPtr` align2)+  poke ptr (Vertex v t n) = do+    poke (castPtr ptr) v+    poke (castPtr ptr `plusPtr` align1) t+    poke (castPtr ptr `plusPtr` align2) n++positionUV :: Vec3 -> Vec2 -> Vertex+positionUV v p = Vertex v p zero++positionOnly :: Vec3 -> Vertex positionOnly v = Vertex v zero zero
src/Call/Util/Deck.hs view
@@ -1,59 +1,59 @@-{-# LANGUAGE Rank2Types #-}
-{-# LANGUAGE FlexibleContexts #-}
-{-# LANGUAGE LambdaCase #-}
-{-# LANGUAGE BangPatterns #-}
-{-# LANGUAGE ViewPatterns #-}
-{-# LANGUAGE TypeOperators #-}
-{-# LANGUAGE ConstraintKinds #-}
------------------------------------------------------------------------------
--- |
--- Module      :  Call.Util.Deck
--- Copyright   :  (c) Fumiaki Kinoshita 2014
--- License     :  BSD3
---
--- Maintainer  :  Fumiaki Kinoshita <fumiexcel@gmail.com>
--- Stability   :  experimental
--- Portability :  non-portable
---
--- The deck for a single stream
---
------------------------------------------------------------------------------
-module Call.Util.Deck (Deck(..), empty, source, pos, playing, playback, playbackOf) where
-import Control.Lens
-import Control.Monad.State.Strict
-import Call.Data.Wave
-import Call.Types
-import qualified Data.Vector.Storable as V
-import Control.Monad.Objective
-import Control.Elevator
-
-data Deck = Deck
-  { _src :: Source Stereo
-  , _pos :: !Time
-  , _playing :: !Bool }
-
-empty :: Deck
-empty = Deck (Source $ const 0) 0 False
-
-source :: Lens' Deck (Source Stereo)
-source f s = f (_src s) <&> \a -> s { _src = a }
-
-pos :: Lens' Deck Time
-pos f s = f (_pos s) <&> \a -> s { _pos = a }
-
-playing :: Lens' Deck Bool
-playing f s = f (_playing s) <&> \a -> s { _playing = a }
-
-playback :: MonadState Deck m => Time -> Int -> m (V.Vector Stereo)
-playback dt n = do
-  Source s <- use source
-  pl <- use playing
-  t0 <- use pos
-  if pl
-    then do
-      pos += dt
-      return $ V.fromList $ take n $ map s [t0,t0 + dt / fromIntegral n..]
-    else return $ V.replicate n 0
-
-playbackOf :: (MonadObjective b m, Elevate n m) => Inst b (State Deck) n -> Time -> Int -> m (V.Vector Stereo)
-playbackOf i = \dt n -> i .^ playback dt n
+{-# LANGUAGE Rank2Types #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE LambdaCase #-}+{-# LANGUAGE BangPatterns #-}+{-# LANGUAGE ViewPatterns #-}+{-# LANGUAGE TypeOperators #-}+{-# LANGUAGE ConstraintKinds #-}+-----------------------------------------------------------------------------+-- |+-- Module      :  Call.Util.Deck+-- Copyright   :  (c) Fumiaki Kinoshita 2014+-- License     :  BSD3+--+-- Maintainer  :  Fumiaki Kinoshita <fumiexcel@gmail.com>+-- Stability   :  experimental+-- Portability :  non-portable+--+-- The deck for a single stream+--+-----------------------------------------------------------------------------+module Call.Util.Deck (Deck(..), empty, source, pos, playing, playback, playbackOf) where+import Control.Lens+import Control.Monad.State.Strict+import Call.Data.Wave+import Call.Types+import qualified Data.Vector.Storable as V+import Control.Monad.Objective+import Control.Elevator++data Deck = Deck+  { _src :: Source Stereo+  , _pos :: !Time+  , _playing :: !Bool }++empty :: Deck+empty = Deck (Source $ const 0) 0 False++source :: Lens' Deck (Source Stereo)+source f s = f (_src s) <&> \a -> s { _src = a }++pos :: Lens' Deck Time+pos f s = f (_pos s) <&> \a -> s { _pos = a }++playing :: Lens' Deck Bool+playing f s = f (_playing s) <&> \a -> s { _playing = a }++playback :: MonadState Deck m => Time -> Int -> m (V.Vector Stereo)+playback dt n = do+  Source s <- use source+  pl <- use playing+  t0 <- use pos+  if pl+    then do+      pos += dt+      return $ V.fromList $ take n $ map s [t0,t0 + dt / fromIntegral n..]+    else return $ V.replicate n 0++playbackOf :: (MonadObjective b m, Elevate n m) => Inst b (State Deck) n -> Time -> Int -> m (V.Vector Stereo)+playbackOf i = \dt n -> i .- playback dt n
src/Call/Util/Sampler.hs view
@@ -1,53 +1,53 @@-{-# LANGUAGE FlexibleContexts, ConstraintKinds #-}
------------------------------------------------------------------------------
--- |
--- Module      :  Call.Util.Deck
--- Copyright   :  (c) Fumiaki Kinoshita 2014
--- License     :  BSD3
---
--- Maintainer  :  Fumiaki Kinoshita <fumiexcel@gmail.com>
--- Stability   :  experimental
--- Portability :  non-portable
---
--- Polyphonic sampler
---
------------------------------------------------------------------------------
-module Call.Util.Sampler where
-import qualified Data.Vector.Storable as V
-import qualified Data.Vector.Storable.Mutable as MV
-import Control.Monad.ST
-import Control.Monad.State.Strict
-import Call.Types
-import Call.Data.Wave
-import Control.Monad.Objective
-import Control.Elevator
-
-data Sampler = Sampler [(Sample Stereo, Time)]
-
-empty :: Sampler
-empty = Sampler []
-
-playback :: MonadState Sampler m => Time -> Int -> m (V.Vector Stereo)
-playback dt n = do
-  Sampler vs <- get
-  let (vs'', r) = runST $ do
-        v <- MV.new n
-        vs' <- forM vs $ \(s0@(Sample d (Source s)), t0) -> do
-          if d > t0 then return []
-            else do
-              forM_ [0..n-1] $ \i -> do
-                z <- MV.unsafeRead v i
-                MV.unsafeWrite v i $ z + s (t0 + f * fromIntegral i)
-              return [(s0, t0 + dt)]
-        v' <- V.unsafeFreeze v
-        return (vs', v')
-  put $ Sampler $ concat vs''
-  return r
-  where
-    f = dt / fromIntegral n
-
-play :: MonadState Sampler m => Sample Stereo -> m ()
-play s = modify $ \(Sampler xs) -> Sampler $ (s, 0) : xs
-
-playbackOf :: (MonadObjective b m, Elevate n m) => Inst b (State Sampler) n -> Time -> Int -> m (V.Vector Stereo)
-playbackOf i = \dt n -> i .^ playback dt n
+{-# LANGUAGE FlexibleContexts, ConstraintKinds #-}+-----------------------------------------------------------------------------+-- |+-- Module      :  Call.Util.Deck+-- Copyright   :  (c) Fumiaki Kinoshita 2014+-- License     :  BSD3+--+-- Maintainer  :  Fumiaki Kinoshita <fumiexcel@gmail.com>+-- Stability   :  experimental+-- Portability :  non-portable+--+-- Polyphonic sampler+--+-----------------------------------------------------------------------------+module Call.Util.Sampler where+import qualified Data.Vector.Storable as V+import qualified Data.Vector.Storable.Mutable as MV+import Control.Monad.ST+import Control.Monad.State.Strict+import Call.Types+import Call.Data.Wave+import Control.Monad.Objective+import Control.Elevator++data Sampler = Sampler [(Sample Stereo, Time)]++empty :: Sampler+empty = Sampler []++playback :: MonadState Sampler m => Time -> Int -> m (V.Vector Stereo)+playback dt n = do+  Sampler vs <- get+  let (vs'', r) = runST $ do+        v <- MV.new n+        vs' <- forM vs $ \(s0@(Sample d (Source s)), t0) -> do+          if d > t0 then return []+            else do+              forM_ [0..n-1] $ \i -> do+                z <- MV.unsafeRead v i+                MV.unsafeWrite v i $ z + s (t0 + f * fromIntegral i)+              return [(s0, t0 + dt)]+        v' <- V.unsafeFreeze v+        return (vs', v')+  put $ Sampler $ concat vs''+  return r+  where+    f = dt / fromIntegral n++play :: MonadState Sampler m => Sample Stereo -> m ()+play s = modify $ \(Sampler xs) -> Sampler $ (s, 0) : xs++playbackOf :: (MonadObjective b m, Elevate n m) => Inst b (State Sampler) n -> Time -> Int -> m (V.Vector Stereo)+playbackOf i = \dt n -> i .- playback dt n
src/Call/Util/Text.hs view
@@ -1,55 +1,56 @@-{-# LANGUAGE ConstraintKinds, FlexibleContexts, BangPatterns #-}
-module Call.Util.Text where
-import Prelude hiding (putStr)
-import Call.Data.Bitmap (Bitmap(..))
-import Call.Data.Font
-import Call.Sight
-import Control.Lens
-import Control.Monad.Objective
-import Control.Monad.Operational.Mini
-import Control.Monad.State.Class
-import Control.Monad.Trans
-import Control.Object
-import Data.Functor.PushPull
-import Data.Functor.Request
-import Data.Monoid
-import Linear
-import Control.DeepSeq
-
-renderer :: MonadIO m => Font -> Float -> Object (Request Char (Bitmap, V2 Float, V2 Float)) m
-renderer font size = flyweight (liftIO . renderChar font size)
-
-typewriter :: MonadIO m => Float -> (Char -> m (Bitmap, V2 Float, V2 Float)) -> Object (ReifiedProgram (PushPull Char Picture)) m
-typewriter l req = sequential $ stateful go (V2 0 0, mempty) where
-  go (Push '\3' cont) = do
-    put (V2 0 0, mempty)
-    return cont
-  go (Push '\r' cont) = return cont
-  go (Push '\n' cont) = do
-    _1 . _y += l
-    _1 . _x .= 0
-    return cont
-  go (Push ch cont) = do
-    (pos, pic) <- get
-    (!bmp@(Bitmap img _ _), !ofs, !adv) <- lift $ req ch
-    return $! rnf img
-    put (pos + adv, pic <> translate (pos + ofs) (bitmap bmp))
-    return cont
-  go (Pull cont) = uses _2 cont
-
-putStr :: String -> ReifiedProgram (PushPull Char Picture) ()
-putStr [] = return ()
-putStr (c:cs) = Push c () :>>= const (putStr cs)
-
-clear :: ReifiedProgram (PushPull Char Picture) ()
-clear = Push '\3' () :>>= return
-
-simple :: MonadIO m => Font -> Float -> m (String -> Picture)
-simple font size = liftIO $ do
-  r <- new $ renderer font size
-  t <- new $ typewriter (size * 1.2) ((r.-) . request)
-  return $ \s -> Picture $ applyVFX $ EmbedIO $ do
-    t .- putStr s
-    p <- t .- (Pull id :>>= return)
-    t .- clear
-    return $! unPicture p
+{-# LANGUAGE ConstraintKinds, FlexibleContexts, BangPatterns #-}+module Call.Util.Text (renderer, typewriter, putStr, clear, simple) where+import Prelude hiding (putStr)+import Call.Data.Bitmap (Bitmap(..))+import Call.Data.Font+import Call.Sight+import Control.Lens hiding (simple)+import Control.Monad.Objective+import Control.Monad.Operational.Mini+import Control.Monad.State.Class+import Control.Monad.Trans+import Control.Object+import Data.Monoid+import Linear+import Control.DeepSeq++renderer :: MonadIO m => Font -> Float -> Object (Request Char (Bitmap, V2 Float, V2 Float)) m+renderer font size = flyweight (liftIO . renderChar font size)++typewriter :: MonadIO m => Float -> (Char -> m (Bitmap, V2 Float, V2 Float)) -> Object (ReifiedProgram (PushPull Char Picture)) m+typewriter l req = sequential $ stateful go (V2 0 0, mempty) where+  go (Push '\3' cont) = do+    put (V2 0 0, mempty)+    return cont+  go (Push '\r' cont) = return cont+  go (Push '\n' cont) = do+    _1 . _y += l+    _1 . _x .= 0+    return cont+  go (Push ch cont) = do+    (pos, pic) <- get+    (!bmp@(Bitmap img _ _), !ofs, !adv) <- lift $ req ch+    return $! rnf img+    put (pos + adv, pic <> translate (pos + ofs) (bitmap bmp))+    return cont+  go (Pull cont) = uses _2 cont++putStr :: String -> ReifiedProgram (PushPull Char Picture) ()+putStr [] = return ()+putStr (c:cs) = Push c () :>>= const (putStr cs)++clear :: ReifiedProgram (PushPull Char Picture) ()+clear = Push '\3' () :>>= return++new' :: ObjectiveBase b => Object f b -> b (Inst b f b)+new' = new++simple :: MonadIO m => Font -> Float -> m (String -> Picture)+simple font size = liftIO $ do+  r <- new' $ renderer font size+  t <- new' $ typewriter (size * 1.2) ((r.-) . request)+  return $ \s -> Picture $ applyVFX $ EmbedIO $ do+    t .- putStr s+    p <- t .- (Pull id :>>= return)+    t .- clear+    return $! unPicture p