sdl2-cairo-0.1.1.0: example/Main.hs
{-# LANGUAGE OverloadedStrings #-}
module Main where
import Control.Monad (unless)
import Control.Monad.State (lift)
import SDL hiding (point, rotate)
import Linear.V2 (V2(..))
import Linear.Affine (Point(..))
import SDL.Cairo
import SDL.Cairo.Canvas
import qualified Graphics.Rendering.Cairo as C
main :: IO ()
main = do
initializeAll
window <- createWindow "SDL2 Cairo Canvas" defaultWindow
renderer <- createRenderer window (-1) defaultRenderer
-- create a texture suitable to use cairo on
texture <- createCairoTexture' renderer window
appLoop renderer texture 0 (V2 0 0)
-- clean up
destroyTexture texture
destroyRenderer renderer
destroyWindow window
return ()
appLoop :: Renderer -> Texture -> Int -> V2 Double -> IO ()
appLoop renderer texture framecount mousepos = do
events <- pollEvents
let quitEvent event = case eventPayload event of
QuitEvent -> True
_ -> False
mouseMoveEvent e = case eventPayload e of
MouseMotionEvent _ -> True
_ -> False
getMousePos (MouseMotionEvent (MouseMotionEventData _ _ _ (P p) _)) = fromIntegral <$> p
getMousePos _ = V2 0 0
mousePositions = map getMousePos $ map eventPayload $ filter mouseMoveEvent events
quit = any quitEvent events
mousepos' = if null mousePositions then mousepos else head mousePositions
-- draw on the texture
withCanvas texture $ do
drawExample
drawRndCircle
drawStars (fromIntegral framecount)
drawTriangleStrip mousepos'
drawBezierTest
-- apply texture and show on screen
copy renderer texture Nothing Nothing
present renderer
delay $ 1000 `div` 60 -- slow down to approx. 60 FPS
unless quit (appLoop renderer texture (framecount+1) mousepos')
-- | draw a circle in a random color
drawRndCircle :: Canvas ()
drawRndCircle = do
rnd <- random (0,255)
fill $ gray rnd
circle (V2 700 500) 100
fill $ gray 255
-- | some shapes, show some features
drawExample :: Canvas ()
drawExample = do
background $ gray 102
stroke $ blue 255
point $ V2 500 10
line (V2 0 0) (V2 100 100)
line (V2 100 0) (V2 0 100)
fill $ red 255 !@ 128
noStroke
rect $ D 200 200 100 100
stroke $ green 255 !@ 128
fill $ blue 255 !@ 128
rect $ centered $ D 200 200 100 100
triangle (V2 700 300) (V2 750 400) (V2 700 400)
strokeWeight 5
strokeJoin LineJoinRound
stroke $ (blue 255 + red 255) !@ 128
fill $ rgb 0 255 255 !@ 128
polygon [V2 600 500,V2 610 505,V2 620 530, V2 600 530]
circle (V2 200 500) 30
strokeWeight 1
ellipse $ D 100 500 30 50
pushMatrix
translate $ V2 350 350
rotate $ pi/4
ellipse $ D 0 0 100 50
popMatrix
ellipse $ D 0 0 100 50
-- render some text
let txtpos = V2 100 50
textFont $ Font "Monospace" 30 False True
offset <- text "sdl2-cairo " txtpos
textFont $ Font "" 30 True False
text "is AWESOME." $ txtpos + offset
return ()
-- use Cairo Render API directly
lift $ do
C.setSourceRGB 1 1 0
C.moveTo 100 300
C.lineTo 200 400
C.stroke
-- | ported star example from Processing home page
drawStars :: Double -> Canvas ()
drawStars frameCount = do
(V2 w h) <- getCanvasSize
stroke $ gray 0
pushMatrix
translate $ V2 (0.2*w) (0.3*h)
rotate $ frameCount / 200
star 0 0 5 70 3
popMatrix
pushMatrix
translate $ V2 (0.5*w) (0.3*h)
rotate $ frameCount / 400
star 0 0 80 100 40
popMatrix
pushMatrix
translate $ V2 (0.8*w) (0.3*h)
rotate $ frameCount / (-100)
star 0 0 30 70 5
popMatrix
star :: Double -> Double -> Double -> Double -> Double -> Canvas ()
star x y r1 r2 n = do
let angle = 2*pi/n
halfAngle = angle/2
p1 a = V2 (x+cos a*r2) (y+sin a*r2)
p2 a = V2 (x+cos (a+halfAngle)*r1) (y+sin (a+halfAngle)*r1)
vertices = concatMap snd $ takeWhile (\(a, _) -> a<2*pi+angle)
$ iterate (\(a, _) -> (a+angle,[p1 a, p2 a])) (0,[])
polygon vertices
-- | ported triangle strip example from Processing homepage
drawTriangleStrip :: V2 Double -> Canvas ()
drawTriangleStrip mousePos = do
(V2 w h) <- getCanvasSize
let (V2 mouseX mouseY) = mousePos
pos = V2 (w/2) (h/4*3)
n = fromIntegral $ round $ mapRange mouseX (0,w) (6,60)
astep = 180/n
insideRadius = 100
outsideRadius = 150
cossin a = V2 (cos a) (sin a)
makeVert a = [ pos+cossin (radians a) * outsideRadius
, pos+cossin (radians $ a+astep)*insideRadius
]
vertices = concatMap makeVert $ map (2*astep*) [0..n]
shape ShapeTriangleStrip vertices
return ()
-- | draw bezier curve examples
drawBezierTest :: Canvas ()
drawBezierTest = do
pushMatrix
translate $ V2 600 0
stroke $ rgb 255 102 0
line (V2 85 20) (V2 10 10)
line (V2 90 90) (V2 15 80)
stroke $ gray 0
bezier (V2 85 20) (V2 10 10) (V2 90 90) (V2 15 80)
translate $ V2 100 0
stroke $ rgb 255 102 0
noFill
line (V2 30 20) (V2 80 5)
line (V2 80 75) (V2 30 75)
stroke $ gray 0
bezier (V2 30 20) (V2 80 5) (V2 80 75) (V2 30 75)
popMatrix