packages feed

helm 0.1.0 → 0.2.0

raw patch · 7 files changed

+605/−254 lines, 7 filesPVP ok

version bump matches the API change (PVP)

API changes (from Hackage documentation)

- FRP.Helm.Graphics: type Shape = [(Double, Double)]
- FRP.Helm.Keyboard: Keypad0Key :: Key
- FRP.Helm.Keyboard: Keypad1Key :: Key
- FRP.Helm.Keyboard: Keypad2Key :: Key
- FRP.Helm.Keyboard: Keypad3Key :: Key
- FRP.Helm.Keyboard: Keypad4Key :: Key
- FRP.Helm.Keyboard: Keypad5Key :: Key
- FRP.Helm.Keyboard: Keypad6Key :: Key
- FRP.Helm.Keyboard: Keypad7Key :: Key
- FRP.Helm.Keyboard: Keypad8Key :: Key
- FRP.Helm.Keyboard: Keypad9Key :: Key
+ FRP.Helm.Color: complement :: Color -> Color
+ FRP.Helm.Color: hsv :: Double -> Double -> Double -> Color
+ FRP.Helm.Color: hsva :: Double -> Double -> Double -> Double -> Color
+ FRP.Helm.Graphics: ArcShape :: (Double, Double) -> Double -> Double -> Double -> (Double, Double) -> Shape
+ FRP.Helm.Graphics: PolygonShape :: Path -> Shape
+ FRP.Helm.Graphics: RectangleShape :: (Double, Double) -> Shape
+ FRP.Helm.Graphics: data Shape
+ FRP.Helm.Graphics: fittedImage :: Int -> Int -> FilePath -> Element
+ FRP.Helm.Keyboard: KKey :: Key
+ FRP.Helm.Keyboard: KeypadNum0Key :: Key
+ FRP.Helm.Keyboard: KeypadNum1Key :: Key
+ FRP.Helm.Keyboard: KeypadNum2Key :: Key
+ FRP.Helm.Keyboard: KeypadNum3Key :: Key
+ FRP.Helm.Keyboard: KeypadNum4Key :: Key
+ FRP.Helm.Keyboard: KeypadNum5Key :: Key
+ FRP.Helm.Keyboard: KeypadNum6Key :: Key
+ FRP.Helm.Keyboard: KeypadNum7Key :: Key
+ FRP.Helm.Keyboard: KeypadNum8Key :: Key
+ FRP.Helm.Keyboard: KeypadNum9Key :: Key
+ FRP.Helm.Keyboard: ModeKey :: Key
+ FRP.Helm.Keyboard: instance Enum Key
+ FRP.Helm.Keyboard: isDown :: Key -> SignalGen (Signal Bool)
+ FRP.Helm.Keyboard: keysDown :: SignalGen (Signal [Key])
- FRP.Helm: degrees :: Float -> Float
+ FRP.Helm: degrees :: Double -> Double
- FRP.Helm: radians :: Float -> Float
+ FRP.Helm: radians :: Double -> Double
- FRP.Helm: turns :: Float -> Float
+ FRP.Helm: turns :: Double -> Double
- FRP.Helm.Graphics: polygon :: [(Double, Double)] -> Shape
+ FRP.Helm.Graphics: polygon :: Path -> Shape

Files

