yampa-sdl2 0.0.3.0 → 0.0.3.1
raw patch · 4 files changed
+311/−132 lines, 4 filesdep +stm
Dependencies added: stm
Files
- src/YampaSDL2/Backend/ExperimentalOutput.hs +284/−0
- src/YampaSDL2/Backend/Output.hs +20/−129
- src/YampaSDL2/Backend/SDL.hs +2/−1
- yampa-sdl2.cabal +5/−2
+ src/YampaSDL2/Backend/ExperimentalOutput.hs view
@@ -0,0 +1,284 @@+module YampaSDL2.Backend.ExperimentalOutput+ (outputAction) where+import qualified SDL+import qualified SDL.Primitive as GFX+import Data.Colour.SRGB+import Control.Monad+import Control.Exception+import Linear.V4+import Linear.V2+import Data.Maybe+import Control.Concurrent.MVar+import Data.StateVar (($=), get)+import Data.List+import Data.Colour.Names+import Debug.Trace++import YampaSDL2.AppOutput ( AppOutput(..)+ , Graphics (..)+ , Camera (..)+ , RenderShape (..)+ )+import YampaSDL2.Geometry+++-- changed bool variable does not do anything+outputAction :: Double -> MVar [(String, (SDL.Texture, V2 Int))]-> MVar Double -> MVar Bool -> MVar (Maybe Graphics) -> SDL.Window -> SDL.Renderer -> Bool -> AppOutput -> IO Bool+outputAction fps mvarTextures mvarFPS mvarReady mvarG window renderer _ ao = do+ lastTime <- readMVar mvarFPS+ currentTime <- SDL.time+ ensureFPS <- if currentTime - lastTime > 1/fps+ then modifyMVar_ mvarFPS (return . const currentTime) >> return True+ else return False+ ready <- readMVar mvarReady+ when (ensureFPS && ready) $ do+ modifyMVar_ mvarReady (\_ -> return False)+ renderGraphics mvarTextures mvarG window renderer (graphics ao)+ modifyMVar_ mvarReady (\_ -> return True)+ return (shouldExit ao)++-- Experimental render, inefficient right now+-- Rendering of preprocessed shapes+renderGraphics :: MVar [(String, (SDL.Texture, V2 Int))] -> MVar (Maybe Graphics) -> SDL.Window -> SDL.Renderer -> Graphics -> IO ()+renderGraphics mvarTextures mvarG window renderer gra = do+ textures <- readMVar mvarTextures+ let newGraphics =+ splitObjects textures 100 $+ adjustToCamera $+ removeOutOfBounds gra+ oldObjects <- fromMaybe [] <$> fmap objects <$> swapMVar mvarG (return newGraphics)+ (V2 wW wH) <- fmap (fromIntegral . fromEnum) <$> get (SDL.windowSize window)+ (V2 cW cH) <- return (cSize $ camera gra)+ SDL.rendererScale renderer $= realToFrac <$> (V2 (wW/cW) (wH/cH))+ render mvarTextures renderer oldObjects gra++render :: MVar [(String, (SDL.Texture, V2 Int))] -> SDL.Renderer -> [RenderShape] -> Graphics -> IO ()+render mvarTextures renderer oldRS gra = do+ let oldSortedRS = sortBy (\rs1 rs2 -> zIndex rs1 `compare` zIndex rs2) oldRS+ newSortedRS = sortBy (\rs1 rs2 -> zIndex rs1 `compare` zIndex rs2) (objects gra)+ obsChanged = checkChanged oldSortedRS newSortedRS+ rerenderList = render' obsChanged+ mapM_ (renderShape mvarTextures renderer) $+ sortBy (\r1 r2 -> zIndex r1 `compare` zIndex r2) newSortedRS+ SDL.present renderer++ +removeOutOfBounds :: Graphics -> Graphics+removeOutOfBounds graphics =+ let cam = camera graphics+ objs = objects graphics+ (V2 bR bT) = cPos cam + cSize cam/2+ (V2 bL bB) = cPos cam - cSize cam/2+ notOutOfBounds s = not $+ let (V4 r l u d) = shapeToBorders s+ in r < bL || l > bR || u < bB || d > bT+ in graphics{objects=filter (notOutOfBounds) objs}++adjustToCamera :: Graphics -> Graphics+adjustToCamera gra =+ let cam = camera gra+ obs = objects gra+ in gra{objects = (\rs -> adjustToCamera' cam rs) <$> obs}+++adjustToCamera' :: Camera -> RenderShape -> RenderShape+adjustToCamera' c rs =+ let (V2 cx cy) = cPos c+ (V2 w h) = cSize c+ s = shape rs+ adjustPoint (V2 x y) = V2 (x+w/2-cx) (h/2-(y+cy))+ inverseY (V2 x y) = V2 x (-y)+ adjustedCentre = adjustPoint (shapeCentre rs)+ adjustedShape = case s of+ Triangle{ pointA=pA, pointB=pB, pointC=pC} ->+ s{pointA=inverseY pA, pointB = inverseY pB, pointC=inverseY pC}+ otherwise -> s+ in rs{shapeCentre=adjustedCentre, shape=adjustedShape}++-- actual renderfunction+renderShape :: MVar [(String, (SDL.Texture, V2 Int))] -> SDL.Renderer -> RenderShape -> IO ()+renderShape mvarTextures renderer renderShape =+ let shape' = shape renderShape+ centre' = shapeCentre renderShape+ in case shape' of+ Rectangle {rectSize = rectSize'} -> do+ let (RGB r g b) = toSRGB24 (sColour shape')+ let draw = if sFilled shape' then GFX.fillRectangle else GFX.rectangle+ draw renderer+ (round <$> centre'-rectSize'/2)+ (round <$> centre'+rectSize'/2)+ (V4 r g b maxBound)+ Circle {radius=rad'} -> do+ let (RGB r g b) = toSRGB24 (sColour shape')+ let draw = if sFilled shape' then GFX.fillCircle else GFX.circle+ draw renderer+ (round <$> centre')+ (round rad')+ (V4 r g b maxBound)+ Triangle {pointA=V2 pax pay, pointB=V2 pbx pby, pointC=V2 pcx pcy, colour=c'} -> do+ let (RGB r g b) = toSRGB24 (sColour shape')+ (V2 x y) = centre'+ draw = if sFilled shape' then GFX.fillTriangle else GFX.smoothTriangle+ draw renderer+ (round <$> V2 (x + pax) (y + pay))+ (round <$> V2 (x + pbx) (y + pby))+ (round <$> V2 (x + pcx) (y + pcy))+ (V4 r g b maxBound)+ Image {size=size', sourceRect=maybeRect, imgPath=path} -> do+ textures <- readMVar mvarTextures+ case lookup path textures of+ (Just (t,size)) ->+ let newSize = fromMaybe ((fromIntegral<$>size)/2, fromIntegral <$> size) maybeRect+ in drawImage renderer t (return newSize) centre' size'+ Nothing -> do+ eitherSurface <- try $ SDL.loadBMP path :: IO (Either SomeException SDL.Surface)+ case eitherSurface of+ Left ex -> putStrLn $ "IMG Loading failed: " ++ show ex+ Right val -> do++ newTexture <- SDL.createTextureFromSurface renderer val+ attrs <- SDL.queryTexture newTexture+ let w = SDL.textureWidth attrs+ h = SDL.textureHeight attrs+ modifyMVar_ mvarTextures $ return . ((path,(newTexture, fromEnum <$> V2 w h)):)+ drawImage renderer newTexture maybeRect centre' size'+ where drawImage renderer texture source position size = do+ let toSDLRect (V2 x y, V2 w h) =+ SDL.Rectangle (round <$> SDL.P (V2 (x-w/2) (y-h/2))) (round <$> V2 w h)+ SDL.copy renderer texture (toSDLRect <$> source) (return $ toSDLRect (position,size))++++-- wrapper for RenderShape to add shapes which are not drawn to decide if a rerender is necessary+data RenderAction = RealAction RenderShape | ShadowAction RenderShape deriving (Show, Eq)++getShape :: RenderAction -> RenderShape+getShape (RealAction s) = s+getShape (ShadowAction s) = s++isReal :: RenderAction -> Bool+isReal (RealAction _) = True+isReal _ = False++-- TODO: More efficient algorhytm -> delete oldRS elements that are already found;+checkChanged :: [RenderShape] -> [RenderShape] -> [(Bool, RenderAction)]+checkChanged oldRS newRS =+ let changedOldRS = filter (\rs -> rs `notElem` newRS) oldRS+ in fmap (\rs -> ((not (any (==rs) oldRS) || null oldRS), RealAction rs)) newRS ++ fmap (\rs -> (True, ShadowAction rs)) changedOldRS++-- decide which rendershapes need rendering+render' :: [(Bool, RenderAction)] -> [RenderShape]+render' rs = fmap getShape . filter isReal $+ let unchanged = snd <$> filter (not . fst) rs+ changed = snd <$> filter fst rs+ in areUnchangedSame [] unchanged changed++areUnchangedSame :: [RenderAction] -> [RenderAction] -> [RenderAction] -> [RenderAction]+areUnchangedSame compare unchanged changed+ | compare == unchanged = changed+ | otherwise = uncurry (areUnchangedSame unchanged) (checkRenders unchanged $ changed)+++checkRenders :: [RenderAction] -> [RenderAction] -> ([RenderAction],[RenderAction])+checkRenders unchanged changed =+ if null unchanged+ then ([],changed)+ else let tests = fmap (\uc -> ((any (checkIfRenderIsNecessary uc) changed),uc)) unchanged+ in (snd <$> filter (not.fst) tests, changed++(snd <$> filter (fst) tests))+ where checkIfRenderIsNecessary unchangedObject changedObject =+ unchangedObject `isColliding` changedObject+++hasHigherZIndex :: RenderAction -> RenderAction -> Bool+hasHigherZIndex rs1 rs2 = zIndex (getShape rs1) > zIndex (getShape rs2)++isCoveredBy :: RenderAction -> RenderAction -> Bool+isCoveredBy a b =+ let (V4 rr rl rt rb) = shapeToBorders (getShape a)+ (V4 cr cl ct cb) = shapeToBorders (getShape b)+ in rr <= cr && rl >= cl && rt <= ct && rb >= cb++-- FIXME: Not sure if this is right+isColliding :: RenderAction -> RenderAction -> Bool+isColliding s1 s2 =+ let (V4 r1 l1 t1 b1) = shapeToBorders (getShape s1)+ (V4 r2 l2 t2 b2) = shapeToBorders (getShape s2)+ in (((r2 > l1 && r2 < r1) || (l2 > l1 && l2 < r1)) && ((t2 > b1 && t2 < t1) || (b2 > b1 && b2 < t1)))+ || (((r1 > l2 && r1 < r2) || (l1 > l2 && l1 < r2)) && ((t1 > b2 && t1 < t2) || (b1 > b2 && b1 < t2)))++-- TODO: Need to properly implement this; Color and Image can be transparent!+isTransparent :: RenderAction -> Bool+isTransparent = const False++-- Split objects at every x/givenSize==0 to minimize necessary rendering for big shapes if just a part of them changed.++splitObjects :: [(String, (SDL.Texture, V2 Int))] -> Double -> Graphics -> Graphics+splitObjects textures givenSize gra =+ gra{objects=concatMap (splitObjects' textures givenSize) (objects gra)}++splitObjects' :: [(String, (SDL.Texture, V2 Int))] -> Double -> RenderShape -> [RenderShape]+splitObjects' textures xSize rs =+ let (V2 x y) = shapeCentre rs+ in case shape rs of+ Rectangle{rectSize=V2 w h, colour=c} ->+ let (firstPoint, sizes) = calculateSize xSize x w+ in snd $ mapAccumL+ (\curPos (s,nextS) -> (curPos+s/2+nextS/2,RS (V2 curPos y) (Rectangle (V2 s h) c) (zIndex rs)))+ firstPoint+ sizes+ Image{size=V2 w h,imgPath=path,sourceRect=maybeRect} ->+ let sourceR = (flip fromMaybe) maybeRect <$> (\(_,s) -> ((fromIntegral <$> s)/2, fromIntegral <$> s)) <$> lookup path textures+ in case sourceR of+ Just (V2 sX sY,V2 sW sH) ->+ let (firstPoint, sizes) = calculateSize xSize x w+ in snd $ mapAccumL+ (\curPos (s,nextS) -> (curPos+s/2+nextS/2,RS (V2 curPos y) (Image (V2 s h) (return (V2 (curPos*sW/w) sY, V2 ((sW/w)*s) sH)) path) (zIndex rs)))+ firstPoint+ sizes++ Nothing -> [rs]+ otherwise -> [rs]+ where calculateSize :: Double -> Double -> Double -> (Double, [(Double,Double)])+ calculateSize preferredSize screenPos actualWidth =+ let leftSide = screenPos - (actualWidth / 2)+ firstSize = preferredSize - fromIntegral (round leftSide `rem` round preferredSize)+ in if firstSize < actualWidth+ then let lastSize = fromIntegral $ round (actualWidth - firstSize) `rem` round preferredSize+ howManyNormal = round $ (actualWidth - (lastSize + firstSize)) / preferredSize+ firstPoint = leftSide + (firstSize / 2)++ sizes = firstSize:replicate howManyNormal preferredSize++if lastSize /= 0 then [lastSize] else []+ in (firstPoint, sizes `zip` (tail sizes ++ [0]))+ else (leftSide+actualWidth / 2,[(actualWidth,0)])+++-- helper functions+shapeToBorders :: RenderShape -> V4 Double+shapeToBorders rs =+ let s = shape rs+ (V2 x y) = shapeCentre rs+ in case s of+ Rectangle {rectSize=V2 w h} ->+ V4 (x+w/2) (x-w/2) (y+h/2) (y-h/2)+ Circle {radius=r} ->+ V4 (x+r) (x-r) (y+r) (y-r)+ Triangle {pointA=V2 xa ya, pointB=V2 xb yb, pointC=V2 xc yc} ->+ V4 (x+maximum [xa, xb, xc]) (x+minimum [xa, xb, xc]) (y+maximum [ya,yb,yc]) (y-maximum [ya,yb,yc])+ Image {size=V2 w h} ->+ V4 (x+w/2) (x-w/2) (y+h/2) (y-h/2)+++sColour :: Shape -> Colour Double+sColour s =+ case colour s of+ (Filled a) -> a+ (Unfilled a) -> a++sFilled :: Shape -> Bool+sFilled s =+ case colour s of+ (Filled _) -> True+ (Unfilled _) -> False++getY :: V2 a -> a+getY (V2 _ y) = y
src/YampaSDL2/Backend/Output.hs view
@@ -13,7 +13,7 @@ import Data.StateVar (($=), get) import Data.List import Data.Colour.Names-+import Debug.Trace import YampaSDL2.AppOutput ( AppOutput(..) , Graphics (..)@@ -24,32 +24,41 @@ -- changed bool variable does not do anything-outputAction :: Double -> MVar [(String, (SDL.Texture, V2 Int))]-> MVar Double -> MVar (Maybe Graphics) -> SDL.Window -> SDL.Renderer -> Bool -> AppOutput -> IO Bool--outputAction fps mvarTextures mvarFPS mvarG window renderer _ ao = do+outputAction :: Double -> MVar [(String, (SDL.Texture, V2 Int))]-> MVar Double -> MVar Bool -> MVar (Maybe Graphics) -> SDL.Window -> SDL.Renderer -> Bool -> AppOutput -> IO Bool+outputAction fps mvarTextures mvarFPS mvarReady mvarG window renderer _ ao = do lastTime <- readMVar mvarFPS currentTime <- SDL.time ensureFPS <- if currentTime - lastTime > 1/fps then modifyMVar_ mvarFPS (return . const currentTime) >> return True else return False+ ready <- readMVar mvarReady+ when (ensureFPS && ready) $ do+ modifyMVar_ mvarReady (\_ -> return False)+ renderGraphics mvarTextures window renderer (graphics ao)+ modifyMVar_ mvarReady (\_ -> return True)+ return (shouldExit ao) - when ensureFPS (renderGraphics mvarTextures mvarG window renderer (graphics ao)) >> return (shouldExit ao) -renderGraphics :: MVar [(String, (SDL.Texture, V2 Int))] -> MVar (Maybe Graphics) -> SDL.Window -> SDL.Renderer -> Graphics -> IO ()-renderGraphics mvarTextures mvarG window renderer gra = do+renderGraphics :: MVar [(String, (SDL.Texture, V2 Int))] -> SDL.Window -> SDL.Renderer -> Graphics -> IO ()+renderGraphics mvarTextures window renderer gra = do textures <- readMVar mvarTextures let newGraphics =- splitObjects textures 100 $ adjustToCamera $ removeOutOfBounds gra- oldObjects <- fromMaybe [] <$> fmap objects <$> swapMVar mvarG (return newGraphics) (V2 wW wH) <- fmap (fromIntegral . fromEnum) <$> get (SDL.windowSize window) (V2 cW cH) <- return (cSize $ camera gra) SDL.rendererScale renderer $= realToFrac <$> (V2 (wW/cW) (wH/cH))- render mvarTextures renderer oldObjects newGraphics-+ render mvarTextures renderer newGraphics+ -- Preprocessing rendershapes for rendering +render :: MVar [(String, (SDL.Texture, V2 Int))] -> SDL.Renderer -> Graphics -> IO ()+render mvarTextures renderer gra = do+ mapM_ (renderShape mvarTextures renderer) $+ sortBy (\r1 r2 -> zIndex r1 `compare` zIndex r2) (objects gra)+ SDL.present renderer++ removeOutOfBounds :: Graphics -> Graphics removeOutOfBounds graphics = let cam = camera graphics@@ -61,7 +70,6 @@ in r < bL || l > bR || u < bB || d > bT in graphics{objects=filter (notOutOfBounds) objs} - adjustToCamera :: Graphics -> Graphics adjustToCamera gra = let cam = camera gra@@ -83,120 +91,6 @@ otherwise -> s in rs{shapeCentre=adjustedCentre, shape=adjustedShape} --- Split objects at every x/givenSize==0 to minimize necessary rendering for big shapes if just a part of them changed.--splitObjects :: [(String, (SDL.Texture, V2 Int))] -> Double -> Graphics -> Graphics-splitObjects textures givenSize gra =- gra{objects=concatMap (splitObjects' textures givenSize) (objects gra)}--splitObjects' :: [(String, (SDL.Texture, V2 Int))] -> Double -> RenderShape -> [RenderShape]-splitObjects' textures xSize rs =- let (V2 x y) = shapeCentre rs- in case shape rs of- Rectangle{rectSize=V2 w h, colour=c} ->- let (firstPoint, sizes) = calculateSize xSize x w- in snd $ mapAccumL- (\curPos (s,nextS) -> (curPos+s/2+nextS/2,RS (V2 curPos y) (Rectangle (V2 s h) c) (zIndex rs)))- firstPoint- sizes- Image{size=V2 w h,imgPath=path,sourceRect=maybeRect} ->- let sourceR = (flip fromMaybe) maybeRect <$> (\(_,s) -> ((fromIntegral <$> s)/2, fromIntegral <$> s)) <$> lookup path textures- in case sourceR of- Just (V2 sX sY,V2 sW sH) ->- let (firstPoint, sizes) = calculateSize xSize x w- in snd $ mapAccumL- (\curPos (s,nextS) -> (curPos+s/2+nextS/2,RS (V2 curPos y) (Image (V2 s h) (return (V2 (curPos*sW/w) sY, V2 ((sW/w)*s) sH)) path) (zIndex rs)))- firstPoint- sizes-- Nothing -> [rs]- otherwise -> [rs]- where calculateSize :: Double -> Double -> Double -> (Double, [(Double,Double)])- calculateSize preferredSize screenPos actualWidth =- let leftSide = screenPos - (actualWidth / 2)- firstSize = preferredSize - fromIntegral (round leftSide `rem` round preferredSize)- in if firstSize < actualWidth- then let lastSize = fromIntegral $ round (actualWidth - firstSize) `rem` round preferredSize- howManyNormal = round $ (actualWidth - (lastSize + firstSize)) / preferredSize- firstPoint = leftSide + (firstSize / 2)-- sizes = firstSize:replicate howManyNormal preferredSize++if lastSize /= 0 then [lastSize] else []- in (firstPoint, sizes `zip` (tail sizes ++ [0]))- else (leftSide+actualWidth / 2,[(actualWidth,0)])---- Rendering of preprocessed shapes-render :: MVar [(String, (SDL.Texture, V2 Int))] -> SDL.Renderer -> [RenderShape] -> Graphics -> IO ()-render mvarTextures renderer oldRS gra = do- let oldSortedRS = sortBy (\rs1 rs2 -> zIndex rs1 `compare` zIndex rs2) oldRS- newSortedRS = sortBy (\rs1 rs2 -> zIndex rs1 `compare` zIndex rs2) (objects gra)- obsChanged = checkChanged oldSortedRS newSortedRS- rerenderList = render' obsChanged- mapM_ (renderShape mvarTextures renderer) $- sortBy (\r1 r2 -> zIndex r1 `compare` zIndex r2) rerenderList- SDL.present renderer---- wrapper for RenderShape to add shapes which are not drawn to decide if a rerender is necessary-data RenderAction = RealAction RenderShape | ShadowAction RenderShape deriving (Show, Eq)--getShape :: RenderAction -> RenderShape-getShape (RealAction s) = s-getShape (ShadowAction s) = s--isReal :: RenderAction -> Bool-isReal (RealAction _) = True-isReal _ = False---- TODO: More efficient algorhytm -> delete oldRS elements that are already found;-checkChanged :: [RenderShape] -> [RenderShape] -> [(Bool, RenderAction)]-checkChanged oldRS newRS =- let changedOldRS = filter (\rs -> rs `notElem` newRS) oldRS- in fmap (\rs -> ((not (any (==rs) oldRS) || null oldRS), RealAction rs)) newRS ++ fmap (\rs -> (True, ShadowAction rs)) changedOldRS---- decide which rendershapes need rendering-render' :: [(Bool, RenderAction)] -> [RenderShape]-render' rs = fmap getShape . filter isReal $- let unchanged = snd <$> filter (not . fst) rs- changed = snd <$> filter fst rs- in areUnchangedSame [] unchanged changed--areUnchangedSame :: [RenderAction] -> [RenderAction] -> [RenderAction] -> [RenderAction]-areUnchangedSame compare unchanged changed- | compare == unchanged = changed- | otherwise = uncurry (areUnchangedSame unchanged) (checkRenders unchanged $ changed)---checkRenders :: [RenderAction] -> [RenderAction] -> ([RenderAction],[RenderAction])-checkRenders unchanged changed =- if null unchanged- then ([],changed)- else let tests = fmap (\uc -> ((any (checkIfRenderIsNecessary uc) changed),uc)) unchanged- in (snd <$> filter (not.fst) tests, changed++(snd <$> filter (fst) tests))- where checkIfRenderIsNecessary unchangedObject changedObject =- unchangedObject `isColliding` changedObject---hasHigherZIndex :: RenderAction -> RenderAction -> Bool-hasHigherZIndex rs1 rs2 = zIndex (getShape rs1) > zIndex (getShape rs2)--isCoveredBy :: RenderAction -> RenderAction -> Bool-isCoveredBy a b =- let (V4 rr rl rt rb) = shapeToBorders (getShape a)- (V4 cr cl ct cb) = shapeToBorders (getShape b)- in rr <= cr && rl >= cl && rt <= ct && rb >= cb---- FIXME: Not sure if this is right-isColliding :: RenderAction -> RenderAction -> Bool-isColliding s1 s2 =- let (V4 r1 l1 t1 b1) = shapeToBorders (getShape s1)- (V4 r2 l2 t2 b2) = shapeToBorders (getShape s2)- in (((r2 > l1 && r2 < r1) || (l2 > l1 && l2 < r1)) && ((t2 > b1 && t2 < t1) || (b2 > b1 && b2 < t1)))- || (((r1 > l2 && r1 < r2) || (l1 > l2 && l1 < r2)) && ((t1 > b2 && t1 < t2) || (b1 > b2 && b1 < t2)))---- TODO: Need to properly implement this; Color and Image can be transparent!-isTransparent :: RenderAction -> Bool-isTransparent = const False-- -- actual renderfunction renderShape :: MVar [(String, (SDL.Texture, V2 Int))] -> SDL.Renderer -> RenderShape -> IO () renderShape mvarTextures renderer renderShape =@@ -277,6 +171,3 @@ case colour s of (Filled _) -> True (Unfilled _) -> False--getY :: V2 a -> a-getY (V2 _ y) = y
src/YampaSDL2/Backend/SDL.hs view
@@ -30,11 +30,12 @@ lastGraphics <- newMVar Nothing lastRender <- newMVar 0 imageTextures <- newMVar []+ ready <- newMVar True return $ Backend { initAction = Init.initAction , inputAction = Input.inputAction lastInteraction- , outputAction = Output.outputAction (fps bc) imageTextures lastRender lastGraphics window renderer+ , outputAction = Output.outputAction (fps bc) imageTextures lastRender ready lastGraphics window renderer , parseInput = Parse.parseInput , closeAction = Close.closeAction renderer window }
yampa-sdl2.cabal view
@@ -2,10 +2,10 @@ -- -- see: https://github.com/sol/hpack ----- hash: 694c40d0bc1120f6be07f773d63f640aa6d1762152dd862b39c3968f7b793628+-- hash: cce52dd189679a994cdbaa8dcc65371aa6c08473eb4bba5e5a75d5acadbde803 name: yampa-sdl2-version: 0.0.3.0+version: 0.0.3.1 synopsis: Yampa and SDL2 made easy description: yampa-sdl2 lets you start coding your app right away instead of dealing with SDL2 first. category: Graphics@@ -30,6 +30,7 @@ YampaSDL2.AppOutput YampaSDL2.Backend YampaSDL2.Backend.Close+ YampaSDL2.Backend.ExperimentalOutput YampaSDL2.Backend.Init YampaSDL2.Backend.Input YampaSDL2.Backend.Output@@ -48,6 +49,7 @@ , linear , sdl2 >=2.2.0 , sdl2-gfx+ , stm , text default-language: Haskell2010 @@ -66,6 +68,7 @@ , linear , sdl2 >=2.2.0 , sdl2-gfx+ , stm , text , yampa-sdl2 default-language: Haskell2010