rhine-gloss 0.4.0.4 → 0.5.0.0
raw patch · 6 files changed
+96/−64 lines, 6 filesdep ~rhinePVP ok
version bump matches the API change (PVP)
Dependency ranges changed: rhine
API changes (from Hackage documentation)
- FRP.Rhine.Gloss: type GlossSyncSF a = SyncSF Identity GlossSimulationClock [a] Picture
+ FRP.Rhine.Gloss: type GlossClSF a = ClSF Identity GlossSimulationClock [a] Picture
- FRP.Rhine.Gloss: buildGlossRhine :: (Event -> Maybe a) -> GlossSyncSF a -> GlossRhine a
+ FRP.Rhine.Gloss: buildGlossRhine :: (Event -> Maybe a) -> GlossClSF a -> GlossRhine a
Files
- ChangeLog.md +6/−2
- Main.hs +4/−4
- README.md +26/−0
- rhine-gloss.cabal +12/−9
- src/FRP/Rhine/Gloss.hs +15/−18
- src/FRP/Rhine/Gloss/Internals.hs +33/−31
ChangeLog.md view
@@ -1,9 +1,13 @@ # Revision history for rhine-gloss -## 0.2.0.0 -- 2017-11-29+## 0.4.0.0 -- 2017.12.04 -* First version. Version numbers follow rhine.+* Version bump ## 0.3.0.0 -- 2017-11-30 * Added simple example.++## 0.2.0.0 -- 2017-11-29++* First version. Version numbers follow rhine.
Main.hs view
@@ -12,9 +12,9 @@ : map (rotate angle) [ rotate (45 * n) $ rectangleSolid 20 150 | n <- [0..3] ] -- | Rotate the gear with a constant angular velocity.-mainSyncSF :: GlossSyncSF a-mainSyncSF = timeInfoOf sinceStart >>> arr (* 50) >>> arr gears+mainClSF :: GlossClSF a+mainClSF = timeInfoOf sinceInit >>> arr (* 50) >>> arr gears main :: IO ()-main = flowGloss (InWindow "sonnen" (400, 400) (10, 10)) (greyN 0.3) 30- $ buildGlossRhine Just mainSyncSF+main = flowGloss (InWindow "rhine-gloss-gears" (400, 400) (10, 10)) (greyN 0.3) 30+ $ buildGlossRhine Just mainClSF
+ README.md view
@@ -0,0 +1,26 @@+# README++This package provides a simple wrapper for the `gloss` library,+or rather the function `Graphics.Gloss.play`,+enabling you to write `gloss` applications as signal functions.+An example "gears" program, which you can run as `cabal run gloss-gears`,+now becomes as simple as:++```haskell+import FRP.Rhine.Gloss+++-- | Calculate a gear wheel rotated by a certain angle.+gears :: Float -> Picture+gears angle = color green $ pictures+ $ circleSolid 60+ : map (rotate angle) [ rotate (45 * n) $ rectangleSolid 20 150 | n <- [0..3] ]++-- | Rotate the gear with a constant angular velocity.+mainClSF :: GlossClSF a+mainClSF = timeInfoOf sinceInit >>> arr (* 50) >>> arr gears++main :: IO ()+main = flowGloss (InWindow "rhine-gloss-gears" (400, 400) (10, 10)) (greyN 0.3) 30+ $ buildGlossRhine Just mainClSF+```
rhine-gloss.cabal view
@@ -2,10 +2,12 @@ -- documentation, see http://haskell.org/cabal/users-guide/ name: rhine-gloss-version: 0.4.0.4+version: 0.5.0.0 synopsis: Gloss backend for Rhine-description: Wrapper to run reactive programs written in Rhine- with Gloss as backend+description:+ This package provides a simple wrapper for the `gloss` library,+ or rather the function `Graphics.Gloss.play`,+ enabling you to write `gloss` applications as signal functions. license: BSD3 license-file: LICENSE author: Manuel Bärenz@@ -14,7 +16,8 @@ category: FRP build-type: Simple extra-source-files: ChangeLog.md-cabal-version: >=1.18+extra-doc-files: README.md+cabal-version: 1.18 source-repository head type: git@@ -23,15 +26,15 @@ source-repository this type: git location: git@github.com:turion/rhine.git- tag: v0.4.0.4+ tag: v0.5.0.0 library exposed-modules: FRP.Rhine.Gloss other-modules: FRP.Rhine.Gloss.Internals- build-depends: base >= 4.9 && < 4.12- , rhine == 0.4.*- , dunai == 0.4.*+ build-depends: base >= 4.9 && < 4.12+ , rhine == 0.5.*+ , dunai == 0.4.* , gloss >= 1.12 && < 1.14 hs-source-dirs: src default-language: Haskell2010@@ -39,6 +42,6 @@ executable rhine-gloss-gears main-is: Main.hs ghc-options: -threaded- build-depends: base >= 4.9 && < 4.12+ build-depends: base >= 4.9 && < 4.12 , rhine-gloss default-language: Haskell2010
src/FRP/Rhine/Gloss.hs view
@@ -6,9 +6,9 @@ In order to run such a reactive program, you have to use 'flowGloss'. -} {-# LANGUAGE FlexibleContexts #-}-{-# LANGUAGE NamedFieldPuns #-}-{-# LANGUAGE RecordWildCards #-}-{-# LANGUAGE TypeFamilies #-}+{-# LANGUAGE NamedFieldPuns #-}+{-# LANGUAGE RecordWildCards #-}+{-# LANGUAGE TypeFamilies #-} module FRP.Rhine.Gloss ( module FRP.Rhine.Gloss , module X@@ -26,14 +26,11 @@ import qualified Graphics.Gloss as X -- rhine-import FRP.Rhine-import FRP.Rhine.Clock.Select+import FRP.Rhine hiding (trivialResamplingBuffer) import FRP.Rhine.Reactimation.Tick-import FRP.Rhine.ResamplingBuffer.Collect-import FRP.Rhine.ResamplingBuffer.KeepLast -import qualified FRP.Rhine as X-import qualified FRP.Rhine.SyncSF as X+import qualified FRP.Rhine as X+import qualified FRP.Rhine.ClSF as X -- rhine-gloss import FRP.Rhine.Gloss.Internals@@ -41,7 +38,7 @@ -- TODO Consider generalising to IO --- | The overall clock of a valid @rhine@ 'SF' that can be run by @gloss@.+-- | The overall clock of a valid @rhine@ 'SN' that can be run by @gloss@. -- @a@ is the type of subevents that are selected. type GlossClock a = SequentialClock Identity@@ -52,24 +49,24 @@ -- @a@ is the type of subevents that are selected. type GlossRhine a = Rhine Identity (GlossClock a) () Picture --- | The type of a 'SyncSF' that you have to implement to get a @gloss@ app.-type GlossSyncSF a = SyncSF Identity GlossSimulationClock [a] Picture+-- | The type of a 'ClSF' that you have to implement to get a @gloss@ app.+type GlossClSF a = ClSF Identity GlossSimulationClock [a] Picture {- | For most applications, it is sufficient to implement-a single synchronous signal function+a single signal function that is called with a list of all relevant events that occurred in the last tick. -} buildGlossRhine :: (Event -> Maybe a) -- ^ The event selector- -> GlossSyncSF a -- ^ The 'SyncSF' representing the game loop.+ -> GlossClSF a -- ^ The 'ClSF' representing the game loop. -> GlossRhine a-buildGlossRhine select syncsfSim+buildGlossRhine select clsfSim = timeInfoOf tag @@ SelectClock { mainClock = GlossEventClock, .. } >-- collect -@- glossSchedule- --> withProperSimClock syncsfSim @@ GlossSimulationClock_+ --> withProperSimClock clsfSim @@ GlossSimulationClock_ --- | The main function that will start the @gloss@ backend and run the 'SF'.+-- | The main function that will start the @gloss@ backend and run the 'SN'. flowGloss :: Display -- ^ Display mode (e.g. 'InWindow' or 'FullScreen'). -> Color -- ^ Background color.@@ -84,7 +81,7 @@ GlossSimulationClock_ GlossGraphicsClock Picture Picture graphicsBuffer = keepLast Blank- world = createTickable (trivialResamplingBuffer clock) sf graphicsBuffer ()+ world = createTickable (trivialResamplingBuffer clock) sn graphicsBuffer () getPic Tickable { buffer2 } = fst $ runIdentity $ get buffer2 $ TimeInfo () () () () handleEvent event tickable = case select (sequentialCl1 clock) event of Just a -> runIdentity $ tick tickable () $ Left a -- Event is relevant
src/FRP/Rhine/Gloss/Internals.hs view
@@ -1,12 +1,12 @@ {- | Internals for 'FRP.Rhine.Gloss'. You probably won't need this module. -}-{-# LANGUAGE Arrows #-}-{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE Arrows #-}+{-# LANGUAGE FlexibleInstances #-} {-# LANGUAGE MultiParamTypeClasses #-}-{-# LANGUAGE NamedFieldPuns #-}-{-# LANGUAGE RecordWildCards #-}-{-# LANGUAGE TypeFamilies #-}+{-# LANGUAGE NamedFieldPuns #-}+{-# LANGUAGE RecordWildCards #-}+{-# LANGUAGE TypeFamilies #-} module FRP.Rhine.Gloss.Internals where @@ -21,68 +21,70 @@ import Graphics.Gloss.Interface.Pure.Game -- rhine-import FRP.Rhine-import FRP.Rhine.Clock.Select+import FRP.Rhine hiding (readerS, runReaderS) -- * Clocks --- | The error message that gets thrown when you try to start a @gloss@ app with 'flow'.+-- | The error message that gets thrown when you try to start a pure @rhine-gloss@ app with 'flow'. errMsg :: String-errMsg = "You cannot start gloss apps with FRP.Rhine.flow. "- ++ "Use FRP.Rhine.Gloss.flowGloss instead."+errMsg = unwords+ [ "You cannot start pure rhine-gloss apps with FRP.Rhine.flow,"+ , "since gloss has its own main loop."+ , "Use FRP.Rhine.Gloss.flowGloss instead."+ ] -- | The clock that ticks whenever a @gloss@ event occurs. data GlossEventClock = GlossEventClock instance Clock m GlossEventClock where- type TimeDomainOf GlossEventClock = ()- type Tag GlossEventClock = Event- startClock _ = error errMsg+ type Time GlossEventClock = ()+ type Tag GlossEventClock = Event+ initClock _ = error errMsg -- | The clock that ticks for every @gloss@ simulation step,--- but only shows the time delta in the tag.+-- but only shows the time /differences/ in the tag. -- Usually, you don't need this clock, but rather 'GlossSimulationClock'. data GlossSimulationClock_ = GlossSimulationClock_ instance Clock m GlossSimulationClock_ where- type TimeDomainOf GlossSimulationClock_ = ()- type Tag GlossSimulationClock_ = Float- startClock _ = error errMsg+ type Time GlossSimulationClock_ = ()+ type Tag GlossSimulationClock_ = Float+ initClock _ = error errMsg -- | The clock that ticks for every @gloss@ simulation step. -- Use 'withProperSimClock' to transform to 'GlossSimulationClock_'. data GlossSimulationClock = GlossSimulationClock instance Clock m GlossSimulationClock where- type TimeDomainOf GlossSimulationClock = Float- type Tag GlossSimulationClock = ()- startClock _ = error errMsg+ type Time GlossSimulationClock = Float+ type Tag GlossSimulationClock = ()+ initClock _ = error errMsg --- | To use all features of the 'SyncSF' framework,+-- | To use all features of the 'ClSF' framework, -- write your synchronous stream function on the 'GlossSimulationClock' -- and then use this function to transform it. withProperSimClock :: Monad m- => SyncSF m GlossSimulationClock a b- -> SyncSF m GlossSimulationClock_ a b-withProperSimClock syncsf = readerS- $ (intermingle *** Category.id) >>> runReaderS syncsf+ => ClSF m GlossSimulationClock a b+ -> ClSF m GlossSimulationClock_ a b+withProperSimClock clsf = readerS+ $ (intermingle *** Category.id) >>> runReaderS clsf where intermingle :: Monad m => MSF m (TimeInfo GlossSimulationClock_) (TimeInfo GlossSimulationClock) intermingle = proc TimeInfo {tag} -> do- let sinceTick = tag- absolute <- sumS -< sinceTick- let sinceStart = absolute+ let sinceLast = tag+ absolute <- sumS -< sinceLast+ let sinceInit = absolute returnA -< TimeInfo { tag = (), .. } -- | The clock that ticks for every @gloss@ graphics output. data GlossGraphicsClock = GlossGraphicsClock instance Clock m GlossGraphicsClock where- type TimeDomainOf GlossGraphicsClock = ()- type Tag GlossGraphicsClock = ()- startClock _ = error errMsg+ type Time GlossGraphicsClock = ()+ type Tag GlossGraphicsClock = ()+ initClock _ = error errMsg -- | A schedule you can't actually use, for internal purposes. glossSchedule :: Schedule Identity (SelectClock GlossEventClock a) GlossSimulationClock_