FRP/Helm.hs view
@@ -1,8 +1,13 @@+{-| Contains miscellaneous utility functions and the main+    functions for interfacing with the engine. -} module FRP.Helm (+  -- * Engine+  run,+  -- * Utilities   radians,   degrees,   turns,-  run,+  -- * Prelude   module FRP.Helm.Color,   module FRP.Helm.Graphics, ) where@@ -20,6 +25,7 @@ {-| Attempt to change the window dimensions (and initialize the video mode if not already).     Will try to get a hardware accelerated window and then fallback to a software one.     Throws an exception if the software mode can't be used as a fallback. -}+-- TODO: userland version of this requestDimensions :: Int -> Int -> IO SDL.Surface requestDimensions w h =	do   mayhaps <- SDL.trySetVideoMode w h 32 [SDL.HWSurface, SDL.DoubleBuf, SDL.Resizable]@@ -28,19 +34,22 @@     Just screen -> return screen     Nothing -> SDL.setVideoMode w h 32 [SDL.SWSurface, SDL.Resizable] --- |Converts radians into the standard angle measurement (radians).-radians :: Float -> Float+{-| Converts radians into the standard angle measurement (radians). -}+radians :: Double -> Double radians n = n --- |Converts degrees into the standard angle measurement (radians).-degrees :: Float -> Float+{-| Converts degrees into the standard angle measurement (radians). -}+degrees :: Double -> Double degrees n = n * pi / 180  {-| Converts turns into the standard angle measurement (radians).     Turns are essentially full revolutions of the unit circle. -}-turns :: Float -> Float+turns :: Double -> Double turns n = 2 * pi * n +{-| A data structure describing the current engine state.+    This may be in userland in the future, for setting+    window dimensions, title, etc. -} data EngineState = EngineState {   smp :: IO Element,   {- FIXME: we need this mutable state (unfortunately) @@ -51,6 +60,7 @@   cache :: IORef (Map.Map FilePath Cairo.Surface) } +{-| Creates a new engine state, spawning an empty cache spawned in an IORef. -} newEngineState :: IO Element -> IO EngineState newEngineState smp = do   cache <- newIORef Map.empty@@ -58,16 +68,34 @@   return EngineState { smp = smp, cache = cache }  {-| Initializes and runs the game engine. The supplied signal generator is-    constantly sampled  for an element to render until the user quits. -}+    constantly sampled  for an element to render until the user quits.++    > import FRP.Helm+    > import qualified FRP.Helm.Window as Window+    >+    > render :: (Int, Int) -> Element+    > render (w, h) = collage w h [filled red $ rect (fromIntegral w) (fromIntegral h)]+    >+    > main :: IO ()+    > main = run $ do+    >   dims <- Window.dimensions+    >+    >   return $ fmap render dims+ -} run :: SignalGen (Signal Element) -> IO () run gen = SDL.init [SDL.InitVideo] >> requestDimensions 800 600 >> start gen >>= newEngineState >>= run' +{-| A utility function called by 'run' that samples the element+    or quits the entire engine if SDL events say to do so. -} run' :: EngineState -> IO () run' state = do   continue <- run''    if continue then smp state >>= render state >> run' state else SDL.quit +{-| A utility function called by 'run\'' that polls all SDL events+    off the stack, returning true if the game should keep running,+    false otherwise. -} run'' :: IO Bool run'' = do   event <- SDL.pollEvent@@ -78,9 +106,13 @@     SDL.VideoResize w h -> requestDimensions w h >> run''     _ -> run'' +{-| A utility function that renders a previously sampled element+    using an engine state. -} render :: EngineState -> Element -> IO () render state element = SDL.getVideoSurface >>= render' state element +{-| A utility function called by 'render\'' that does+    the actual heavy lifting. -} render' :: EngineState -> Element -> SDL.Surface -> IO () render' state element screen = do     pixels <- SDL.surfaceGetPixels screen@@ -94,6 +126,8 @@     w = SDL.surfaceGetWidth screen     h = SDL.surfaceGetHeight screen +{-| A utility function called by 'render\'\'' that is called by Cairo+    when it's ready to do rendering. -} render'' :: Int -> Int -> EngineState -> Element -> Cairo.Render () render'' w h state element = do   Cairo.setSourceRGB 0 0 0@@ -102,37 +136,53 @@    renderElement state element -getSurface :: EngineState -> FilePath -> IO Cairo.Surface+{-| A utility function that lazily grabs an image surface from the cache,+    i.e. creating it if it's not already stored in it. -}+getSurface :: EngineState -> FilePath -> IO (Cairo.Surface, Int, Int) getSurface (EngineState { cache }) src = do   cached <- Cairo.liftIO (readIORef cache)    case Map.lookup src cached of-    Just surface -> return surface+    Just surface -> do+      w <- Cairo.imageSurfaceGetWidth surface+      h <- Cairo.imageSurfaceGetHeight surface++      return (surface, w, h)     Nothing -> do       -- TODO: Use SDL_image to support more formats. I gave up after it was painful       -- to convert between the two surface types safely.       -- FIXME: Does this throw an error?       surface <- Cairo.imageSurfaceCreateFromPNG src--      writeIORef cache (Map.insert src surface cached) >> return surface+      w <- Cairo.imageSurfaceGetWidth surface+      h <- Cairo.imageSurfaceGetHeight surface +      writeIORef cache (Map.insert src surface cached) >> return (surface, w, h) +{-| A utility function for rendering a specific element. -} renderElement :: EngineState -> Element -> Cairo.Render () renderElement state (CollageElement _ _ forms) = mapM (renderForm state) forms >> return ()-renderElement state (ImageElement (sx, sy) sw sh src _) = do-  surface <- Cairo.liftIO $ getSurface state (normalise src)+renderElement state (ImageElement (sx, sy) sw sh src stretch) = do+  (surface, w, h) <- Cairo.liftIO $ getSurface state (normalise src)    Cairo.save   Cairo.translate (-fromIntegral sx) (-fromIntegral sy)++  if stretch then+    Cairo.scale (fromIntegral sw / fromIntegral w) (fromIntegral sh / fromIntegral h)+  else+    Cairo.scale 1 1+   Cairo.setSourceSurface surface 0 0   Cairo.translate (fromIntegral sx) (fromIntegral sy)   Cairo.rectangle 0 0 (fromIntegral sw) (fromIntegral sh)   Cairo.fill   Cairo.restore +{-| A utility function that goes into a state of transformation and then pops it when finished. -} withTransform :: Double -> Double -> Double -> Double -> Cairo.Render () -> Cairo.Render () withTransform s t x y f = Cairo.save >> Cairo.scale s s >> Cairo.rotate t >> Cairo.translate x y >> f >> Cairo.restore +{-| A utility function that sets the Cairo line cap based off of our version. -} setLineCap :: LineCap -> Cairo.Render () setLineCap cap =    case cap of@@ -140,6 +190,7 @@     Round -> Cairo.setLineCap Cairo.LineCapRound     Padded -> Cairo.setLineCap Cairo.LineCapSquare +{-| A utility function that sets the Cairo line style based off of our version. -} setLineJoin :: LineJoin -> Cairo.Render () setLineJoin join =   case join of@@ -147,15 +198,21 @@     Sharp lim -> Cairo.setLineJoin Cairo.LineJoinMiter >> Cairo.setMiterLimit lim     Clipped -> Cairo.setLineJoin Cairo.LineJoinBevel +{-| A utility function that sets up all the necessary settings with Cairo+    to render with a line style and then strokes afterwards. Assumes+    that all drawing paths have already been setup before being called. -} setLineStyle :: LineStyle -> Cairo.Render () setLineStyle (LineStyle { color = Color r g b a, .. }) =   Cairo.setSourceRGBA r g b a >> setLineCap cap >> setLineJoin join >>   Cairo.setLineWidth width >> Cairo.setDash dashing dashOffset >> Cairo.stroke +{-| A utility function that sets up all the necessary settings with Cairo+    to render with a fill style and then fills afterwards. Assumes+    that all drawing paths have already been setup before being called. -} setFillStyle :: EngineState -> FillStyle -> Cairo.Render () setFillStyle _ (Solid (Color r g b a)) = Cairo.setSourceRGBA r g b a >> Cairo.fill setFillStyle state (Texture src) = do-  surface <- Cairo.liftIO $ getSurface state (normalise src)+  (surface, w, h) <- Cairo.liftIO $ getSurface state (normalise src)    Cairo.setSourceSurface surface 0 0 >> Cairo.getSource >>= (flip Cairo.patternSetExtend) Cairo.ExtendRepeat   Cairo.fill@@ -168,6 +225,7 @@   Cairo.withRadialPattern sx sy sr ex ey er $ \pattern -> do     Cairo.setSource pattern >> mapM (\(o, (Color r g b a)) -> Cairo.patternAddColorStopRGBA pattern o r g b a) points >> Cairo.fill +{-| A utility that renders a form. -} renderForm :: EngineState -> Form -> Cairo.Render () renderForm _ (Form { style = PathForm style p, .. }) =   withTransform scalar theta x y $ @@ -176,16 +234,34 @@     where       (hx, hy) = head p -renderForm state (Form { style = ShapeForm style shape, .. }) =+renderForm state (Form { style = ShapeForm style (PolygonShape points), .. }) =   withTransform scalar theta x y $ do-      Cairo.newPath >> Cairo.moveTo hx hy >> mapM (\(x_, y_) -> Cairo.lineTo x_ y_) shape >> Cairo.closePath+      Cairo.newPath >> Cairo.moveTo hx hy >> mapM (\(x_, y_) -> Cairo.lineTo x_ y_) points >> Cairo.closePath        case style of         Left lineStyle -> setLineStyle lineStyle         Right fillStyle -> setFillStyle state fillStyle      where-      (hx, hy) = head shape+      (hx, hy) = head points++renderForm state (Form { style = ShapeForm style (RectangleShape (w, h)), .. }) =+  withTransform scalar theta x y $ do+    Cairo.rectangle 0 0 w h++    case style of+      Left lineStyle -> setLineStyle lineStyle+      Right fillStyle -> setFillStyle state fillStyle++renderForm state (Form { style = ShapeForm style (ArcShape (cx, cy) a1 a2 r (sx, sy)), .. }) =+  withTransform scalar theta x y $ do+    Cairo.scale sx sy+    Cairo.arc cx cy r a1 a2+    Cairo.scale 1 1++    case style of+      Left lineStyle -> setLineStyle lineStyle+      Right fillStyle -> setFillStyle state fillStyle  renderForm state (Form { style = ElementForm element, .. }) = withTransform scalar theta x y $ renderElement state element renderForm state (Form { style = GroupForm m forms, .. }) = withTransform scalar theta x y $ Cairo.setMatrix m >> mapM (renderForm state) forms >> return ()
FRP/Helm/Color.hs view
@@ -1,83 +1,177 @@-module FRP.Helm.Color where+{-| Contains all data structures and functions for composing colors. -}+module FRP.Helm.Color (+	-- * Types+	Color(..),+	Gradient(..),+	-- * Composing+	rgba,+	rgb,+  hsva,+  hsv,+  complement,+	linear,+	radial,+	-- * Constants+	red,+	lime,+	blue,+	yellow,+	cyan,+	magenta,+	black,+	white,+	gray,+	grey,+	maroon,+	navy,+	green,+	teal,+	purple,+	violet,+	forestGreen+) where +{-| A data structure describing a color. It is represented interally as an RGBA+    color, but the utility functions 'hsva', 'hsv', etc. can be used to convert+    from other popular formats to this structure. -} data Color = Color { r :: !Double, g :: !Double, b :: !Double, a :: !Double } --- |Creates an RGB color.+{-| Creates an RGB color. -} rgb :: Double -> Double -> Double -> Color rgb r g b = Color r g b 1 --- |Creates an RGB color, with transparency.+{-| Creates an RGB color, with transparency. -} rgba :: Double -> Double -> Double -> Double -> Color rgba = Color +{-| A bright red color. -} red :: Color red = rgb 1 0 0 +{-| A bright green color. -} lime :: Color lime = rgb 0 1 0 +{-| A bright blue color. -} blue :: Color blue = rgb 0 0 1 +{-| A yellow color, made from combining red and green. -} yellow :: Color yellow = rgb 1 1 0 +{-| A cyan color, combined from bright green and blue. -} cyan :: Color cyan = rgb 0 1 1 +{-| A magenta color, combined from bright red and blue. -} magenta :: Color magenta = rgb 1 0 1 +{-| A black color. -} black :: Color black = rgb 0 0 0 +{-| A white color. -} white :: Color white = rgb 1 1 1 +{-| A gray color, exactly halfway between black and white. -} gray :: Color gray = rgb 0.5 0.5 0.5 +{-| Common alternative spelling of 'gray'. -} grey :: Color grey = gray +{-| A medium red color. -} maroon :: Color maroon = rgb 0.5 0 0 +{-| A medium blue color. -} navy :: Color navy = rgb 0 0 0.5 +{-| A medium green color. -} green :: Color green = rgb 0 0.5 0 +{-| A teal color, combined from medium green and blue. -} teal :: Color teal = rgb 0 0.5 0.5 +{-| A purple color, combined from medium red and blue. -} purple :: Color purple = rgb 0.5 0 0.5 +{-| A violet color. -} violet :: Color violet = rgb 0.923 0.508 0.923 +{-| A dark green color. -} forestGreen :: Color forestGreen = rgb 0.133 0.543 0.133 -{- TODO:-+{-| Calculate a complementary color for a provided color. Useful for outlining+    a filled shape in a color clearly distinguishable from the fill color. -} complement :: Color -> Color+complement (Color r g b a) = hsva (fromIntegral ((round (h + 180) :: Int) `mod` 360)) (s / mx) mx a+  where+    mx = r `max` g `max` b+    mn = r `min` g `min` b+    s = mx - mn+    h | mx == r = (g - b) / s * 60+      | mx == g = (b - r) / s * 60 + 120+      | mx == b = (r - g) / s * 60 + 240+      | otherwise = undefined +{-| Create an RGBA color from HSVA values. -} hsva :: Double -> Double -> Double -> Double -> Color+hsva h s v a+  | h'' == 0 = rgba v t p a+  | h'' == 1 = rgba q v p a+  | h'' == 2 = rgba p v t a+  | h'' == 3 = rgba p q v a+  | h'' == 4 = rgba t p v a+  | h'' == 5 = rgba v p q a+  | otherwise = undefined +  where+    h' = h / 60+    h'' = (floor h') `mod` 6 :: Int+    f = h' - fromIntegral h''+    p = v * (1 - s)+    q = v * (1 - f * s)+    t = v * (1 - (1 - f) * s)    ++{-| Create an RGB color from HSV values. -} hsv :: Double -> Double -> Double -> Color--}+hsv h s v = hsva h s v 1 +{-| A data structure describing a gradient. There are two types of gradients:+    radial and linear. Radial gradients are based on a set of colors transitioned+    over certain radii in an arc pattern. Linear gradients are a set of colors+    transitioned in a straight line. -} data Gradient = Linear (Double, Double) (Double, Double) [(Double, Color)] |                 Radial (Double, Double) Double (Double, Double) Double [(Double, Color)]  --- |Creates a linear gradient. Takes an +{-| Creates a linear gradient. Takes a starting position, ending position and a list+    of color stops (which are colors combined with a floating value between /0.0/ and /1.0/+    that describes at what step along the line between the starting position+    and ending position the paired color should be transitioned to).++	> linear (0, 0) (100, 100) [(0, black), (1, white)]++	The above example creates a gradient that starts at /(0, 0)/+	and ends at /(100, 100)/. In other words, it's a diagonal gradient, transitioning from the top-left+	to the bottom-right. The provided color stops result in the gradient transitioning from+	black to white.+ -} linear :: (Double, Double) -> (Double, Double) -> [(Double, Color)] -> Gradient linear = Linear --- |Creates a radial gradient.+{-| Creates a radial gradient. Takes a starting position and radius, ending position and radius+    and a list of color stops. See the document for 'linear' for more information on color stops. -} radial :: (Double, Double) -> Double -> (Double, Double) -> Double -> [(Double, Color)] -> Gradient radial = Radial
FRP/Helm/Graphics.hs view
@@ -1,17 +1,26 @@+{-| Contains all the data structures and functions for composing+    and rendering graphics. -} module FRP.Helm.Graphics (+  -- * Types   Element(..),-  image,-  croppedImage,   Form(..),+  FormStyle(..),   FillStyle(..),   LineCap(..),   LineJoin(..),   LineStyle(..),+  Path,+  Shape(..),+  -- * Elements+  image,+  fittedImage,+  croppedImage,+  collage,+  -- * Styles & Forms   defaultLine,   solid,   dashed,   dotted,-  FormStyle(..),   filled,   textured,   gradient,@@ -19,18 +28,19 @@   traced,   sprite,   toForm,+  -- * Grouping   group,   groupTransform,+  -- * Transforming   rotate,   scale,   move,   moveX,   moveY,-  collage,-  Path,+  -- * Paths   path,   segment,-  Shape,+  -- * Shapes   polygon,   rect,   square,@@ -42,6 +52,13 @@ import FRP.Helm.Color as Color import Graphics.Rendering.Cairo.Matrix (Matrix, identity) +{-| A data structure describing something that can be rendered+    to the screen. Elements are the most important structure+    in Helm. Games essentially feed the engine a stream+    of elements which are then rendered directly to the screen.+    The usual way to render art in a Helm game is to call+    off to the 'collage' function, which essentially+    renders a collection of forms together. -} data Element = CollageElement Int Int [Form] |                ImageElement (Int, Int) Int Int FilePath Bool @@ -51,19 +68,21 @@ image :: Int -> Int -> FilePath -> Element image w h src = ImageElement (0, 0) w h src True -{- TODO: {-| Create an element from an image with a given width, height and image file path.     If the image dimensions are not the same as given, then it will only use the relevant pixels-    (i.e. cut out the given width instead of scaling). If the given dimensions are bigger than+    (i.e. cut out the given dimensions instead of scaling). If the given dimensions are bigger than     the actual image, than irrelevant pixels are ignored. -} fittedImage :: Int -> Int -> FilePath -> Element-fittedImage w h src = ImageElement (0, 0) w h src False -}+fittedImage w h src = ImageElement (0, 0) w h src False  {-| Create an element from an image by cropping it with a certain position, width, height     and image file path. This can be used to divide a single image up into smaller ones. -} croppedImage :: (Int, Int) -> Int -> Int -> FilePath -> Element croppedImage pos w h src = ImageElement pos w h src False +{-| A data structure describing a form. A form is essentially a notion of a transformed+    graphic, whether it be an element or shape. See 'FormStyle' for an insight+    into what sort of graphics can be wrapped in a form. -} data Form = Form {   theta :: Double,   scalar :: Double,@@ -71,9 +90,19 @@   y :: Double,   style :: FormStyle }++{-| A data structure describing how a shape or path looks when filled. -} data FillStyle = Solid Color | Texture String | Gradient Gradient++{-| A data structure describing the shape of the ends of a line. -} data LineCap = Flat | Round | Padded++{-| A data structure describing the shape of the join of a line, i.e.+    where separate line segments join. The 'Sharp' variant takes+    an argument to limit the length of the join. -} data LineJoin = Smooth | Sharp Double | Clipped++{-| A data structure describing how a shape or path looks when stroked. -} data LineStyle = LineStyle {   color :: Color,   width :: Double,@@ -95,46 +124,50 @@   dashOffset = 0 } --- |Create a solid line style with a color.+{-| Create a solid line style with a color. -} solid :: Color -> LineStyle solid color = defaultLine { color = color } --- |Create a dashed line style with a color.+{-| Create a dashed line style with a color. -} dashed :: Color -> LineStyle dashed color = defaultLine { color = color, dashing = [8, 4] } --- |Create a dotted line style with a color.+{-| Create a dotted line style with a color. -} dotted :: Color -> LineStyle dotted color = defaultLine { color = color, dashing = [3, 3] } +{-| A data structure describing a few ways that graphics that can be wrapped in a form+    and hence transformed. -} data FormStyle = PathForm LineStyle Path |                  ShapeForm (Either LineStyle FillStyle) Shape |                  ElementForm Element |                  GroupForm Matrix [Form] +{-| Utility function for creating a form. -} form :: FormStyle -> Form form style = Form { theta = 0, scalar = 1, x = 0, y = 0, style = style } +{-| Utility function for creating a filled form from a fill style and shape. -} fill :: FillStyle -> Shape -> Form fill style shape = form (ShapeForm (Right style) shape) --- |Creates a form from a shape by filling it with a specific color.+{-| Creates a form from a shape by filling it with a specific color. -} filled :: Color -> Shape -> Form filled color shape = fill (Solid color) shape --- |Creates a form from a shape with a tiled texture and image file path.+{-| Creates a form from a shape with a tiled texture and image file path. -} textured :: String -> Shape -> Form textured src shape = fill (Texture src) shape --- |Creates a form from a shape filled with a gradient.+{-| Creates a form from a shape filled with a gradient. -} gradient :: Gradient -> Shape -> Form gradient grad shape = fill (Gradient grad) shape --- |Creates a form from a shape by outlining it with a specific line style.+{-| Creates a form from a shape by outlining it with a specific line style. -} outlined :: LineStyle -> Shape -> Form outlined style shape = form (ShapeForm (Left style) shape) --- |Creates a form from a path by tracing it with a specific line style.+{-| Creates a form from a path by tracing it with a specific line style. -} traced :: LineStyle -> Path -> Form traced style p = form (PathForm style p) @@ -143,88 +176,86 @@ sprite :: Int -> Int -> (Int, Int) -> FilePath -> Form sprite w h pos src = form (ElementForm (ImageElement pos w h src False)) --- |Creates a form from an element.+{-| Creates a form from an element. -} toForm :: Element -> Form toForm element = form (ElementForm element) --- |Groups a collection of forms into a single one.+{-| Groups a collection of forms into a single one. -} group :: [Form] -> Form group forms = form (GroupForm identity forms) --- |Groups a collection of forms into a single one, also applying a matrix transformation.+{-| Groups a collection of forms into a single one, also applying a matrix transformation. -} groupTransform :: Matrix -> [Form] -> Form groupTransform matrix forms = form (GroupForm matrix forms) --- |Rotates a form by an amount (in radians).+{-| Rotates a form by an amount (in radians). -} rotate :: Double -> Form -> Form rotate t f = f { theta = t + theta f } --- |Scales a form by an amount, e.g. scaling by 2 will double the size.+{-| Scales a form by an amount, e.g. scaling by /2.0/ will double the size. -} scale :: Double -> Form -> Form scale n f = f { scalar = n + scalar f } --- |Moves a form relative to its current position.+{-| Moves a form relative to its current position. -} move :: (Double, Double) -> Form -> Form move (rx, ry) f = f { x = rx + x f, y = ry + y f } --- |Moves a form's x-coordinate relative to its current position.+{-| Moves a form's x-coordinate relative to its current position. -} moveX :: Double -> Form -> Form moveX x f = move (x, 0) f --- |Moves a form's y-coordinate relative to its current position.+{-| Moves a form's y-coordinate relative to its current position. -} moveY :: Double -> Form -> Form moveY y f = move (0, y) f -{-| Create an element from a collection of forms.-    Can be used to directly render a collection of forms. -}+{-| Create an element from a collection of forms, with width and height arguments.+    Can be used to directly render a collection of forms.++    > collage 800 600 [move (100, 100) $ filled red $ square 100,+    >                  move (100, 100) $ outlined (solid white) $ circle 50]+ -} collage :: Int -> Int -> [Form] -> Element collage w h forms = CollageElement w h forms +{-| A data type made up a collection of points that form a path when joined. -} type Path = [(Double, Double)] --- |Creates a path for a collection of points.+{-| Creates a path for a collection of points. -} path :: [(Double, Double)] -> Path path points = points --- |Creates a path from a line segment, i.e. a start and end point.+{-| Creates a path from a line segment, i.e. a start and end point. -} segment :: (Double, Double) -> (Double, Double) -> Path-segment p1 p2 = [p1,p2]+segment p1 p2 = [p1, p2] -type Shape = [(Double, Double)]+{-| A data structure describing a some sort of graphically representable object,+    such as a polygon formed from a set of points or a rectangle. -}+data Shape = PolygonShape Path | RectangleShape (Double, Double) | ArcShape (Double, Double) Double Double Double (Double, Double) --- |Creates a shape from a set of points.-polygon :: [(Double, Double)] -> Shape-polygon points = points+{-| Creates a shape from a path (a set of points). -}+polygon :: Path -> Shape+polygon points = PolygonShape points --- |Creates a rectangular shape with a specific width and height.+{-| Creates a rectangular shape with a width and height. -} rect :: Double -> Double -> Shape-rect w h = [(-hw, -hh), (-hw, hh), (hw, hh), (hw, -hh)]-  where-    hw = w / 2-    hh = h / 2+rect w h = RectangleShape (w, h) --- |Creates a square shape with a specific side length.+{-| Creates a square shape with a side length. -} square :: Double -> Shape square n = rect n n --- |Creates an oval shape with a specific width and height.+{-| Creates an oval shape with a width and height. -} oval :: Double -> Double -> Shape-oval w h = map (\i -> (hw * cos (t * i), hh * sin (t * i))) [0 .. n - 1]-  where-    n = 50-    t = 2 * pi / n-    hw = w / 2-    hh = h / 2+oval w h = ArcShape (0, 0) 0 (2 * pi) 1 (w / 2, h / 2) --- |Creates an oval shape with a specific radius.-{- TODO: Make a separate variant of a shape that is based on an arc.-   as this sort of thing is going to be pretty unaccurate and slower. -}+{-| Creates a circle shape with a radius. -} circle :: Double -> Shape-circle r = oval (2 * r) (2 * r)+circle r = ArcShape (0, 0) 0 (2 * pi) r (1, 1) --- |Creates a generic n-sided polygon (e.g. octagon) with a specific amount of sides and radius.+{-| Creates a generic n-sided polygon (e.g. octagon, pentagon, etc) with+    an amount of sides and radius. -} ngon :: Int -> Double -> Shape-ngon n r = map (\i -> (r * cos (t * i), r * sin (t * i))) [0 .. fromIntegral (n - 1)]+ngon n r = PolygonShape (map (\i -> (r * cos (t * i), r * sin (t * i))) [0 .. fromIntegral (n - 1)])   where      m = fromIntegral n     t = 2 * pi / m
FRP/Helm/Keyboard.hs view
@@ -1,11 +1,12 @@+{-| Contains signals that sample input from the keyboard. -} module FRP.Helm.Keyboard (-  shift,-  ctrl,-  enter,+  -- * Types   Key(..),-  space,-  arrows,-  wasd+  -- * Key State+  shift, ctrl, enter,+  space, isDown, keysDown,+  -- * Directions+  arrows, wasd ) where  import Control.Applicative@@ -14,18 +15,19 @@ import Foreign.C.Types import FRP.Elerea.Simple import qualified Graphics.UI.SDL as SDL-import qualified Graphics.UI.SDL.Utilities as Utilities --- The SDL bindings for Haskell don't wrap this, so we have to use the FFI ourselves.+{-| The SDL bindings for Haskell don't wrap this, so we have to use the FFI ourselves. -} foreign import ccall unsafe "SDL_GetKeyState" sdlGetKeyState :: Ptr CInt -> IO (Ptr Word8) --- Based on http://coderepos.org/share/browser/lang/haskell/nario/Main.hs?rev=22646#L49-getKeyState :: IO [SDL.SDLKey]+{-| A utility function for getting a list of SDL keys currently pressed.+    Based on <http://coderepos.org/share/browser/lang/haskell/nario/Main.hs?rev=22646#L49>. -}+getKeyState :: IO [Int] getKeyState = alloca $ \numkeysPtr -> do   keysPtr <- sdlGetKeyState numkeysPtr   numkeys <- peek numkeysPtr-  (map Utilities.toEnum . map fromIntegral . findIndices (== 1)) <$> peekArray (fromIntegral numkeys) keysPtr+  (map fromIntegral . findIndices (== 1)) <$> peekArray (fromIntegral numkeys) keysPtr +{-| A data structure describing a physical key on a keyboard. -} data Key = BackspaceKey | TabKey | ClearKey | EnterKey | PauseKey | EscapeKey |            SpaceKey | ExclaimKey | QuotedBlKey | HashKey | DollarKey | AmpersandKey |            QuoteKey | LeftParenKey | RightParenKey | AsteriskKey | PlusKey | CommaKey |@@ -34,187 +36,325 @@            Num9Key | ColonKey | SemicolonKey | LessKey | EqualsKey | GreaterKey |            QuestionKey | AtKey | LeftBracketKey | BackslashKey | RightBracketKey | CaretKey |            UnderscoreKey | BackquoteKey | AKey | BKey | CKey | DKey |-           EKey | FKey | GKey | HKey | IKey | JKey |+           EKey | FKey | GKey | HKey | IKey | JKey | KKey |            LKey | MKey | NKey | OKey | PKey | QKey |            RKey | SKey | TKey | UKey | VKey | WKey |-           XKey | YKey | ZKey | DeleteKey | Keypad0Key | Keypad1Key |-           Keypad2Key | Keypad3Key | Keypad4Key | Keypad5Key | Keypad6Key | Keypad7Key |-           Keypad8Key | Keypad9Key | KeypadPeriodKey | KeypadDivideKey | KeypadMultiplyKey | KeypadMinusKey |+           XKey | YKey | ZKey | DeleteKey | KeypadNum0Key | KeypadNum1Key |+           KeypadNum2Key | KeypadNum3Key | KeypadNum4Key | KeypadNum5Key | KeypadNum6Key | KeypadNum7Key |+           KeypadNum8Key | KeypadNum9Key | KeypadPeriodKey | KeypadDivideKey | KeypadMultiplyKey | KeypadMinusKey |            KeypadPlusKey | KeypadEnterKey | KeypadEqualsKey | UpKey | DownKey | RightKey |            LeftKey | InsertKey | HomeKey | EndKey | PageUpKey | PageDownKey |            F1Key | F2Key | F3Key | F4Key |  F5Key | F6Key |            F7Key | F8Key | F9Key | F10Key | F11Key | F12Key |            F13Key | F14Key | F15Key | NumLockKey | CapsLockKey | ScrollLockKey |            RShiftKey | LShiftKey | RCtrlKey | LCtrlKey | RAltKey | LAltKey |-           RMetaKey | LMetaKey | RSuperKey | LSuperKey | ComposeKey | HelpKey |+           RMetaKey | LMetaKey | RSuperKey | LSuperKey | ModeKey | ComposeKey | HelpKey |            PrintKey | SysReqKey | BreakKey | MenuKey | PowerKey | EuroKey |            UndoKey -mapKey :: Key -> SDL.SDLKey-mapKey k =-  case k of-    BackspaceKey -> SDL.SDLK_BACKSPACE-    TabKey -> SDL.SDLK_TAB-    ClearKey -> SDL.SDLK_CLEAR-    EnterKey -> SDL.SDLK_RETURN-    PauseKey -> SDL.SDLK_PAUSE-    EscapeKey -> SDL.SDLK_ESCAPE-    SpaceKey -> SDL.SDLK_SPACE-    ExclaimKey -> SDL.SDLK_EXCLAIM-    QuotedBlKey -> SDL.SDLK_QUOTEDBL-    HashKey -> SDL.SDLK_HASH-    DollarKey -> SDL.SDLK_DOLLAR-    AmpersandKey -> SDL.SDLK_AMPERSAND-    QuoteKey -> SDL.SDLK_QUOTE-    LeftParenKey -> SDL.SDLK_LEFTPAREN-    RightParenKey -> SDL.SDLK_RIGHTPAREN-    AsteriskKey -> SDL.SDLK_ASTERISK-    PlusKey -> SDL.SDLK_PLUS-    CommaKey -> SDL.SDLK_COMMA-    MinusKey -> SDL.SDLK_MINUS-    PeriodKey -> SDL.SDLK_PERIOD-    SlashKey -> SDL.SDLK_SLASH-    Num0Key -> SDL.SDLK_0-    Num1Key -> SDL.SDLK_1-    Num2Key -> SDL.SDLK_2-    Num3Key -> SDL.SDLK_3-    Num4Key -> SDL.SDLK_4-    Num5Key -> SDL.SDLK_5-    Num6Key -> SDL.SDLK_6-    Num7Key -> SDL.SDLK_7-    Num8Key -> SDL.SDLK_8-    Num9Key -> SDL.SDLK_9-    ColonKey -> SDL.SDLK_COLON-    SemicolonKey -> SDL.SDLK_SEMICOLON-    LessKey -> SDL.SDLK_LESS-    EqualsKey -> SDL.SDLK_EQUALS-    GreaterKey -> SDL.SDLK_GREATER-    QuestionKey -> SDL.SDLK_QUESTION-    AtKey -> SDL.SDLK_AT-    LeftBracketKey -> SDL.SDLK_LEFTBRACKET-    BackslashKey -> SDL.SDLK_BACKSLASH-    RightBracketKey -> SDL.SDLK_RIGHTBRACKET-    CaretKey -> SDL.SDLK_CARET-    UnderscoreKey -> SDL.SDLK_UNDERSCORE-    BackquoteKey -> SDL.SDLK_BACKQUOTE-    AKey -> SDL.SDLK_a-    BKey -> SDL.SDLK_b-    CKey -> SDL.SDLK_c-    DKey -> SDL.SDLK_d-    EKey -> SDL.SDLK_e-    FKey -> SDL.SDLK_f-    GKey -> SDL.SDLK_g-    HKey -> SDL.SDLK_h-    IKey -> SDL.SDLK_i-    JKey -> SDL.SDLK_j-    LKey -> SDL.SDLK_l-    MKey -> SDL.SDLK_m-    NKey -> SDL.SDLK_n-    OKey -> SDL.SDLK_o-    PKey -> SDL.SDLK_p-    QKey -> SDL.SDLK_q-    RKey -> SDL.SDLK_r-    SKey -> SDL.SDLK_s-    TKey -> SDL.SDLK_t-    UKey -> SDL.SDLK_u-    VKey -> SDL.SDLK_v-    WKey -> SDL.SDLK_w-    XKey -> SDL.SDLK_x-    YKey -> SDL.SDLK_y-    ZKey -> SDL.SDLK_z-    DeleteKey -> SDL.SDLK_DELETE-    Keypad0Key -> SDL.SDLK_KP0-    Keypad1Key -> SDL.SDLK_KP1-    Keypad2Key -> SDL.SDLK_KP2-    Keypad3Key -> SDL.SDLK_KP3-    Keypad4Key -> SDL.SDLK_KP4-    Keypad5Key -> SDL.SDLK_KP5-    Keypad6Key -> SDL.SDLK_KP6-    Keypad7Key -> SDL.SDLK_KP7-    Keypad8Key -> SDL.SDLK_KP8-    Keypad9Key -> SDL.SDLK_KP9-    KeypadPeriodKey -> SDL.SDLK_KP_PERIOD-    KeypadDivideKey -> SDL.SDLK_KP_DIVIDE-    KeypadMultiplyKey -> SDL.SDLK_KP_MULTIPLY-    KeypadMinusKey -> SDL.SDLK_KP_MINUS-    KeypadPlusKey -> SDL.SDLK_KP_PLUS-    KeypadEnterKey -> SDL.SDLK_KP_ENTER-    KeypadEqualsKey -> SDL.SDLK_KP_EQUALS-    UpKey -> SDL.SDLK_UP-    DownKey -> SDL.SDLK_DOWN-    RightKey -> SDL.SDLK_RIGHT-    LeftKey -> SDL.SDLK_LEFT-    InsertKey -> SDL.SDLK_INSERT-    HomeKey -> SDL.SDLK_HOME-    EndKey -> SDL.SDLK_END-    PageUpKey -> SDL.SDLK_PAGEUP-    PageDownKey -> SDL.SDLK_PAGEDOWN-    F1Key -> SDL.SDLK_F1-    F2Key -> SDL.SDLK_F2-    F3Key -> SDL.SDLK_F3-    F4Key -> SDL.SDLK_F4-    F5Key -> SDL.SDLK_F5-    F6Key -> SDL.SDLK_F6-    F7Key -> SDL.SDLK_F7-    F8Key -> SDL.SDLK_F8-    F9Key -> SDL.SDLK_F9-    F10Key -> SDL.SDLK_F10-    F11Key -> SDL.SDLK_F11-    F12Key -> SDL.SDLK_F12-    F13Key -> SDL.SDLK_F13-    F14Key -> SDL.SDLK_F14-    F15Key -> SDL.SDLK_F15-    NumLockKey -> SDL.SDLK_NUMLOCK-    CapsLockKey -> SDL.SDLK_CAPSLOCK-    ScrollLockKey -> SDL.SDLK_SCROLLOCK-    RShiftKey -> SDL.SDLK_RSHIFT-    LShiftKey -> SDL.SDLK_LSHIFT-    RCtrlKey -> SDL.SDLK_RCTRL-    LCtrlKey -> SDL.SDLK_LCTRL-    RAltKey -> SDL.SDLK_RALT-    LAltKey -> SDL.SDLK_LALT-    RMetaKey -> SDL.SDLK_RMETA-    LMetaKey -> SDL.SDLK_LMETA-    RSuperKey -> SDL.SDLK_RSUPER-    LSuperKey -> SDL.SDLK_LSUPER-    ComposeKey -> SDL.SDLK_COMPOSE-    HelpKey -> SDL.SDLK_HELP-    PrintKey -> SDL.SDLK_PRINT-    SysReqKey -> SDL.SDLK_SYSREQ-    BreakKey -> SDL.SDLK_BREAK-    MenuKey -> SDL.SDLK_MENU-    PowerKey -> SDL.SDLK_POWER-    EuroKey -> SDL.SDLK_EURO-    UndoKey -> SDL.SDLK_UNDO+{- All integer values of this enum are equivalent to the SDL key enum. -}+instance Enum Key where+  fromEnum BackspaceKey = 8+  fromEnum TabKey = 9+  fromEnum ClearKey = 12+  fromEnum EnterKey = 13+  fromEnum PauseKey = 19+  fromEnum EscapeKey = 27+  fromEnum SpaceKey = 32+  fromEnum ExclaimKey = 33+  fromEnum QuotedBlKey = 34+  fromEnum HashKey = 35+  fromEnum DollarKey = 36+  fromEnum AmpersandKey = 38+  fromEnum QuoteKey = 39+  fromEnum LeftParenKey = 40+  fromEnum RightParenKey = 41+  fromEnum AsteriskKey = 42+  fromEnum PlusKey = 43+  fromEnum CommaKey = 44+  fromEnum MinusKey = 45+  fromEnum PeriodKey = 46+  fromEnum SlashKey = 47+  fromEnum Num0Key = 48+  fromEnum Num1Key = 49+  fromEnum Num2Key = 50+  fromEnum Num3Key = 51+  fromEnum Num4Key = 52+  fromEnum Num5Key = 53+  fromEnum Num6Key = 54+  fromEnum Num7Key = 55+  fromEnum Num8Key = 56+  fromEnum Num9Key = 57+  fromEnum ColonKey = 58+  fromEnum SemicolonKey = 59+  fromEnum LessKey = 60+  fromEnum EqualsKey = 61+  fromEnum GreaterKey = 62+  fromEnum QuestionKey = 63+  fromEnum AtKey = 64+  fromEnum LeftBracketKey = 91+  fromEnum BackslashKey = 92+  fromEnum RightBracketKey = 93+  fromEnum CaretKey = 94+  fromEnum UnderscoreKey = 95+  fromEnum BackquoteKey = 96+  fromEnum AKey = 97+  fromEnum BKey = 98+  fromEnum CKey = 99+  fromEnum DKey = 100+  fromEnum EKey = 101+  fromEnum FKey = 102+  fromEnum GKey = 103+  fromEnum HKey = 104+  fromEnum IKey = 105+  fromEnum JKey = 106+  fromEnum KKey = 107+  fromEnum LKey = 108+  fromEnum MKey = 109+  fromEnum NKey = 110+  fromEnum OKey = 111+  fromEnum PKey = 112+  fromEnum QKey = 113+  fromEnum RKey = 114+  fromEnum SKey = 115+  fromEnum TKey = 116+  fromEnum UKey = 117+  fromEnum VKey = 118+  fromEnum WKey = 119+  fromEnum XKey = 120+  fromEnum YKey = 121+  fromEnum ZKey = 122+  fromEnum DeleteKey = 127+  fromEnum KeypadNum0Key = 256+  fromEnum KeypadNum1Key = 257+  fromEnum KeypadNum2Key = 258+  fromEnum KeypadNum3Key = 259+  fromEnum KeypadNum4Key = 260+  fromEnum KeypadNum5Key = 261+  fromEnum KeypadNum6Key = 262+  fromEnum KeypadNum7Key = 263+  fromEnum KeypadNum8Key = 264+  fromEnum KeypadNum9Key = 265+  fromEnum KeypadPeriodKey = 266+  fromEnum KeypadDivideKey = 267+  fromEnum KeypadMultiplyKey = 268+  fromEnum KeypadMinusKey = 269+  fromEnum KeypadPlusKey = 270+  fromEnum KeypadEnterKey = 271+  fromEnum KeypadEqualsKey = 272+  fromEnum UpKey = 273+  fromEnum DownKey = 274+  fromEnum RightKey = 275+  fromEnum LeftKey = 276+  fromEnum InsertKey = 277+  fromEnum HomeKey = 278+  fromEnum EndKey = 279+  fromEnum PageUpKey = 280+  fromEnum PageDownKey = 281+  fromEnum F1Key = 282+  fromEnum F2Key = 283+  fromEnum F3Key = 284+  fromEnum F4Key = 285+  fromEnum F5Key = 286+  fromEnum F6Key = 287+  fromEnum F7Key = 288+  fromEnum F8Key = 289+  fromEnum F9Key = 290+  fromEnum F10Key = 291+  fromEnum F11Key = 292+  fromEnum F12Key = 293+  fromEnum F13Key = 294+  fromEnum F14Key = 295+  fromEnum F15Key = 296+  fromEnum NumLockKey = 300+  fromEnum CapsLockKey = 301+  fromEnum ScrollLockKey = 302+  fromEnum RShiftKey = 303+  fromEnum LShiftKey = 304+  fromEnum RCtrlKey = 305+  fromEnum LCtrlKey = 306+  fromEnum RAltKey = 307+  fromEnum LAltKey = 308+  fromEnum RMetaKey = 309+  fromEnum LMetaKey = 310+  fromEnum LSuperKey = 311+  fromEnum RSuperKey = 312+  fromEnum ModeKey = 313+  fromEnum ComposeKey = 314+  fromEnum HelpKey = 315+  fromEnum PrintKey = 316+  fromEnum SysReqKey = 317+  fromEnum BreakKey = 318+  fromEnum MenuKey = 319+  fromEnum PowerKey = 320+  fromEnum EuroKey = 321+  fromEnum UndoKey = 322 --- |Whether either shift key is pressed.+  toEnum 8 = BackspaceKey+  toEnum 9 = TabKey+  toEnum 12 = ClearKey+  toEnum 13 = EnterKey+  toEnum 19 = PauseKey+  toEnum 27 = EscapeKey+  toEnum 32 = SpaceKey+  toEnum 33 = ExclaimKey+  toEnum 34 = QuotedBlKey+  toEnum 35 = HashKey+  toEnum 36 = DollarKey+  toEnum 38 = AmpersandKey+  toEnum 39 = QuoteKey+  toEnum 40 = LeftParenKey+  toEnum 41 = RightParenKey+  toEnum 42 = AsteriskKey+  toEnum 43 = PlusKey+  toEnum 44 = CommaKey+  toEnum 45 = MinusKey+  toEnum 46 = PeriodKey+  toEnum 47 = SlashKey+  toEnum 48 = Num0Key+  toEnum 49 = Num1Key+  toEnum 50 = Num2Key+  toEnum 51 = Num3Key+  toEnum 52 = Num4Key+  toEnum 53 = Num5Key+  toEnum 54 = Num6Key+  toEnum 55 = Num7Key+  toEnum 56 = Num8Key+  toEnum 57 = Num9Key+  toEnum 58 = ColonKey+  toEnum 59 = SemicolonKey+  toEnum 60 = LessKey+  toEnum 61 = EqualsKey+  toEnum 62 = GreaterKey+  toEnum 63 = QuestionKey+  toEnum 64 = AtKey+  toEnum 91 = LeftBracketKey+  toEnum 92 = BackslashKey+  toEnum 93 = RightBracketKey+  toEnum 94 = CaretKey+  toEnum 95 = UnderscoreKey+  toEnum 96 = BackquoteKey+  toEnum 97 = AKey+  toEnum 98 = BKey+  toEnum 99 = CKey+  toEnum 100 = DKey+  toEnum 101 = EKey+  toEnum 102 = FKey+  toEnum 103 = GKey+  toEnum 104 = HKey+  toEnum 105 = IKey+  toEnum 106 = JKey+  toEnum 107 = KKey+  toEnum 108 = LKey+  toEnum 109 = MKey+  toEnum 110 = NKey+  toEnum 111 = OKey+  toEnum 112 = PKey+  toEnum 113 = QKey+  toEnum 114 = RKey+  toEnum 115 = SKey+  toEnum 116 = TKey+  toEnum 117 = UKey+  toEnum 118 = VKey+  toEnum 119 = WKey+  toEnum 120 = XKey+  toEnum 121 = YKey+  toEnum 122 = ZKey+  toEnum 127 = DeleteKey+  toEnum 256 = KeypadNum0Key+  toEnum 257 = KeypadNum1Key+  toEnum 258 = KeypadNum2Key+  toEnum 259 = KeypadNum3Key+  toEnum 260 = KeypadNum4Key+  toEnum 261 = KeypadNum5Key+  toEnum 262 = KeypadNum6Key+  toEnum 263 = KeypadNum7Key+  toEnum 264 = KeypadNum8Key+  toEnum 265 = KeypadNum9Key+  toEnum 266 = KeypadPeriodKey+  toEnum 267 = KeypadDivideKey+  toEnum 268 = KeypadMultiplyKey+  toEnum 269 = KeypadMinusKey+  toEnum 270 = KeypadPlusKey+  toEnum 271 = KeypadEnterKey+  toEnum 272 = KeypadEqualsKey+  toEnum 273 = UpKey+  toEnum 274 = DownKey+  toEnum 275 = RightKey+  toEnum 276 = LeftKey+  toEnum 277 = InsertKey+  toEnum 278 = HomeKey+  toEnum 279 = EndKey+  toEnum 280 = PageUpKey+  toEnum 281 = PageDownKey+  toEnum 282 = F1Key+  toEnum 283 = F2Key+  toEnum 284 = F3Key+  toEnum 285 = F4Key+  toEnum 286 = F5Key+  toEnum 287 = F6Key+  toEnum 288 = F7Key+  toEnum 289 = F8Key+  toEnum 290 = F9Key+  toEnum 291 = F10Key+  toEnum 292 = F11Key+  toEnum 293 = F12Key+  toEnum 294 = F13Key+  toEnum 295 = F14Key+  toEnum 296 = F15Key+  toEnum 300 = NumLockKey+  toEnum 301 = CapsLockKey+  toEnum 302 = ScrollLockKey+  toEnum 303 = RShiftKey+  toEnum 304 = LShiftKey+  toEnum 305 = RCtrlKey+  toEnum 306 = LCtrlKey+  toEnum 307 = RAltKey+  toEnum 308 = LAltKey+  toEnum 309 = RMetaKey+  toEnum 310 = LMetaKey+  toEnum 311 = LSuperKey+  toEnum 312 = RSuperKey+  toEnum 313 = ModeKey+  toEnum 314 = ComposeKey+  toEnum 315 = HelpKey+  toEnum 316 = PrintKey+  toEnum 317 = SysReqKey+  toEnum 318 = BreakKey+  toEnum 319 = MenuKey+  toEnum 320 = PowerKey+  toEnum 321 = EuroKey+  toEnum 322 = UndoKey+  toEnum _ = error "FRP.Helm.Keyboard.Key.toEnum: bad argument"++{-| Whether either shift key is pressed. -} shift :: SignalGen (Signal Bool) shift = effectful $ (elem SDL.KeyModShift) <$> SDL.getModState --- |Whether either control key is pressed.+{-| Whether either control key is pressed. -} ctrl :: SignalGen (Signal Bool) ctrl = effectful $ (elem SDL.KeyModCtrl) <$> SDL.getModState --- |Whether a specific key is pressed.+{-| Whether a key is pressed. -} isDown :: Key -> SignalGen (Signal Bool)-isDown k = effectful $ (elem (mapKey k)) <$> getKeyState+isDown k = effectful $ (elem $ fromEnum k) <$> getKeyState --- |Whether the shift key is pressed.+{-| Whether the enter (a.k.a. return) key is pressed. -} enter :: SignalGen (Signal Bool) enter = isDown EnterKey --- |Whether the space key is pressed.+{-| Whether the space key is pressed. -} space :: SignalGen (Signal Bool) space = isDown SpaceKey -{- TODO:+{-| A list of keys that are currently being pressed. -} keysDown :: SignalGen (Signal [Key])--}+keysDown = effectful $ (map toEnum) <$> getKeyState -{-| A unit vector combined from the arrow keys. When no keys are being pressed-    this signal samples to (0, 0), otherwise it samples to a specific direction-    based on which keys are pressed. For example, pressing the left key results-    in (-1, 0), the down key (0, 1), etc. -}+{-| A directional tuple combined from the arrow keys. When none of the arrow keys+    are being pressed this signal samples to /(0, 0)/, otherwise it samples to a+    direction based on which keys are pressed. For example, pressing the left key+    results in /(-1, 0)/, the down key /(0, 1)/, up and right /(1, -1)/, etc. -} arrows :: SignalGen (Signal (Int, Int)) arrows = do   up <- isDown UpKey@@ -224,10 +364,11 @@    return $ arrows' <$> up <*> left <*> down <*> right +{-| A utility function for setting up a vector signal from directional keys. -} arrows' :: Bool -> Bool -> Bool -> Bool -> (Int, Int) arrows' u l d r = (-1 * fromEnum l + 1 * fromEnum r, -1 * fromEnum u + 1 * fromEnum d) --- |Similar to the 'arrows' signal, but uses the W, A, S and D keys instead.+{-| Similar to the 'arrows' signal, but uses the popular WASD movement controls instead. -} wasd :: SignalGen (Signal (Int, Int)) wasd = do   w <- isDown WKey
FRP/Helm/Mouse.hs view
@@ -1,24 +1,33 @@-module FRP.Helm.Mouse (position, x, y, isDown, Mouse(..)) where+{-| Contains signals that sample input from the mouse. -}+module FRP.Helm.Mouse (+	-- * Types+	Mouse(..),+	-- * Position+	isDown,+	-- * Mouse State+	position, x, y+) where  import Control.Applicative import FRP.Elerea.Simple import qualified Graphics.UI.SDL as SDL +{-| A data structure describing a button on a mouse. -} data Mouse = LeftMouse | MiddleMouse | RightMouse --- |The current mouse position.+{-| The current position of the mouse. -} position :: SignalGen (Signal (Int, Int)) position = effectful $ (\(x_, y_, _) -> (x_, y_)) <$> SDL.getMouseState --- |The current x-coordinate of the mouse.+{-| The current x-coordinate of the mouse. -} x :: SignalGen (Signal Int) x = effectful $ (\(x_, _, _) -> x_) <$> SDL.getMouseState --- |The current y-coordinate of the mouse.+{-| The current y-coordinate of the mouse. -} y :: SignalGen (Signal Int) y = effectful $ (\(_, y_, _) -> y_) <$> SDL.getMouseState -+{-| Maps our mouse type into SDL's one. -} mapMouse :: Mouse -> SDL.MouseButton mapMouse m =   case m of@@ -30,7 +39,3 @@     True if the mouse is down, false otherwise. -} isDown :: Mouse -> SignalGen (Signal Bool) isDown m = effectful $ (\(_, _, b_) -> elem (mapMouse m) b_) <$> SDL.getMouseState--{- TODO:-isClicked :: SignalGen (Signal Bool)- -}
FRP/Helm/Window.hs view
@@ -1,4 +1,8 @@-module FRP.Helm.Window (dimensions, width, height) where+{-| Contains signals that sample input from the game window. -}+module FRP.Helm.Window (+	-- * Dimensions+	dimensions, width, height+) where  import Control.Applicative import FRP.Elerea.Simple
helm.cabal view
@@ -1,5 +1,5 @@ name: helm-version: 0.1.0+version: 0.2.0 synopsis: A functionally reactive game engine. description: A functionally reactive game engine, with headgear to protect you              from the headache of game development provided.