gloss-relative 0.1.1.0 → 0.1.2.0
raw patch · 4 files changed
+66/−7 lines, 4 filesdep ~gloss-relative
Dependency ranges changed: gloss-relative
Files
- README.md +1/−0
- gloss-relative.cabal +4/−4
- src/Graphics/Gloss/Relative/Interface.hs +3/−3
- src/Graphics/Gloss/Relative/Internal/Picture.hs +58/−0
README.md view
@@ -24,4 +24,5 @@ ``` cabal run gloss-relative-checkers cabal run gloss-relative-button+cabal run gloss-relative-drag ```
gloss-relative.cabal view
@@ -1,6 +1,6 @@ cabal-version: 3.0 name: gloss-relative-version: 0.1.1.0+version: 0.1.2.0 synopsis: Painless relative-sized pictures in Gloss. description: A new Frame data type for Gloss that simplifies drawing vector graphics with relative sizes and flexible layouts -- no more hardcoding distances. Bonus: graphics automatically resize when the screen changes, and native mouse hover events over defined screen regions. @@ -46,21 +46,21 @@ executable gloss-relative-checkers import: warnings main-is: Checkers.hs- build-depends: base < 5, gloss-relative >= 0.1.1.0+ build-depends: base < 5, gloss-relative >= 0.1.2.0 hs-source-dirs: examples default-language: Haskell2010 executable gloss-relative-button import: warnings main-is: Button.hs- build-depends: base < 5, gloss-relative >= 0.1.1.0+ build-depends: base < 5, gloss-relative >= 0.1.2.0 hs-source-dirs: examples default-language: Haskell2010 executable gloss-relative-drag import: warnings main-is: Drag.hs- build-depends: base < 5, gloss-relative >= 0.1.1.0+ build-depends: base < 5, gloss-relative >= 0.1.2.0 hs-source-dirs: examples default-language: Haskell2010
src/Graphics/Gloss/Relative/Interface.hs view
@@ -62,7 +62,7 @@ displayRelative dis backColor frame = do screen <- getDisplayDimension dis let pic = renderStaticFrame frame screen- Gloss.display dis backColor pic+ Gloss.display dis backColor pic (Picture.flattenPicture pic) -- | A variant of 'Gloss.displayIO' using 'Frame'. displayRelativeIO@@ -77,7 +77,7 @@ let makePicture = do frame <- makeFrame let pic = renderStaticFrame frame screen- return pic+ return (Picture.flattenPicture pic) Gloss.displayIO dis backColor makePicture eatController -- | A variant of 'Gloss.play' using 'Frame'. The resulting picture is automatically redimensioned on resize events.@@ -127,7 +127,7 @@ writeIORef handler $! h writeIORef currentFrame $! i + 1 Cache.evictOldCacheTable (i+1) simResolution cache- return pic+ return (Picture.flattenPicture pic) let handleEvent ev (w,s) = do h <- readIORef handler fromGlossEvent ev h >>= \e -> case e of
src/Graphics/Gloss/Relative/Internal/Picture.hs view
@@ -28,6 +28,64 @@ catPictures [x] = x catPictures xs = Pictures xs +-- | Flattens a picture, by eliminating some nested transforms.+-- NOTE: OpenGL backends have a nested transforms stack of only 32, so we need to make sure to flatten Pictures before rendering to avoid stack overflows.+flattenPicture :: Picture -> Picture+flattenPicture p = Pictures $ flatten identityMatrix p++-- Representing Affine Transformation Matrices.+-- | a c e |+-- | b d f |+-- | 0 0 1 |+data Matrix = Matrix Float Float Float Float Float Float++identityMatrix :: Matrix+identityMatrix = Matrix 1 0 0 1 0 0++isShearedMatrix :: Matrix -> Bool+isShearedMatrix (Matrix a b c d _ _) = + let dotProduct = a * c + b * d+ epsilon = 0.0001+ in abs dotProduct > epsilon++multiplyMatrix :: Matrix -> Matrix -> Matrix+multiplyMatrix (Matrix a1 b1 c1 d1 e1 f1) (Matrix a2 b2 c2 d2 e2 f2) =+ Matrix (a1*a2 + c1*b2) (b1*a2 + d1*b2)+ (a1*c2 + c1*d2) (b1*c2 + d1*d2)+ (a1*e2 + c1*f2 + e1) (b1*e2 + d1*f2 + f1)++flatten :: Matrix -> Picture -> [Picture]+flatten m pic | isShearedMatrix m = [transformLeaf m pic]+flatten m Blank = []+flatten m (Pictures ps) = concatMap (flatten m) ps+flatten m (Translate x y p) = flatten (m `multiplyMatrix` Matrix 1 0 0 1 x y) p+flatten m (Scale sx sy p) = flatten (m `multiplyMatrix` Matrix sx 0 0 sy 0 0) p+flatten m (Rotate deg p) =+ let rad = -deg * pi / 180 -- Gloss is clockwise+ s = sin rad+ c = cos rad+ in flatten (m `multiplyMatrix` Matrix c (-s) s c 0 0) p+flatten m (Polygon points) = [Polygon (map (transformPoint m) points)]+flatten m (Line points) = [Line (map (transformPoint m) points)]+flatten m pic = [transformLeaf m pic]++transformPoint :: Matrix -> Point -> Point+transformPoint (Matrix a b c d e f) (x, y) = + (a*x + c*y + e, b*x + d*y + f)++transformLeaf :: Matrix -> Picture -> Picture+transformLeaf (Matrix a b c d e f) leaf =+ let+ tx = e+ ty = f+ sx = sqrt (a*a + b*b)+ -- Use the determinant to handle negative scaling/flipping+ det = a*d - b*c+ sy = (signum det) * sqrt (c*c + d*d)+ angle = atan2 b a * 180 / pi+ in+ Translate tx ty $ Rotate (-angle) $ Scale sx sy leaf+ -- * Regions -- | A rectangular region within the screen.