mirror of
https://github.com/reanimate/reanimate.git
synced 2026-09-14 09:32:22 +00:00
1203 lines
104 KiB
HTML
1203 lines
104 KiB
HTML
<html>
|
|
<head>
|
|
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
|
|
<style type="text/css">
|
|
span.lineno { color: white; background: #aaaaaa; border-right: solid white 12px }
|
|
span.nottickedoff { background: yellow}
|
|
span.istickedoff { background: white }
|
|
span.tickonlyfalse { margin: -1px; border: 1px solid #f20913; background: #f20913 }
|
|
span.tickonlytrue { margin: -1px; border: 1px solid #60de51; background: #60de51 }
|
|
span.funcount { font-size: small; color: orange; z-index: 2; position: absolute; right: 20 }
|
|
span.decl { font-weight: bold }
|
|
span.spaces { background: white }
|
|
</style>
|
|
</head>
|
|
<body>
|
|
<pre>
|
|
<span class="decl"><span class="nottickedoff">never executed</span> <span class="tickonlytrue">always true</span> <span class="tickonlyfalse">always false</span></span>
|
|
</pre>
|
|
<pre>
|
|
<span class="lineno"> 1 </span>{-# LANGUAGE ApplicativeDo #-}
|
|
<span class="lineno"> 2 </span>{-# LANGUAGE ExistentialQuantification #-}
|
|
<span class="lineno"> 3 </span>{-# LANGUAGE RankNTypes #-}
|
|
<span class="lineno"> 4 </span>{-# LANGUAGE RecordWildCards #-}
|
|
<span class="lineno"> 5 </span>{-|
|
|
<span class="lineno"> 6 </span>Module : Reanimate.Scene
|
|
<span class="lineno"> 7 </span>Copyright : Written by David Himmelstrup
|
|
<span class="lineno"> 8 </span>License : Unlicense
|
|
<span class="lineno"> 9 </span>Maintainer : lemmih@gmail.com
|
|
<span class="lineno"> 10 </span>Stability : experimental
|
|
<span class="lineno"> 11 </span>Portability : POSIX
|
|
<span class="lineno"> 12 </span>
|
|
<span class="lineno"> 13 </span>Scenes are an imperative way of defining animations.
|
|
<span class="lineno"> 14 </span>
|
|
<span class="lineno"> 15 </span>-}
|
|
<span class="lineno"> 16 </span>module Reanimate.Scene
|
|
<span class="lineno"> 17 </span> ( -- * Scenes
|
|
<span class="lineno"> 18 </span> Scene
|
|
<span class="lineno"> 19 </span> , ZIndex
|
|
<span class="lineno"> 20 </span> , scene -- :: (forall s. Scene s a) -> Animation
|
|
<span class="lineno"> 21 </span> , sceneAnimation -- :: (forall s. Scene s a) -> Animation
|
|
<span class="lineno"> 22 </span> , play -- :: Animation -> Scene s ()
|
|
<span class="lineno"> 23 </span> , fork -- :: Scene s a -> Scene s a
|
|
<span class="lineno"> 24 </span> , queryNow -- :: Scene s Time
|
|
<span class="lineno"> 25 </span> , wait -- :: Duration -> Scene s ()
|
|
<span class="lineno"> 26 </span> , waitUntil -- :: Time -> Scene s ()
|
|
<span class="lineno"> 27 </span> , waitOn -- :: Scene s a -> Scene s a
|
|
<span class="lineno"> 28 </span> , adjustZ -- :: (ZIndex -> ZIndex) -> Scene s a -> Scene s a
|
|
<span class="lineno"> 29 </span> , withSceneDuration -- :: Scene s () -> Scene s Duration
|
|
<span class="lineno"> 30 </span> -- * Variables
|
|
<span class="lineno"> 31 </span> , Var
|
|
<span class="lineno"> 32 </span> , newVar -- :: a -> Scene s (Var s a)
|
|
<span class="lineno"> 33 </span> , readVar -- :: Var s a -> Scene s a
|
|
<span class="lineno"> 34 </span> , writeVar -- :: Var s a -> a -> Scene s ()
|
|
<span class="lineno"> 35 </span> , modifyVar -- :: Var s a -> (a -> a) -> Scene s ()
|
|
<span class="lineno"> 36 </span> , tweenVar -- :: Var s a -> Duration -> (a -> Time -> a) -> Scene s ()
|
|
<span class="lineno"> 37 </span> , tweenVarUnclamped -- :: Var s a -> Duration -> (a -> Time -> a) -> Scene s ()
|
|
<span class="lineno"> 38 </span> , simpleVar -- :: (a -> SVG) -> a -> Scene s (Var s a)
|
|
<span class="lineno"> 39 </span> , findVar -- :: (a -> Bool) -> [Var s a] -> Scene s (Var s a)
|
|
<span class="lineno"> 40 </span> -- * Sprites
|
|
<span class="lineno"> 41 </span> , Sprite
|
|
<span class="lineno"> 42 </span> , Frame
|
|
<span class="lineno"> 43 </span> , unVar -- :: Var s a -> Frame s a
|
|
<span class="lineno"> 44 </span> , spriteT -- :: Frame s Time
|
|
<span class="lineno"> 45 </span> , spriteDuration -- :: Frame s Duration
|
|
<span class="lineno"> 46 </span> , newSprite -- :: Frame s SVG -> Scene s (Sprite s)
|
|
<span class="lineno"> 47 </span> , newSprite_ -- :: Frame s SVG -> Scene s ()
|
|
<span class="lineno"> 48 </span> , newSpriteA -- :: Animation -> Scene s (Sprite s)
|
|
<span class="lineno"> 49 </span> , newSpriteA' -- :: Sync -> Animation -> Scene s (Sprite s)
|
|
<span class="lineno"> 50 </span> , newSpriteSVG -- :: SVG -> Scene s (Sprite s)
|
|
<span class="lineno"> 51 </span> , newSpriteSVG_ -- :: SVG -> Scene s ()
|
|
<span class="lineno"> 52 </span> , destroySprite -- :: Sprite s -> Scene s ()
|
|
<span class="lineno"> 53 </span> , applyVar -- :: Var s a -> Sprite s -> (a -> SVG -> SVG) -> Scene s ()
|
|
<span class="lineno"> 54 </span> , spriteModify -- :: Sprite s -> Frame s ((SVG,ZIndex) -> (SVG, ZIndex)) -> Scene s ()
|
|
<span class="lineno"> 55 </span> , spriteMap -- :: Sprite s -> (SVG -> SVG) -> Scene s ()
|
|
<span class="lineno"> 56 </span> , spriteTween -- :: Sprite s -> Duration -> (Double -> SVG -> SVG) -> Scene s ()
|
|
<span class="lineno"> 57 </span> , spriteVar -- :: Sprite s -> a -> (a -> SVG -> SVG) -> Scene s (Var s a)
|
|
<span class="lineno"> 58 </span> , spriteE -- :: Sprite s -> Effect -> Scene s ()
|
|
<span class="lineno"> 59 </span> , spriteZ -- :: Sprite s -> ZIndex -> Scene s ()
|
|
<span class="lineno"> 60 </span> , spriteScope -- :: Scene s a -> Scene s a
|
|
<span class="lineno"> 61 </span>
|
|
<span class="lineno"> 62 </span> -- * Object API
|
|
<span class="lineno"> 63 </span> , Object
|
|
<span class="lineno"> 64 </span> , ObjectData
|
|
<span class="lineno"> 65 </span> , oNew
|
|
<span class="lineno"> 66 </span> , newObject
|
|
<span class="lineno"> 67 </span> , oModify
|
|
<span class="lineno"> 68 </span> , oModifyS
|
|
<span class="lineno"> 69 </span> , oRead
|
|
<span class="lineno"> 70 </span> , oTween
|
|
<span class="lineno"> 71 </span> , oTweenS
|
|
<span class="lineno"> 72 </span> , oTweenV
|
|
<span class="lineno"> 73 </span> , oTweenVS
|
|
<span class="lineno"> 74 </span> , Renderable(..)
|
|
<span class="lineno"> 75 </span> -- ** Object Properties
|
|
<span class="lineno"> 76 </span> , oTranslate
|
|
<span class="lineno"> 77 </span> , oSVG
|
|
<span class="lineno"> 78 </span> , oContext
|
|
<span class="lineno"> 79 </span> , oMargin
|
|
<span class="lineno"> 80 </span> , oMarginTop
|
|
<span class="lineno"> 81 </span> , oMarginRight
|
|
<span class="lineno"> 82 </span> , oMarginBottom
|
|
<span class="lineno"> 83 </span> , oMarginLeft
|
|
<span class="lineno"> 84 </span> , oBB
|
|
<span class="lineno"> 85 </span> , oBBMinX
|
|
<span class="lineno"> 86 </span> , oBBMinY
|
|
<span class="lineno"> 87 </span> , oBBWidth
|
|
<span class="lineno"> 88 </span> , oBBHeight
|
|
<span class="lineno"> 89 </span> , oOpacity
|
|
<span class="lineno"> 90 </span> , oShown
|
|
<span class="lineno"> 91 </span> , oZIndex
|
|
<span class="lineno"> 92 </span> , oEasing
|
|
<span class="lineno"> 93 </span> , oScale
|
|
<span class="lineno"> 94 </span> , oScaleOrigin
|
|
<span class="lineno"> 95 </span> , oTopY
|
|
<span class="lineno"> 96 </span> , oBottomY
|
|
<span class="lineno"> 97 </span> , oLeftX
|
|
<span class="lineno"> 98 </span> , oRightX
|
|
<span class="lineno"> 99 </span> , oCenterXY
|
|
<span class="lineno"> 100 </span> , oValue
|
|
<span class="lineno"> 101 </span>
|
|
<span class="lineno"> 102 </span> -- ** Graphics object methods
|
|
<span class="lineno"> 103 </span> , oShow
|
|
<span class="lineno"> 104 </span> , oHide
|
|
<span class="lineno"> 105 </span> , oFadeIn
|
|
<span class="lineno"> 106 </span> , oFadeOut
|
|
<span class="lineno"> 107 </span> , oGrow
|
|
<span class="lineno"> 108 </span> , oShrink
|
|
<span class="lineno"> 109 </span> , oTransform
|
|
<span class="lineno"> 110 </span>
|
|
<span class="lineno"> 111 </span> -- ** Pre-defined objects
|
|
<span class="lineno"> 112 </span> , Circle(..)
|
|
<span class="lineno"> 113 </span> , circleRadius
|
|
<span class="lineno"> 114 </span> , Rectangle(..)
|
|
<span class="lineno"> 115 </span> , rectWidth
|
|
<span class="lineno"> 116 </span> , rectHeight
|
|
<span class="lineno"> 117 </span> , Morph(..)
|
|
<span class="lineno"> 118 </span> , morphDelta
|
|
<span class="lineno"> 119 </span> , morphSrc
|
|
<span class="lineno"> 120 </span> , morphDst
|
|
<span class="lineno"> 121 </span> , Camera(..)
|
|
<span class="lineno"> 122 </span> , cameraAttach
|
|
<span class="lineno"> 123 </span> , cameraFocus
|
|
<span class="lineno"> 124 </span> , cameraSetZoom
|
|
<span class="lineno"> 125 </span> , cameraZoom
|
|
<span class="lineno"> 126 </span> , cameraSetPan
|
|
<span class="lineno"> 127 </span> , cameraPan
|
|
<span class="lineno"> 128 </span>
|
|
<span class="lineno"> 129 </span> -- * ST internals
|
|
<span class="lineno"> 130 </span> , liftST
|
|
<span class="lineno"> 131 </span> , transitionO
|
|
<span class="lineno"> 132 </span> , evalScene
|
|
<span class="lineno"> 133 </span> )
|
|
<span class="lineno"> 134 </span>where
|
|
<span class="lineno"> 135 </span>
|
|
<span class="lineno"> 136 </span>import Control.Lens
|
|
<span class="lineno"> 137 </span>import Control.Monad (void)
|
|
<span class="lineno"> 138 </span>import Control.Monad.Fix
|
|
<span class="lineno"> 139 </span>import Control.Monad.ST
|
|
<span class="lineno"> 140 </span>import Control.Monad.State (execState, State)
|
|
<span class="lineno"> 141 </span>import Data.List
|
|
<span class="lineno"> 142 </span>import Data.STRef
|
|
<span class="lineno"> 143 </span>import Graphics.SvgTree (Tree (None))
|
|
<span class="lineno"> 144 </span>import Reanimate.Animation
|
|
<span class="lineno"> 145 </span>import Reanimate.Ease (Signal, curveS, fromToS)
|
|
<span class="lineno"> 146 </span>import Reanimate.Effect
|
|
<span class="lineno"> 147 </span>import Reanimate.Svg.Constructors
|
|
<span class="lineno"> 148 </span>import Reanimate.Svg.BoundingBox
|
|
<span class="lineno"> 149 </span>import Reanimate.Transition
|
|
<span class="lineno"> 150 </span>import Reanimate.Morph.Common (morph)
|
|
<span class="lineno"> 151 </span>import Reanimate.Morph.Linear (linear)
|
|
<span class="lineno"> 152 </span>
|
|
<span class="lineno"> 153 </span>-- | The ZIndex property specifies the stack order of sprites and animations. Elements
|
|
<span class="lineno"> 154 </span>-- with a higher ZIndex will be drawn on top of elements with a lower index.
|
|
<span class="lineno"> 155 </span>type ZIndex = Int
|
|
<span class="lineno"> 156 </span>
|
|
<span class="lineno"> 157 </span>
|
|
<span class="lineno"> 158 </span>-- (seq duration, par duration)
|
|
<span class="lineno"> 159 </span>-- [(Time, Animation, ZIndex)]
|
|
<span class="lineno"> 160 </span>-- Map Time [(Animation, ZIndex)]
|
|
<span class="lineno"> 161 </span>type Gen s = ST s (Duration -> Time -> (SVG, ZIndex))
|
|
<span class="lineno"> 162 </span>-- | A 'Scene' represents a sequence of animations and variables
|
|
<span class="lineno"> 163 </span>-- that change over time.
|
|
<span class="lineno"> 164 </span>newtype Scene s a = M { <span class="istickedoff"><span class="decl"><span class="istickedoff">unM</span></span></span> :: Time -> ST s (a, Duration, Duration, [Gen s]) }
|
|
<span class="lineno"> 165 </span>
|
|
<span class="lineno"> 166 </span>instance Functor (Scene s) where
|
|
<span class="lineno"> 167 </span> <span class="decl"><span class="istickedoff">fmap f action = M $ \t -> do</span>
|
|
<span class="lineno"> 168 </span><span class="spaces"> </span><span class="istickedoff">(a, d1, d2, gens) <- unM action t</span>
|
|
<span class="lineno"> 169 </span><span class="spaces"> </span><span class="istickedoff">return (f a, d1, d2, gens)</span></span>
|
|
<span class="lineno"> 170 </span>
|
|
<span class="lineno"> 171 </span>instance Applicative (Scene s) where
|
|
<span class="lineno"> 172 </span> <span class="decl"><span class="istickedoff">pure a = M $ \_ -> return (a, 0, 0, [])</span></span>
|
|
<span class="lineno"> 173 </span> <span class="decl"><span class="istickedoff">f <*> g = M $ \t -> do</span>
|
|
<span class="lineno"> 174 </span><span class="spaces"> </span><span class="istickedoff">(f', s1, p1, gen1) <- unM f t</span>
|
|
<span class="lineno"> 175 </span><span class="spaces"> </span><span class="istickedoff">(g', s2, p2, gen2) <- unM g (t + s1)</span>
|
|
<span class="lineno"> 176 </span><span class="spaces"> </span><span class="istickedoff">return (f' g', s1 + s2, max p1 (s1 + p2), gen1 ++ gen2)</span></span>
|
|
<span class="lineno"> 177 </span>
|
|
<span class="lineno"> 178 </span>instance Monad (Scene s) where
|
|
<span class="lineno"> 179 </span> <span class="decl"><span class="nottickedoff">return = pure</span></span>
|
|
<span class="lineno"> 180 </span> <span class="decl"><span class="istickedoff">f >>= g = M $ \t -> do</span>
|
|
<span class="lineno"> 181 </span><span class="spaces"> </span><span class="istickedoff">(a, s1, p1, gen1) <- unM f t</span>
|
|
<span class="lineno"> 182 </span><span class="spaces"> </span><span class="istickedoff">(b, s2, p2, gen2) <- unM (g a) (t + s1)</span>
|
|
<span class="lineno"> 183 </span><span class="spaces"> </span><span class="istickedoff">return (b, s1 + s2, max p1 (s1 + p2), gen1 ++ gen2)</span></span>
|
|
<span class="lineno"> 184 </span>
|
|
<span class="lineno"> 185 </span>instance MonadFix (Scene s) where
|
|
<span class="lineno"> 186 </span> <span class="decl"><span class="nottickedoff">mfix fn = M $ \t -> mfix (\v -> let (a, _s, _p, _gens) = v in unM (fn a) t)</span></span>
|
|
<span class="lineno"> 187 </span>
|
|
<span class="lineno"> 188 </span>-- | Lift an ST action into the Scene monad.
|
|
<span class="lineno"> 189 </span>liftST :: ST s a -> Scene s a
|
|
<span class="lineno"> 190 </span><span class="decl"><span class="istickedoff">liftST action = M $ \_ -> action >>= \a -> return (a, 0, 0, [])</span></span>
|
|
<span class="lineno"> 191 </span>
|
|
<span class="lineno"> 192 </span>-- | Evaluate the value of a scene.
|
|
<span class="lineno"> 193 </span>evalScene :: (forall s . Scene s a) -> a
|
|
<span class="lineno"> 194 </span><span class="decl"><span class="nottickedoff">evalScene action = runST $ do</span>
|
|
<span class="lineno"> 195 </span><span class="spaces"> </span><span class="nottickedoff">(val, _, _ , _) <- unM action 0</span>
|
|
<span class="lineno"> 196 </span><span class="spaces"> </span><span class="nottickedoff">return val</span></span>
|
|
<span class="lineno"> 197 </span>
|
|
<span class="lineno"> 198 </span>-- | Render a 'Scene' to an 'Animation'.
|
|
<span class="lineno"> 199 </span>scene :: (forall s . Scene s a) -> Animation
|
|
<span class="lineno"> 200 </span><span class="decl"><span class="nottickedoff">scene = sceneAnimation</span></span>
|
|
<span class="lineno"> 201 </span>
|
|
<span class="lineno"> 202 </span>-- | Render a 'Scene' to an 'Animation'.
|
|
<span class="lineno"> 203 </span>sceneAnimation :: (forall s . Scene s a) -> Animation
|
|
<span class="lineno"> 204 </span><span class="decl"><span class="istickedoff">sceneAnimation action = runST</span>
|
|
<span class="lineno"> 205 </span><span class="spaces"> </span><span class="istickedoff">(do</span>
|
|
<span class="lineno"> 206 </span><span class="spaces"> </span><span class="istickedoff">(_, s, p, gens) <- unM action 0</span>
|
|
<span class="lineno"> 207 </span><span class="spaces"> </span><span class="istickedoff">let dur = max s p</span>
|
|
<span class="lineno"> 208 </span><span class="spaces"> </span><span class="istickedoff">genFns <- sequence gens</span>
|
|
<span class="lineno"> 209 </span><span class="spaces"> </span><span class="istickedoff">return $ mkAnimation</span>
|
|
<span class="lineno"> 210 </span><span class="spaces"> </span><span class="istickedoff">dur</span>
|
|
<span class="lineno"> 211 </span><span class="spaces"> </span><span class="istickedoff">(\t -> mkGroup $ map fst $ sortOn</span>
|
|
<span class="lineno"> 212 </span><span class="spaces"> </span><span class="istickedoff">snd</span>
|
|
<span class="lineno"> 213 </span><span class="spaces"> </span><span class="istickedoff">[ spriteRender dur (t * dur) | spriteRender <- genFns ]</span>
|
|
<span class="lineno"> 214 </span><span class="spaces"> </span><span class="istickedoff">)</span>
|
|
<span class="lineno"> 215 </span><span class="spaces"> </span><span class="istickedoff">)</span></span>
|
|
<span class="lineno"> 216 </span>
|
|
<span class="lineno"> 217 </span>-- | Execute actions in a scene without advancing the clock. Note that scenes do not end before
|
|
<span class="lineno"> 218 </span>-- all forked actions have completed.
|
|
<span class="lineno"> 219 </span>--
|
|
<span class="lineno"> 220 </span>-- Example:
|
|
<span class="lineno"> 221 </span>--
|
|
<span class="lineno"> 222 </span>-- > do fork $ play drawBox
|
|
<span class="lineno"> 223 </span>-- > play drawCircle
|
|
<span class="lineno"> 224 </span>--
|
|
<span class="lineno"> 225 </span>-- <<docs/gifs/doc_fork.gif>>
|
|
<span class="lineno"> 226 </span>fork :: Scene s a -> Scene s a
|
|
<span class="lineno"> 227 </span><span class="decl"><span class="istickedoff">fork (M action) = M $ \t -> do</span>
|
|
<span class="lineno"> 228 </span><span class="spaces"> </span><span class="istickedoff">(a, s, p, gens) <- action t</span>
|
|
<span class="lineno"> 229 </span><span class="spaces"> </span><span class="istickedoff">return (a, 0, max s p, gens)</span></span>
|
|
<span class="lineno"> 230 </span>
|
|
<span class="lineno"> 231 </span>-- | Play an animation once and then remove it. This advances the clock by the duration of the
|
|
<span class="lineno"> 232 </span>-- animation.
|
|
<span class="lineno"> 233 </span>--
|
|
<span class="lineno"> 234 </span>-- Example:
|
|
<span class="lineno"> 235 </span>--
|
|
<span class="lineno"> 236 </span>-- > do play drawBox
|
|
<span class="lineno"> 237 </span>-- > play drawCircle
|
|
<span class="lineno"> 238 </span>--
|
|
<span class="lineno"> 239 </span>-- <<docs/gifs/doc_play.gif>>
|
|
<span class="lineno"> 240 </span>play :: Animation -> Scene s ()
|
|
<span class="lineno"> 241 </span><span class="decl"><span class="istickedoff">play ani = newSpriteA ani >>= destroySprite</span></span>
|
|
<span class="lineno"> 242 </span>
|
|
<span class="lineno"> 243 </span>-- | Query the current clock timestamp.
|
|
<span class="lineno"> 244 </span>--
|
|
<span class="lineno"> 245 </span>-- Example:
|
|
<span class="lineno"> 246 </span>--
|
|
<span class="lineno"> 247 </span>-- > do now <- play drawCircle *> queryNow
|
|
<span class="lineno"> 248 </span>-- > play $ staticFrame 1 $ scale 2 $ withStrokeWidth 0.05 $
|
|
<span class="lineno"> 249 </span>-- > mkText $ "Now=" <> T.pack (show now)
|
|
<span class="lineno"> 250 </span>--
|
|
<span class="lineno"> 251 </span>-- <<docs/gifs/doc_queryNow.gif>>
|
|
<span class="lineno"> 252 </span>queryNow :: Scene s Time
|
|
<span class="lineno"> 253 </span><span class="decl"><span class="istickedoff">queryNow = M $ \t -> return (t, 0, 0, [])</span></span>
|
|
<span class="lineno"> 254 </span>
|
|
<span class="lineno"> 255 </span>-- | Advance the clock by a given number of seconds.
|
|
<span class="lineno"> 256 </span>--
|
|
<span class="lineno"> 257 </span>-- Example:
|
|
<span class="lineno"> 258 </span>--
|
|
<span class="lineno"> 259 </span>-- > do fork $ play drawBox
|
|
<span class="lineno"> 260 </span>-- > wait 1
|
|
<span class="lineno"> 261 </span>-- > play drawCircle
|
|
<span class="lineno"> 262 </span>--
|
|
<span class="lineno"> 263 </span>-- <<docs/gifs/doc_wait.gif>>
|
|
<span class="lineno"> 264 </span>wait :: Duration -> Scene s ()
|
|
<span class="lineno"> 265 </span><span class="decl"><span class="istickedoff">wait d = M $ \_ -> return (<span class="nottickedoff">()</span>, d, 0, [])</span></span>
|
|
<span class="lineno"> 266 </span>
|
|
<span class="lineno"> 267 </span>-- | Wait until the clock is equal to the given timestamp.
|
|
<span class="lineno"> 268 </span>waitUntil :: Time -> Scene s ()
|
|
<span class="lineno"> 269 </span><span class="decl"><span class="nottickedoff">waitUntil tNew = do</span>
|
|
<span class="lineno"> 270 </span><span class="spaces"> </span><span class="nottickedoff">now <- queryNow</span>
|
|
<span class="lineno"> 271 </span><span class="spaces"> </span><span class="nottickedoff">wait (max 0 (tNew - now))</span></span>
|
|
<span class="lineno"> 272 </span>
|
|
<span class="lineno"> 273 </span>-- | Wait until all forked and sequential animations have finished.
|
|
<span class="lineno"> 274 </span>--
|
|
<span class="lineno"> 275 </span>-- Example:
|
|
<span class="lineno"> 276 </span>--
|
|
<span class="lineno"> 277 </span>-- > do waitOn $ fork $ play drawBox
|
|
<span class="lineno"> 278 </span>-- > play drawCircle
|
|
<span class="lineno"> 279 </span>--
|
|
<span class="lineno"> 280 </span>-- <<docs/gifs/doc_waitOn.gif>>
|
|
<span class="lineno"> 281 </span>waitOn :: Scene s a -> Scene s a
|
|
<span class="lineno"> 282 </span><span class="decl"><span class="istickedoff">waitOn (M action) = M $ \t -> do</span>
|
|
<span class="lineno"> 283 </span><span class="spaces"> </span><span class="istickedoff">(a, s, p, gens) <- action t</span>
|
|
<span class="lineno"> 284 </span><span class="spaces"> </span><span class="istickedoff">return (<span class="nottickedoff">a</span>, max s p, 0, gens)</span></span>
|
|
<span class="lineno"> 285 </span>
|
|
<span class="lineno"> 286 </span>-- | Change the ZIndex of a scene.
|
|
<span class="lineno"> 287 </span>adjustZ :: (ZIndex -> ZIndex) -> Scene s a -> Scene s a
|
|
<span class="lineno"> 288 </span><span class="decl"><span class="nottickedoff">adjustZ fn (M action) = M $ \t -> do</span>
|
|
<span class="lineno"> 289 </span><span class="spaces"> </span><span class="nottickedoff">(a, s, p, gens) <- action t</span>
|
|
<span class="lineno"> 290 </span><span class="spaces"> </span><span class="nottickedoff">return (a, s, p, map genFn gens)</span>
|
|
<span class="lineno"> 291 </span><span class="spaces"> </span><span class="nottickedoff">where</span>
|
|
<span class="lineno"> 292 </span><span class="spaces"> </span><span class="nottickedoff">genFn gen = do</span>
|
|
<span class="lineno"> 293 </span><span class="spaces"> </span><span class="nottickedoff">frameGen <- gen</span>
|
|
<span class="lineno"> 294 </span><span class="spaces"> </span><span class="nottickedoff">return $ \d t -> let (svg, z) = frameGen d t in (svg, fn z)</span></span>
|
|
<span class="lineno"> 295 </span>
|
|
<span class="lineno"> 296 </span>-- | Query the duration of a scene.
|
|
<span class="lineno"> 297 </span>withSceneDuration :: Scene s () -> Scene s Duration
|
|
<span class="lineno"> 298 </span><span class="decl"><span class="nottickedoff">withSceneDuration s = do</span>
|
|
<span class="lineno"> 299 </span><span class="spaces"> </span><span class="nottickedoff">t1 <- queryNow</span>
|
|
<span class="lineno"> 300 </span><span class="spaces"> </span><span class="nottickedoff">s</span>
|
|
<span class="lineno"> 301 </span><span class="spaces"> </span><span class="nottickedoff">t2 <- queryNow</span>
|
|
<span class="lineno"> 302 </span><span class="spaces"> </span><span class="nottickedoff">return (t2 - t1)</span></span>
|
|
<span class="lineno"> 303 </span>
|
|
<span class="lineno"> 304 </span>addGen :: Gen s -> Scene s ()
|
|
<span class="lineno"> 305 </span><span class="decl"><span class="istickedoff">addGen gen = M $ \_ -> return (<span class="nottickedoff">()</span>, 0, 0, [gen])</span></span>
|
|
<span class="lineno"> 306 </span>
|
|
<span class="lineno"> 307 </span>-- | Time dependent variable.
|
|
<span class="lineno"> 308 </span>newtype Var s a = Var (STRef s (Time -> a))
|
|
<span class="lineno"> 309 </span>
|
|
<span class="lineno"> 310 </span>-- | Create a new variable with a default value.
|
|
<span class="lineno"> 311 </span>-- Variables always have a defined value even if they are read at a timestamp that is
|
|
<span class="lineno"> 312 </span>-- earlier than when the variable was created. For example:
|
|
<span class="lineno"> 313 </span>--
|
|
<span class="lineno"> 314 </span>-- > do v <- fork (wait 10 >> newVar 0) -- Create a variable at timestamp '10'.
|
|
<span class="lineno"> 315 </span>-- > readVar v -- Read the variable at timestamp '0'.
|
|
<span class="lineno"> 316 </span>-- > -- The value of the variable will be '0'.
|
|
<span class="lineno"> 317 </span>newVar :: a -> Scene s (Var s a)
|
|
<span class="lineno"> 318 </span><span class="decl"><span class="istickedoff">newVar def = Var <$> liftST (newSTRef (const def))</span></span>
|
|
<span class="lineno"> 319 </span>
|
|
<span class="lineno"> 320 </span>-- | Read the value of a variable at the current timestamp.
|
|
<span class="lineno"> 321 </span>readVar :: Var s a -> Scene s a
|
|
<span class="lineno"> 322 </span><span class="decl"><span class="istickedoff">readVar (Var ref) = liftST (readSTRef ref) <*> queryNow</span></span>
|
|
<span class="lineno"> 323 </span>
|
|
<span class="lineno"> 324 </span>-- | Write the value of a variable at the current timestamp.
|
|
<span class="lineno"> 325 </span>--
|
|
<span class="lineno"> 326 </span>-- Example:
|
|
<span class="lineno"> 327 </span>--
|
|
<span class="lineno"> 328 </span>-- > do v <- newVar 0
|
|
<span class="lineno"> 329 </span>-- > newSprite $ mkCircle <$> unVar v
|
|
<span class="lineno"> 330 </span>-- > writeVar v 1; wait 1
|
|
<span class="lineno"> 331 </span>-- > writeVar v 2; wait 1
|
|
<span class="lineno"> 332 </span>-- > writeVar v 3; wait 1
|
|
<span class="lineno"> 333 </span>--
|
|
<span class="lineno"> 334 </span>-- <<docs/gifs/doc_writeVar.gif>>
|
|
<span class="lineno"> 335 </span>writeVar :: Var s a -> a -> Scene s ()
|
|
<span class="lineno"> 336 </span><span class="decl"><span class="istickedoff">writeVar var val = modifyVar var (const val)</span></span>
|
|
<span class="lineno"> 337 </span>
|
|
<span class="lineno"> 338 </span>-- | Modify the value of a variable at the current timestamp and all future timestamps.
|
|
<span class="lineno"> 339 </span>modifyVar :: Var s a -> (a -> a) -> Scene s ()
|
|
<span class="lineno"> 340 </span><span class="decl"><span class="istickedoff">modifyVar (Var ref) fn = do</span>
|
|
<span class="lineno"> 341 </span><span class="spaces"> </span><span class="istickedoff">now <- queryNow</span>
|
|
<span class="lineno"> 342 </span><span class="spaces"> </span><span class="istickedoff">liftST $ modifySTRef ref $ \prev t -> if t < now then prev t else fn <span class="nottickedoff">(prev t)</span></span></span>
|
|
<span class="lineno"> 343 </span>
|
|
<span class="lineno"> 344 </span>-- | Modify a variable between @now@ and @now+duration@.
|
|
<span class="lineno"> 345 </span>-- Note: The modification function is invoked for past timestamps (with a time value of 0) and
|
|
<span class="lineno"> 346 </span>-- for timestamps after @now+duration@ (with a time value of 1). See 'tweenVarUnclamped'.
|
|
<span class="lineno"> 347 </span>tweenVar :: Var s a -> Duration -> (a -> Time -> a) -> Scene s ()
|
|
<span class="lineno"> 348 </span><span class="decl"><span class="istickedoff">tweenVar (Var ref) dur fn = do</span>
|
|
<span class="lineno"> 349 </span><span class="spaces"> </span><span class="istickedoff">now <- queryNow</span>
|
|
<span class="lineno"> 350 </span><span class="spaces"> </span><span class="istickedoff">liftST $ modifySTRef ref $ \prev t -></span>
|
|
<span class="lineno"> 351 </span><span class="spaces"> </span><span class="istickedoff">if t < now</span>
|
|
<span class="lineno"> 352 </span><span class="spaces"> </span><span class="istickedoff">then prev t</span>
|
|
<span class="lineno"> 353 </span><span class="spaces"> </span><span class="istickedoff">else fn (prev t) (max 0 (min dur $ t - now) / dur)</span>
|
|
<span class="lineno"> 354 </span><span class="spaces"> </span><span class="istickedoff">wait dur</span></span>
|
|
<span class="lineno"> 355 </span>
|
|
<span class="lineno"> 356 </span>-- | Modify a variable between @now@ and @now+duration@.
|
|
<span class="lineno"> 357 </span>-- Note: The modification function is invoked for past timestamps (with a negative time value) and
|
|
<span class="lineno"> 358 </span>-- for timestamps after @now+duration@ (with a time value greater than 1).
|
|
<span class="lineno"> 359 </span>tweenVarUnclamped :: Var s a -> Duration -> (a -> Time -> a) -> Scene s ()
|
|
<span class="lineno"> 360 </span><span class="decl"><span class="nottickedoff">tweenVarUnclamped (Var ref) dur fn = do</span>
|
|
<span class="lineno"> 361 </span><span class="spaces"> </span><span class="nottickedoff">now <- queryNow</span>
|
|
<span class="lineno"> 362 </span><span class="spaces"> </span><span class="nottickedoff">liftST $ modifySTRef ref $ \prev t -> fn (prev t) ((t - now) / dur)</span>
|
|
<span class="lineno"> 363 </span><span class="spaces"> </span><span class="nottickedoff">wait dur</span></span>
|
|
<span class="lineno"> 364 </span>
|
|
<span class="lineno"> 365 </span>-- | Create and render a variable. The rendering will be born at the current timestamp
|
|
<span class="lineno"> 366 </span>-- and will persist until the end of the scene.
|
|
<span class="lineno"> 367 </span>--
|
|
<span class="lineno"> 368 </span>-- Example:
|
|
<span class="lineno"> 369 </span>--
|
|
<span class="lineno"> 370 </span>-- > do var <- simpleVar mkCircle 0
|
|
<span class="lineno"> 371 </span>-- > tweenVar var 2 $ \val -> fromToS val (screenHeight/2)
|
|
<span class="lineno"> 372 </span>--
|
|
<span class="lineno"> 373 </span>-- <<docs/gifs/doc_simpleVar.gif>>
|
|
<span class="lineno"> 374 </span>simpleVar :: (a -> SVG) -> a -> Scene s (Var s a)
|
|
<span class="lineno"> 375 </span><span class="decl"><span class="istickedoff">simpleVar render def = do</span>
|
|
<span class="lineno"> 376 </span><span class="spaces"> </span><span class="istickedoff">v <- newVar def</span>
|
|
<span class="lineno"> 377 </span><span class="spaces"> </span><span class="istickedoff">_ <- newSprite $ render <$> unVar v</span>
|
|
<span class="lineno"> 378 </span><span class="spaces"> </span><span class="istickedoff">return v</span></span>
|
|
<span class="lineno"> 379 </span>
|
|
<span class="lineno"> 380 </span>-- | Helper function for filtering variables.
|
|
<span class="lineno"> 381 </span>findVar :: (a -> Bool) -> [Var s a] -> Scene s (Var s a)
|
|
<span class="lineno"> 382 </span><span class="decl"><span class="nottickedoff">findVar _cond [] = error "Variable not found."</span>
|
|
<span class="lineno"> 383 </span><span class="spaces"></span><span class="nottickedoff">findVar cond (v : vs) = do</span>
|
|
<span class="lineno"> 384 </span><span class="spaces"> </span><span class="nottickedoff">val <- readVar v</span>
|
|
<span class="lineno"> 385 </span><span class="spaces"> </span><span class="nottickedoff">if cond val then return v else findVar cond vs</span></span>
|
|
<span class="lineno"> 386 </span>
|
|
<span class="lineno"> 387 </span>-- | Sprites are animations with a given time of birth as well as a time of death.
|
|
<span class="lineno"> 388 </span>-- They can be controlled using variables, tweening, and effects.
|
|
<span class="lineno"> 389 </span>data Sprite s = Sprite Time (STRef s (Duration, ST s (Duration -> Time -> SVG -> (SVG, ZIndex))))
|
|
<span class="lineno"> 390 </span>
|
|
<span class="lineno"> 391 </span>-- | Sprite frame generator. Generates frames over time in a stateful environment.
|
|
<span class="lineno"> 392 </span>newtype Frame s a = Frame { <span class="istickedoff"><span class="decl"><span class="istickedoff">unFrame</span></span></span> :: ST s (Time -> Duration -> Time -> a) }
|
|
<span class="lineno"> 393 </span>
|
|
<span class="lineno"> 394 </span>instance Functor (Frame s) where
|
|
<span class="lineno"> 395 </span> <span class="decl"><span class="istickedoff">fmap fn (Frame gen) = Frame $ do</span>
|
|
<span class="lineno"> 396 </span><span class="spaces"> </span><span class="istickedoff">m <- gen</span>
|
|
<span class="lineno"> 397 </span><span class="spaces"> </span><span class="istickedoff">return (\real_t d t -> fn $ m real_t <span class="nottickedoff">d</span> t)</span></span>
|
|
<span class="lineno"> 398 </span>
|
|
<span class="lineno"> 399 </span>instance Applicative (Frame s) where
|
|
<span class="lineno"> 400 </span> <span class="decl"><span class="istickedoff">pure v = Frame $ return (\_ _ _ -> v)</span></span>
|
|
<span class="lineno"> 401 </span> <span class="decl"><span class="istickedoff">Frame f <*> Frame g = Frame $ do</span>
|
|
<span class="lineno"> 402 </span><span class="spaces"> </span><span class="istickedoff">m1 <- f</span>
|
|
<span class="lineno"> 403 </span><span class="spaces"> </span><span class="istickedoff">m2 <- g</span>
|
|
<span class="lineno"> 404 </span><span class="spaces"> </span><span class="istickedoff">return $ \real_t d t -> m1 real_t <span class="nottickedoff">d</span> t (m2 real_t d <span class="nottickedoff">t</span>)</span></span>
|
|
<span class="lineno"> 405 </span>
|
|
<span class="lineno"> 406 </span>-- | Dereference a variable as a Sprite frame.
|
|
<span class="lineno"> 407 </span>--
|
|
<span class="lineno"> 408 </span>-- Example:
|
|
<span class="lineno"> 409 </span>--
|
|
<span class="lineno"> 410 </span>-- > do v <- newVar 0
|
|
<span class="lineno"> 411 </span>-- > newSprite $ mkCircle <$> unVar v
|
|
<span class="lineno"> 412 </span>-- > tweenVar v 1 $ \val -> fromToS val 3
|
|
<span class="lineno"> 413 </span>-- > tweenVar v 1 $ \val -> fromToS val 0
|
|
<span class="lineno"> 414 </span>--
|
|
<span class="lineno"> 415 </span>-- <<docs/gifs/doc_unVar.gif>>
|
|
<span class="lineno"> 416 </span>unVar :: Var s a -> Frame s a
|
|
<span class="lineno"> 417 </span><span class="decl"><span class="istickedoff">unVar (Var ref) = Frame $ do</span>
|
|
<span class="lineno"> 418 </span><span class="spaces"> </span><span class="istickedoff">fn <- readSTRef ref</span>
|
|
<span class="lineno"> 419 </span><span class="spaces"> </span><span class="istickedoff">return $ \real_t _d _t -> fn real_t</span></span>
|
|
<span class="lineno"> 420 </span>
|
|
<span class="lineno"> 421 </span>
|
|
<span class="lineno"> 422 </span>-- | Dereference seconds since sprite birth.
|
|
<span class="lineno"> 423 </span>spriteT :: Frame s Time
|
|
<span class="lineno"> 424 </span><span class="decl"><span class="istickedoff">spriteT = Frame $ return (\_real_t _d t -> t)</span></span>
|
|
<span class="lineno"> 425 </span>
|
|
<span class="lineno"> 426 </span>-- | Dereference duration of the current sprite.
|
|
<span class="lineno"> 427 </span>spriteDuration :: Frame s Duration
|
|
<span class="lineno"> 428 </span><span class="decl"><span class="istickedoff">spriteDuration = Frame $ return (\_real_t d _t -> d)</span></span>
|
|
<span class="lineno"> 429 </span>
|
|
<span class="lineno"> 430 </span>-- | Create new sprite defined by a frame generator. Unless otherwise specified using
|
|
<span class="lineno"> 431 </span>-- 'destroySprite', the sprite will die at the end of the scene.
|
|
<span class="lineno"> 432 </span>--
|
|
<span class="lineno"> 433 </span>-- Example:
|
|
<span class="lineno"> 434 </span>--
|
|
<span class="lineno"> 435 </span>-- > do newSprite $ mkCircle <$> spriteT -- Circle sprite where radius=time.
|
|
<span class="lineno"> 436 </span>-- > wait 2
|
|
<span class="lineno"> 437 </span>--
|
|
<span class="lineno"> 438 </span>-- <<docs/gifs/doc_newSprite.gif>>
|
|
<span class="lineno"> 439 </span>newSprite :: Frame s SVG -> Scene s (Sprite s)
|
|
<span class="lineno"> 440 </span><span class="decl"><span class="istickedoff">newSprite render = do</span>
|
|
<span class="lineno"> 441 </span><span class="spaces"> </span><span class="istickedoff">now <- queryNow</span>
|
|
<span class="lineno"> 442 </span><span class="spaces"> </span><span class="istickedoff">ref <- liftST $ newSTRef (-1, return $ \_d _t svg -> (svg, 0))</span>
|
|
<span class="lineno"> 443 </span><span class="spaces"> </span><span class="istickedoff">addGen $ do</span>
|
|
<span class="lineno"> 444 </span><span class="spaces"> </span><span class="istickedoff">fn <- unFrame render</span>
|
|
<span class="lineno"> 445 </span><span class="spaces"> </span><span class="istickedoff">(spriteDur, spriteEffectGen) <- readSTRef ref</span>
|
|
<span class="lineno"> 446 </span><span class="spaces"> </span><span class="istickedoff">spriteEffect <- spriteEffectGen</span>
|
|
<span class="lineno"> 447 </span><span class="spaces"> </span><span class="istickedoff">return $ \d absT -></span>
|
|
<span class="lineno"> 448 </span><span class="spaces"> </span><span class="istickedoff">let relD = (if spriteDur < 0 then d else spriteDur) - now</span>
|
|
<span class="lineno"> 449 </span><span class="spaces"> </span><span class="istickedoff">relT = absT - now</span>
|
|
<span class="lineno"> 450 </span><span class="spaces"> </span><span class="istickedoff">-- Sprite is live [now;duration[</span>
|
|
<span class="lineno"> 451 </span><span class="spaces"> </span><span class="istickedoff">-- If we're at the end of a scene, sprites</span>
|
|
<span class="lineno"> 452 </span><span class="spaces"> </span><span class="istickedoff">-- are live: [now;duration]</span>
|
|
<span class="lineno"> 453 </span><span class="spaces"> </span><span class="istickedoff">-- This behavior is difficult to get right. See the 'bug_*' examples for</span>
|
|
<span class="lineno"> 454 </span><span class="spaces"> </span><span class="istickedoff">-- automated tests.</span>
|
|
<span class="lineno"> 455 </span><span class="spaces"> </span><span class="istickedoff">inTimeSlice = relT >= 0 && relT < relD</span>
|
|
<span class="lineno"> 456 </span><span class="spaces"> </span><span class="istickedoff">isLastFrame = d==absT && relT == relD</span>
|
|
<span class="lineno"> 457 </span><span class="spaces"> </span><span class="istickedoff">in if inTimeSlice || isLastFrame</span>
|
|
<span class="lineno"> 458 </span><span class="spaces"> </span><span class="istickedoff">then spriteEffect relD relT (fn absT relD relT)</span>
|
|
<span class="lineno"> 459 </span><span class="spaces"> </span><span class="istickedoff">else (None, 0)</span>
|
|
<span class="lineno"> 460 </span><span class="spaces"> </span><span class="istickedoff">return $ Sprite now ref</span></span>
|
|
<span class="lineno"> 461 </span>
|
|
<span class="lineno"> 462 </span>-- | Create new sprite defined by a frame generator. The sprite will die at
|
|
<span class="lineno"> 463 </span>-- the end of the scene.
|
|
<span class="lineno"> 464 </span>newSprite_ :: Frame s SVG -> Scene s ()
|
|
<span class="lineno"> 465 </span><span class="decl"><span class="istickedoff">newSprite_ = void . newSprite</span></span>
|
|
<span class="lineno"> 466 </span>
|
|
<span class="lineno"> 467 </span>-- | Create a new sprite from an animation. This advances the clock by the
|
|
<span class="lineno"> 468 </span>-- duration of the animation. Unless otherwise specified using
|
|
<span class="lineno"> 469 </span>-- 'destroySprite', the sprite will die at the end of the scene.
|
|
<span class="lineno"> 470 </span>--
|
|
<span class="lineno"> 471 </span>-- Note: If the scene doesn't end immediately after the duration of the
|
|
<span class="lineno"> 472 </span>-- animation, the animation will be stretched to match the lifetime of the
|
|
<span class="lineno"> 473 </span>-- sprite. See 'newSpriteA'' and 'play'.
|
|
<span class="lineno"> 474 </span>--
|
|
<span class="lineno"> 475 </span>-- Example:
|
|
<span class="lineno"> 476 </span>--
|
|
<span class="lineno"> 477 </span>-- > do fork $ newSpriteA drawCircle
|
|
<span class="lineno"> 478 </span>-- > play drawBox
|
|
<span class="lineno"> 479 </span>-- > play $ reverseA drawBox
|
|
<span class="lineno"> 480 </span>--
|
|
<span class="lineno"> 481 </span>-- <<docs/gifs/doc_newSpriteA.gif>>
|
|
<span class="lineno"> 482 </span>newSpriteA :: Animation -> Scene s (Sprite s)
|
|
<span class="lineno"> 483 </span><span class="decl"><span class="istickedoff">newSpriteA = newSpriteA' SyncStretch</span></span>
|
|
<span class="lineno"> 484 </span>
|
|
<span class="lineno"> 485 </span>-- | Create a new sprite from an animation and specify the synchronization policy. This advances
|
|
<span class="lineno"> 486 </span>-- the clock by the duration of the animation.
|
|
<span class="lineno"> 487 </span>--
|
|
<span class="lineno"> 488 </span>-- Example:
|
|
<span class="lineno"> 489 </span>--
|
|
<span class="lineno"> 490 </span>-- > do fork $ newSpriteA' SyncFreeze drawCircle
|
|
<span class="lineno"> 491 </span>-- > play drawBox
|
|
<span class="lineno"> 492 </span>-- > play $ reverseA drawBox
|
|
<span class="lineno"> 493 </span>--
|
|
<span class="lineno"> 494 </span>-- <<docs/gifs/doc_newSpriteA'.gif>>
|
|
<span class="lineno"> 495 </span>newSpriteA' :: Sync -> Animation -> Scene s (Sprite s)
|
|
<span class="lineno"> 496 </span><span class="decl"><span class="istickedoff">newSpriteA' sync animation =</span>
|
|
<span class="lineno"> 497 </span><span class="spaces"> </span><span class="istickedoff">newSprite (getAnimationFrame sync animation <$> spriteT <*> spriteDuration)</span>
|
|
<span class="lineno"> 498 </span><span class="spaces"> </span><span class="istickedoff"><* wait (duration animation)</span></span>
|
|
<span class="lineno"> 499 </span>
|
|
<span class="lineno"> 500 </span>-- | Create a sprite from a static SVG image.
|
|
<span class="lineno"> 501 </span>--
|
|
<span class="lineno"> 502 </span>-- Example:
|
|
<span class="lineno"> 503 </span>--
|
|
<span class="lineno"> 504 </span>-- > do newSpriteSVG $ mkBackground "lightblue"
|
|
<span class="lineno"> 505 </span>-- > play drawCircle
|
|
<span class="lineno"> 506 </span>--
|
|
<span class="lineno"> 507 </span>-- <<docs/gifs/doc_newSpriteSVG.gif>>
|
|
<span class="lineno"> 508 </span>newSpriteSVG :: SVG -> Scene s (Sprite s)
|
|
<span class="lineno"> 509 </span><span class="decl"><span class="istickedoff">newSpriteSVG = newSprite . pure</span></span>
|
|
<span class="lineno"> 510 </span>
|
|
<span class="lineno"> 511 </span>-- | Create a permanent sprite from a static SVG image. Same as `newSpriteSVG`
|
|
<span class="lineno"> 512 </span>-- but the sprite isn't returned and thus cannot be destroyed.
|
|
<span class="lineno"> 513 </span>newSpriteSVG_ :: SVG -> Scene s ()
|
|
<span class="lineno"> 514 </span><span class="decl"><span class="istickedoff">newSpriteSVG_ = void . newSpriteSVG</span></span>
|
|
<span class="lineno"> 515 </span>
|
|
<span class="lineno"> 516 </span>-- | Change the rendering of a sprite using data from a variable. If data from several variables
|
|
<span class="lineno"> 517 </span>-- is needed, use a frame generator instead.
|
|
<span class="lineno"> 518 </span>--
|
|
<span class="lineno"> 519 </span>-- Example:
|
|
<span class="lineno"> 520 </span>--
|
|
<span class="lineno"> 521 </span>-- > do s <- fork $ newSpriteA drawBox
|
|
<span class="lineno"> 522 </span>-- > v <- newVar 0
|
|
<span class="lineno"> 523 </span>-- > applyVar v s rotate
|
|
<span class="lineno"> 524 </span>-- > tweenVar v 2 $ \val -> fromToS val 90
|
|
<span class="lineno"> 525 </span>--
|
|
<span class="lineno"> 526 </span>-- <<docs/gifs/doc_applyVar.gif>>
|
|
<span class="lineno"> 527 </span>applyVar :: Var s a -> Sprite s -> (a -> SVG -> SVG) -> Scene s ()
|
|
<span class="lineno"> 528 </span><span class="decl"><span class="istickedoff">applyVar var sprite fn = spriteModify sprite $ do</span>
|
|
<span class="lineno"> 529 </span><span class="spaces"> </span><span class="istickedoff">varFn <- unVar var</span>
|
|
<span class="lineno"> 530 </span><span class="spaces"> </span><span class="istickedoff">return $ \(svg, zindex) -> (fn varFn svg, zindex)</span></span>
|
|
<span class="lineno"> 531 </span>
|
|
<span class="lineno"> 532 </span>-- | Destroy a sprite, preventing it from being rendered in the future of the scene.
|
|
<span class="lineno"> 533 </span>-- If 'destroySprite' is invoked multiple times, the earliest time-of-death is used.
|
|
<span class="lineno"> 534 </span>--
|
|
<span class="lineno"> 535 </span>-- Example:
|
|
<span class="lineno"> 536 </span>--
|
|
<span class="lineno"> 537 </span>-- > do s <- newSpriteSVG $ withFillOpacity 1 $ mkCircle 1
|
|
<span class="lineno"> 538 </span>-- > fork $ wait 1 >> destroySprite s
|
|
<span class="lineno"> 539 </span>-- > play drawBox
|
|
<span class="lineno"> 540 </span>--
|
|
<span class="lineno"> 541 </span>-- <<docs/gifs/doc_destroySprite.gif>>
|
|
<span class="lineno"> 542 </span>destroySprite :: Sprite s -> Scene s ()
|
|
<span class="lineno"> 543 </span><span class="decl"><span class="istickedoff">destroySprite (Sprite _ ref) = do</span>
|
|
<span class="lineno"> 544 </span><span class="spaces"> </span><span class="istickedoff">now <- queryNow</span>
|
|
<span class="lineno"> 545 </span><span class="spaces"> </span><span class="istickedoff">liftST $ modifySTRef ref $ \(ttl, render) -></span>
|
|
<span class="lineno"> 546 </span><span class="spaces"> </span><span class="istickedoff">(if <span class="tickonlytrue">ttl < 0</span> then now else <span class="nottickedoff">min ttl now</span>, render)</span></span>
|
|
<span class="lineno"> 547 </span>
|
|
<span class="lineno"> 548 </span>-- | Low-level frame modifier.
|
|
<span class="lineno"> 549 </span>spriteModify :: Sprite s -> Frame s ((SVG, ZIndex) -> (SVG, ZIndex)) -> Scene s ()
|
|
<span class="lineno"> 550 </span><span class="decl"><span class="istickedoff">spriteModify (Sprite born ref) modFn = liftST $ modifySTRef ref $ \(ttl, renderGen) -></span>
|
|
<span class="lineno"> 551 </span><span class="spaces"> </span><span class="istickedoff">( ttl</span>
|
|
<span class="lineno"> 552 </span><span class="spaces"> </span><span class="istickedoff">, do</span>
|
|
<span class="lineno"> 553 </span><span class="spaces"> </span><span class="istickedoff">render <- renderGen</span>
|
|
<span class="lineno"> 554 </span><span class="spaces"> </span><span class="istickedoff">modRender <- unFrame modFn</span>
|
|
<span class="lineno"> 555 </span><span class="spaces"> </span><span class="istickedoff">return $ \relD relT -></span>
|
|
<span class="lineno"> 556 </span><span class="spaces"> </span><span class="istickedoff">let absT = relT + born in modRender absT <span class="nottickedoff">relD</span> relT . render <span class="nottickedoff">relD</span> <span class="nottickedoff">relT</span></span>
|
|
<span class="lineno"> 557 </span><span class="spaces"> </span><span class="istickedoff">)</span></span>
|
|
<span class="lineno"> 558 </span>
|
|
<span class="lineno"> 559 </span>-- | Map the SVG output of a sprite.
|
|
<span class="lineno"> 560 </span>--
|
|
<span class="lineno"> 561 </span>-- Example:
|
|
<span class="lineno"> 562 </span>--
|
|
<span class="lineno"> 563 </span>-- > do s <- fork $ newSpriteA drawCircle
|
|
<span class="lineno"> 564 </span>-- > wait 1
|
|
<span class="lineno"> 565 </span>-- > spriteMap s flipYAxis
|
|
<span class="lineno"> 566 </span>--
|
|
<span class="lineno"> 567 </span>-- <<docs/gifs/doc_spriteMap.gif>>
|
|
<span class="lineno"> 568 </span>spriteMap :: Sprite s -> (SVG -> SVG) -> Scene s ()
|
|
<span class="lineno"> 569 </span><span class="decl"><span class="istickedoff">spriteMap sprite@(Sprite born _) fn = do</span>
|
|
<span class="lineno"> 570 </span><span class="spaces"> </span><span class="istickedoff">now <- queryNow</span>
|
|
<span class="lineno"> 571 </span><span class="spaces"> </span><span class="istickedoff">let tDelta = now - born</span>
|
|
<span class="lineno"> 572 </span><span class="spaces"> </span><span class="istickedoff">spriteModify sprite $ do</span>
|
|
<span class="lineno"> 573 </span><span class="spaces"> </span><span class="istickedoff">t <- spriteT</span>
|
|
<span class="lineno"> 574 </span><span class="spaces"> </span><span class="istickedoff">return $ \(svg, zindex) -> (if (t - tDelta) < 0 then svg else fn svg, zindex)</span></span>
|
|
<span class="lineno"> 575 </span>
|
|
<span class="lineno"> 576 </span>-- | Modify the output of a sprite between @now@ and @now+duration@.
|
|
<span class="lineno"> 577 </span>--
|
|
<span class="lineno"> 578 </span>-- Example:
|
|
<span class="lineno"> 579 </span>--
|
|
<span class="lineno"> 580 </span>-- > do s <- fork $ newSpriteA drawCircle
|
|
<span class="lineno"> 581 </span>-- > spriteTween s 1 $ \val -> translate (screenWidth*0.3*val) 0
|
|
<span class="lineno"> 582 </span>--
|
|
<span class="lineno"> 583 </span>-- <<docs/gifs/doc_spriteTween.gif>>
|
|
<span class="lineno"> 584 </span>spriteTween :: Sprite s -> Duration -> (Double -> SVG -> SVG) -> Scene s ()
|
|
<span class="lineno"> 585 </span><span class="decl"><span class="istickedoff">spriteTween sprite@(Sprite born _) dur fn = do</span>
|
|
<span class="lineno"> 586 </span><span class="spaces"> </span><span class="istickedoff">now <- queryNow</span>
|
|
<span class="lineno"> 587 </span><span class="spaces"> </span><span class="istickedoff">let tDelta = now - born</span>
|
|
<span class="lineno"> 588 </span><span class="spaces"> </span><span class="istickedoff">spriteModify sprite $ do</span>
|
|
<span class="lineno"> 589 </span><span class="spaces"> </span><span class="istickedoff">t <- spriteT</span>
|
|
<span class="lineno"> 590 </span><span class="spaces"> </span><span class="istickedoff">return $ \(svg, zindex) -> (fn (clamp 0 1 $ (t - tDelta) / dur) svg, zindex)</span>
|
|
<span class="lineno"> 591 </span><span class="spaces"> </span><span class="istickedoff">wait dur</span>
|
|
<span class="lineno"> 592 </span><span class="spaces"> </span><span class="istickedoff">where</span>
|
|
<span class="lineno"> 593 </span><span class="spaces"> </span><span class="istickedoff">clamp a b v | <span class="tickonlyfalse">v < a</span> = <span class="nottickedoff">a</span></span>
|
|
<span class="lineno"> 594 </span><span class="spaces"> </span><span class="istickedoff">| v > b = b</span>
|
|
<span class="lineno"> 595 </span><span class="spaces"> </span><span class="istickedoff">| <span class="tickonlytrue">otherwise</span> = v</span></span>
|
|
<span class="lineno"> 596 </span>
|
|
<span class="lineno"> 597 </span>-- | Create a new variable and apply it to a sprite.
|
|
<span class="lineno"> 598 </span>--
|
|
<span class="lineno"> 599 </span>-- Example:
|
|
<span class="lineno"> 600 </span>--
|
|
<span class="lineno"> 601 </span>-- > do s <- fork $ newSpriteA drawBox
|
|
<span class="lineno"> 602 </span>-- > v <- spriteVar s 0 rotate
|
|
<span class="lineno"> 603 </span>-- > tweenVar v 2 $ \val -> fromToS val 90
|
|
<span class="lineno"> 604 </span>--
|
|
<span class="lineno"> 605 </span>-- <<docs/gifs/doc_spriteVar.gif>>
|
|
<span class="lineno"> 606 </span>spriteVar :: Sprite s -> a -> (a -> SVG -> SVG) -> Scene s (Var s a)
|
|
<span class="lineno"> 607 </span><span class="decl"><span class="istickedoff">spriteVar sprite def fn = do</span>
|
|
<span class="lineno"> 608 </span><span class="spaces"> </span><span class="istickedoff">v <- newVar def</span>
|
|
<span class="lineno"> 609 </span><span class="spaces"> </span><span class="istickedoff">applyVar v sprite fn</span>
|
|
<span class="lineno"> 610 </span><span class="spaces"> </span><span class="istickedoff">return v</span></span>
|
|
<span class="lineno"> 611 </span>
|
|
<span class="lineno"> 612 </span>-- | Apply an effect to a sprite.
|
|
<span class="lineno"> 613 </span>--
|
|
<span class="lineno"> 614 </span>-- Example:
|
|
<span class="lineno"> 615 </span>--
|
|
<span class="lineno"> 616 </span>-- > do s <- fork $ newSpriteA drawCircle
|
|
<span class="lineno"> 617 </span>-- > spriteE s $ overBeginning 1 fadeInE
|
|
<span class="lineno"> 618 </span>-- > spriteE s $ overEnding 0.5 fadeOutE
|
|
<span class="lineno"> 619 </span>--
|
|
<span class="lineno"> 620 </span>-- <<docs/gifs/doc_spriteE.gif>>
|
|
<span class="lineno"> 621 </span>spriteE :: Sprite s -> Effect -> Scene s ()
|
|
<span class="lineno"> 622 </span><span class="decl"><span class="istickedoff">spriteE (Sprite born ref) effect = do</span>
|
|
<span class="lineno"> 623 </span><span class="spaces"> </span><span class="istickedoff">now <- queryNow</span>
|
|
<span class="lineno"> 624 </span><span class="spaces"> </span><span class="istickedoff">liftST $ modifySTRef ref $ \(ttl, renderGen) -></span>
|
|
<span class="lineno"> 625 </span><span class="spaces"> </span><span class="istickedoff">( ttl</span>
|
|
<span class="lineno"> 626 </span><span class="spaces"> </span><span class="istickedoff">, do</span>
|
|
<span class="lineno"> 627 </span><span class="spaces"> </span><span class="istickedoff">render <- renderGen</span>
|
|
<span class="lineno"> 628 </span><span class="spaces"> </span><span class="istickedoff">return $ \d t svg -></span>
|
|
<span class="lineno"> 629 </span><span class="spaces"> </span><span class="istickedoff">let (svg', z) = render d t svg</span>
|
|
<span class="lineno"> 630 </span><span class="spaces"> </span><span class="istickedoff">in (delayE (max 0 $ now - born) effect d t svg', z)</span>
|
|
<span class="lineno"> 631 </span><span class="spaces"> </span><span class="istickedoff">)</span></span>
|
|
<span class="lineno"> 632 </span>
|
|
<span class="lineno"> 633 </span>-- | Set new ZIndex of a sprite.
|
|
<span class="lineno"> 634 </span>--
|
|
<span class="lineno"> 635 </span>-- Example:
|
|
<span class="lineno"> 636 </span>--
|
|
<span class="lineno"> 637 </span>-- > do s1 <- newSpriteSVG $ withFillOpacity 1 $ withFillColor "blue" $ mkCircle 3
|
|
<span class="lineno"> 638 </span>-- > newSpriteSVG $ withFillOpacity 1 $ withFillColor "red" $ mkRect 8 3
|
|
<span class="lineno"> 639 </span>-- > wait 1
|
|
<span class="lineno"> 640 </span>-- > spriteZ s1 1
|
|
<span class="lineno"> 641 </span>-- > wait 1
|
|
<span class="lineno"> 642 </span>--
|
|
<span class="lineno"> 643 </span>-- <<docs/gifs/doc_spriteZ.gif>>
|
|
<span class="lineno"> 644 </span>spriteZ :: Sprite s -> ZIndex -> Scene s ()
|
|
<span class="lineno"> 645 </span><span class="decl"><span class="istickedoff">spriteZ (Sprite born ref) zindex = do</span>
|
|
<span class="lineno"> 646 </span><span class="spaces"> </span><span class="istickedoff">now <- queryNow</span>
|
|
<span class="lineno"> 647 </span><span class="spaces"> </span><span class="istickedoff">liftST $ modifySTRef ref $ \(ttl, renderGen) -></span>
|
|
<span class="lineno"> 648 </span><span class="spaces"> </span><span class="istickedoff">( ttl</span>
|
|
<span class="lineno"> 649 </span><span class="spaces"> </span><span class="istickedoff">, do</span>
|
|
<span class="lineno"> 650 </span><span class="spaces"> </span><span class="istickedoff">render <- renderGen</span>
|
|
<span class="lineno"> 651 </span><span class="spaces"> </span><span class="istickedoff">return $ \d t svg -></span>
|
|
<span class="lineno"> 652 </span><span class="spaces"> </span><span class="istickedoff">let (svg', z) = render <span class="nottickedoff">d</span> <span class="nottickedoff">t</span> svg in (svg', if t < now - born then z else zindex)</span>
|
|
<span class="lineno"> 653 </span><span class="spaces"> </span><span class="istickedoff">)</span></span>
|
|
<span class="lineno"> 654 </span>
|
|
<span class="lineno"> 655 </span>-- | Destroy all local sprites at the end of a scene.
|
|
<span class="lineno"> 656 </span>--
|
|
<span class="lineno"> 657 </span>-- Example:
|
|
<span class="lineno"> 658 </span>--
|
|
<span class="lineno"> 659 </span>-- > do -- the rect lives through the entire 3s animation
|
|
<span class="lineno"> 660 </span>-- > newSpriteSVG_ $ translate (-3) 0 $ mkRect 4 4
|
|
<span class="lineno"> 661 </span>-- > wait 1
|
|
<span class="lineno"> 662 </span>-- > spriteScope $ do
|
|
<span class="lineno"> 663 </span>-- > -- the circle only lives for 1 second.
|
|
<span class="lineno"> 664 </span>-- > local <- newSpriteSVG $ translate 3 0 $ mkCircle 2
|
|
<span class="lineno"> 665 </span>-- > spriteE local $ overBeginning 0.3 fadeInE
|
|
<span class="lineno"> 666 </span>-- > spriteE local $ overEnding 0.3 fadeOutE
|
|
<span class="lineno"> 667 </span>-- > wait 1
|
|
<span class="lineno"> 668 </span>-- > wait 1
|
|
<span class="lineno"> 669 </span>--
|
|
<span class="lineno"> 670 </span>-- <<docs/gifs/doc_spriteScope.gif>>
|
|
<span class="lineno"> 671 </span>spriteScope :: Scene s a -> Scene s a
|
|
<span class="lineno"> 672 </span><span class="decl"><span class="nottickedoff">spriteScope (M action) = M $ \t -> do</span>
|
|
<span class="lineno"> 673 </span><span class="spaces"> </span><span class="nottickedoff">(a, s, p, gens) <- action t</span>
|
|
<span class="lineno"> 674 </span><span class="spaces"> </span><span class="nottickedoff">return (a, s, p, map (genFn (t+max s p)) gens)</span>
|
|
<span class="lineno"> 675 </span><span class="spaces"> </span><span class="nottickedoff">where</span>
|
|
<span class="lineno"> 676 </span><span class="spaces"> </span><span class="nottickedoff">genFn maxT gen = do</span>
|
|
<span class="lineno"> 677 </span><span class="spaces"> </span><span class="nottickedoff">frameGen <- gen</span>
|
|
<span class="lineno"> 678 </span><span class="spaces"> </span><span class="nottickedoff">return $ \_ t -></span>
|
|
<span class="lineno"> 679 </span><span class="spaces"> </span><span class="nottickedoff">if t < maxT</span>
|
|
<span class="lineno"> 680 </span><span class="spaces"> </span><span class="nottickedoff">then frameGen maxT t</span>
|
|
<span class="lineno"> 681 </span><span class="spaces"> </span><span class="nottickedoff">else (None, 0)</span></span>
|
|
<span class="lineno"> 682 </span>
|
|
<span class="lineno"> 683 </span>asAnimation :: (forall s'. Scene s' a) -> Scene s Animation
|
|
<span class="lineno"> 684 </span><span class="decl"><span class="nottickedoff">asAnimation s = do</span>
|
|
<span class="lineno"> 685 </span><span class="spaces"> </span><span class="nottickedoff">now <- queryNow</span>
|
|
<span class="lineno"> 686 </span><span class="spaces"> </span><span class="nottickedoff">return $ dropA now (sceneAnimation (wait now >> s))</span></span>
|
|
<span class="lineno"> 687 </span>
|
|
<span class="lineno"> 688 </span>-- | Apply a transformation with a given overlap. This makes sure
|
|
<span class="lineno"> 689 </span>-- to keep timestamps intact such that events can still be timed
|
|
<span class="lineno"> 690 </span>-- by transcripts.
|
|
<span class="lineno"> 691 </span>transitionO :: Transition -> Double -> (forall s'. Scene s' a) -> (forall s'. Scene s' b) -> Scene s ()
|
|
<span class="lineno"> 692 </span><span class="decl"><span class="nottickedoff">transitionO t o a b = do</span>
|
|
<span class="lineno"> 693 </span><span class="spaces"> </span><span class="nottickedoff">aA <- asAnimation a</span>
|
|
<span class="lineno"> 694 </span><span class="spaces"> </span><span class="nottickedoff">bA <- fork $ do</span>
|
|
<span class="lineno"> 695 </span><span class="spaces"> </span><span class="nottickedoff">wait (duration aA - o)</span>
|
|
<span class="lineno"> 696 </span><span class="spaces"> </span><span class="nottickedoff">asAnimation b</span>
|
|
<span class="lineno"> 697 </span><span class="spaces"> </span><span class="nottickedoff">play $ overlapT o t aA bA</span></span>
|
|
<span class="lineno"> 698 </span>
|
|
<span class="lineno"> 699 </span>
|
|
<span class="lineno"> 700 </span>
|
|
<span class="lineno"> 701 </span>
|
|
<span class="lineno"> 702 </span>-------------------------------------------------------
|
|
<span class="lineno"> 703 </span>-- Objects
|
|
<span class="lineno"> 704 </span>
|
|
<span class="lineno"> 705 </span>-- | Objects can be any Haskell structure as long as it can be rendered to SVG.
|
|
<span class="lineno"> 706 </span>class Renderable a where
|
|
<span class="lineno"> 707 </span> toSVG :: a -> SVG
|
|
<span class="lineno"> 708 </span>
|
|
<span class="lineno"> 709 </span>instance Renderable Tree where
|
|
<span class="lineno"> 710 </span> <span class="decl"><span class="nottickedoff">toSVG = id</span></span>
|
|
<span class="lineno"> 711 </span>
|
|
<span class="lineno"> 712 </span>-- | Objects are SVG nodes (represented as Haskell values) with
|
|
<span class="lineno"> 713 </span>-- identity, location, and several other properties that can
|
|
<span class="lineno"> 714 </span>-- change over time.
|
|
<span class="lineno"> 715 </span>data Object s a = Object
|
|
<span class="lineno"> 716 </span> { <span class="nottickedoff"><span class="decl"><span class="nottickedoff">objectSprite</span></span></span> :: Sprite s
|
|
<span class="lineno"> 717 </span> , <span class="nottickedoff"><span class="decl"><span class="nottickedoff">objectData</span></span></span> :: Var s (ObjectData a)
|
|
<span class="lineno"> 718 </span> }
|
|
<span class="lineno"> 719 </span>
|
|
<span class="lineno"> 720 </span>-- | Container for object properties.
|
|
<span class="lineno"> 721 </span>data ObjectData a = ObjectData
|
|
<span class="lineno"> 722 </span> { <span class="nottickedoff"><span class="decl"><span class="nottickedoff">_oTranslate</span></span></span> :: (Double, Double)
|
|
<span class="lineno"> 723 </span> , <span class="nottickedoff"><span class="decl"><span class="nottickedoff">_oValueRef</span></span></span> :: a
|
|
<span class="lineno"> 724 </span> , <span class="nottickedoff"><span class="decl"><span class="nottickedoff">_oSVG</span></span></span> :: SVG
|
|
<span class="lineno"> 725 </span> , <span class="nottickedoff"><span class="decl"><span class="nottickedoff">_oContext</span></span></span> :: SVG -> SVG
|
|
<span class="lineno"> 726 </span> , <span class="nottickedoff"><span class="decl"><span class="nottickedoff">_oMargin</span></span></span> :: (Double, Double, Double, Double)
|
|
<span class="lineno"> 727 </span> -- ^ Top, right, bottom, left
|
|
<span class="lineno"> 728 </span> , <span class="nottickedoff"><span class="decl"><span class="nottickedoff">_oBB</span></span></span> :: (Double,Double,Double,Double)
|
|
<span class="lineno"> 729 </span> , <span class="nottickedoff"><span class="decl"><span class="nottickedoff">_oOpacity</span></span></span> :: Double
|
|
<span class="lineno"> 730 </span> , <span class="nottickedoff"><span class="decl"><span class="nottickedoff">_oShown</span></span></span> :: Bool
|
|
<span class="lineno"> 731 </span> , <span class="nottickedoff"><span class="decl"><span class="nottickedoff">_oZIndex</span></span></span> :: Int
|
|
<span class="lineno"> 732 </span> , <span class="nottickedoff"><span class="decl"><span class="nottickedoff">_oEasing</span></span></span> :: Signal
|
|
<span class="lineno"> 733 </span> , <span class="nottickedoff"><span class="decl"><span class="nottickedoff">_oScale</span></span></span> :: Double
|
|
<span class="lineno"> 734 </span> , <span class="nottickedoff"><span class="decl"><span class="nottickedoff">_oScaleOrigin</span></span></span> :: (Double, Double)
|
|
<span class="lineno"> 735 </span> }
|
|
<span class="lineno"> 736 </span>
|
|
<span class="lineno"> 737 </span>-- Basic lenses
|
|
<span class="lineno"> 738 </span>
|
|
<span class="lineno"> 739 </span>-- FIXME: Maybe 'position' is a better name.
|
|
<span class="lineno"> 740 </span>-- | Object position. Default: \<0,0\>
|
|
<span class="lineno"> 741 </span>oTranslate :: Lens' (ObjectData a) (Double, Double)
|
|
<span class="lineno"> 742 </span><span class="decl"><span class="nottickedoff">oTranslate = lens _oTranslate $ \obj val -> obj { _oTranslate = val }</span></span>
|
|
<span class="lineno"> 743 </span>
|
|
<span class="lineno"> 744 </span>-- | Rendered SVG node of an object. Does not include context
|
|
<span class="lineno"> 745 </span>-- or object properties. Read-only.
|
|
<span class="lineno"> 746 </span>oSVG :: Getter (ObjectData a) SVG
|
|
<span class="lineno"> 747 </span><span class="decl"><span class="nottickedoff">oSVG = to _oSVG</span></span>
|
|
<span class="lineno"> 748 </span>
|
|
<span class="lineno"> 749 </span>-- | Custom render context. Is applied to the object for every
|
|
<span class="lineno"> 750 </span>-- frame that it is shown.
|
|
<span class="lineno"> 751 </span>oContext :: Lens' (ObjectData a) (SVG -> SVG)
|
|
<span class="lineno"> 752 </span><span class="decl"><span class="nottickedoff">oContext = lens _oContext $ \obj val -> obj { _oContext = val }</span></span>
|
|
<span class="lineno"> 753 </span>
|
|
<span class="lineno"> 754 </span>-- | Object margins (top, right, bottom, left) in local units.
|
|
<span class="lineno"> 755 </span>oMargin :: Lens' (ObjectData a) (Double, Double, Double, Double)
|
|
<span class="lineno"> 756 </span><span class="decl"><span class="nottickedoff">oMargin = lens _oMargin $ \obj val -> obj { _oMargin = val }</span></span>
|
|
<span class="lineno"> 757 </span>
|
|
<span class="lineno"> 758 </span>-- | Object bounding-box (minimal X-coordinate, minimal Y-coordinate,
|
|
<span class="lineno"> 759 </span>-- width, height). Uses `Reanimate.Svg.BoundingBox.boundingBox`
|
|
<span class="lineno"> 760 </span>-- and has the same limitations.
|
|
<span class="lineno"> 761 </span>oBB :: Getter (ObjectData a) (Double, Double, Double, Double)
|
|
<span class="lineno"> 762 </span><span class="decl"><span class="nottickedoff">oBB = to _oBB</span></span>
|
|
<span class="lineno"> 763 </span>
|
|
<span class="lineno"> 764 </span>-- | Object opacity. Default: 1
|
|
<span class="lineno"> 765 </span>oOpacity :: Lens' (ObjectData a) Double
|
|
<span class="lineno"> 766 </span><span class="decl"><span class="nottickedoff">oOpacity = lens _oOpacity $ \obj val -> obj { _oOpacity = val }</span></span>
|
|
<span class="lineno"> 767 </span>
|
|
<span class="lineno"> 768 </span>-- | Toggle for whether or not the object should be rendered.
|
|
<span class="lineno"> 769 </span>-- Default: False
|
|
<span class="lineno"> 770 </span>oShown :: Lens' (ObjectData a) Bool
|
|
<span class="lineno"> 771 </span><span class="decl"><span class="nottickedoff">oShown = lens _oShown $ \obj val -> obj { _oShown = val }</span></span>
|
|
<span class="lineno"> 772 </span>
|
|
<span class="lineno"> 773 </span>-- | Object's z-index.
|
|
<span class="lineno"> 774 </span>oZIndex :: Lens' (ObjectData a) Int
|
|
<span class="lineno"> 775 </span><span class="decl"><span class="nottickedoff">oZIndex = lens _oZIndex $ \obj val -> obj { _oZIndex = val }</span></span>
|
|
<span class="lineno"> 776 </span>
|
|
<span class="lineno"> 777 </span>-- | Easing function used when modifying object properties.
|
|
<span class="lineno"> 778 </span>-- Default: @'Reanimate.Ease.curveS' 2@
|
|
<span class="lineno"> 779 </span>oEasing :: Lens' (ObjectData a) Signal
|
|
<span class="lineno"> 780 </span><span class="decl"><span class="nottickedoff">oEasing = lens _oEasing $ \obj val -> obj { _oEasing = val }</span></span>
|
|
<span class="lineno"> 781 </span>
|
|
<span class="lineno"> 782 </span>-- | Object's scale. Default: 1
|
|
<span class="lineno"> 783 </span>oScale :: Lens' (ObjectData a) Double
|
|
<span class="lineno"> 784 </span><span class="decl"><span class="nottickedoff">oScale = lens _oScale $ \obj val -> obj { _oScale = val }</span></span>
|
|
<span class="lineno"> 785 </span>
|
|
<span class="lineno"> 786 </span>-- | Origin point for scaling. Default: \<0,0\>
|
|
<span class="lineno"> 787 </span>oScaleOrigin :: Lens' (ObjectData a) (Double, Double)
|
|
<span class="lineno"> 788 </span><span class="decl"><span class="nottickedoff">oScaleOrigin = lens _oScaleOrigin $ \obj val -> obj { _oScaleOrigin = val }</span></span>
|
|
<span class="lineno"> 789 </span>
|
|
<span class="lineno"> 790 </span>-- Smart lenses
|
|
<span class="lineno"> 791 </span>
|
|
<span class="lineno"> 792 </span>-- | Lens for the source value contained in an object.
|
|
<span class="lineno"> 793 </span>oValue :: Renderable a => Lens' (ObjectData a) a
|
|
<span class="lineno"> 794 </span><span class="decl"><span class="nottickedoff">oValue = lens _oValueRef $ \obj newVal -></span>
|
|
<span class="lineno"> 795 </span><span class="spaces"> </span><span class="nottickedoff">let svg = toSVG newVal</span>
|
|
<span class="lineno"> 796 </span><span class="spaces"> </span><span class="nottickedoff">in obj</span>
|
|
<span class="lineno"> 797 </span><span class="spaces"> </span><span class="nottickedoff">{ _oValueRef = newVal</span>
|
|
<span class="lineno"> 798 </span><span class="spaces"> </span><span class="nottickedoff">, _oSVG = svg</span>
|
|
<span class="lineno"> 799 </span><span class="spaces"> </span><span class="nottickedoff">, _oBB = boundingBox svg }</span></span>
|
|
<span class="lineno"> 800 </span>
|
|
<span class="lineno"> 801 </span>-- | Derived location of the top-most point of an object + margin.
|
|
<span class="lineno"> 802 </span>oTopY :: Lens' (ObjectData a) Double
|
|
<span class="lineno"> 803 </span><span class="decl"><span class="nottickedoff">oTopY = lens getter setter</span>
|
|
<span class="lineno"> 804 </span><span class="spaces"> </span><span class="nottickedoff">where</span>
|
|
<span class="lineno"> 805 </span><span class="spaces"> </span><span class="nottickedoff">getter obj = </span>
|
|
<span class="lineno"> 806 </span><span class="spaces"> </span><span class="nottickedoff">let top = obj ^. oMarginTop</span>
|
|
<span class="lineno"> 807 </span><span class="spaces"> </span><span class="nottickedoff">miny = obj ^. oBBMinY</span>
|
|
<span class="lineno"> 808 </span><span class="spaces"> </span><span class="nottickedoff">h = obj ^. oBBHeight</span>
|
|
<span class="lineno"> 809 </span><span class="spaces"> </span><span class="nottickedoff">dy = obj ^. oTranslate . _2</span>
|
|
<span class="lineno"> 810 </span><span class="spaces"> </span><span class="nottickedoff">in dy+miny+h+top</span>
|
|
<span class="lineno"> 811 </span><span class="spaces"> </span><span class="nottickedoff">setter obj val =</span>
|
|
<span class="lineno"> 812 </span><span class="spaces"> </span><span class="nottickedoff">obj & (oTranslate . _2) +~ val-getter obj</span></span>
|
|
<span class="lineno"> 813 </span>
|
|
<span class="lineno"> 814 </span>-- | Derived location of the bottom-most point of an object + margin.
|
|
<span class="lineno"> 815 </span>oBottomY :: Lens' (ObjectData a) Double
|
|
<span class="lineno"> 816 </span><span class="decl"><span class="nottickedoff">oBottomY = lens getter setter</span>
|
|
<span class="lineno"> 817 </span><span class="spaces"> </span><span class="nottickedoff">where</span>
|
|
<span class="lineno"> 818 </span><span class="spaces"> </span><span class="nottickedoff">getter obj = </span>
|
|
<span class="lineno"> 819 </span><span class="spaces"> </span><span class="nottickedoff">let bot = obj ^. oMarginBottom</span>
|
|
<span class="lineno"> 820 </span><span class="spaces"> </span><span class="nottickedoff">miny = obj ^. oBBMinY</span>
|
|
<span class="lineno"> 821 </span><span class="spaces"> </span><span class="nottickedoff">dy = obj ^. oTranslate . _2</span>
|
|
<span class="lineno"> 822 </span><span class="spaces"> </span><span class="nottickedoff">in dy+miny-bot</span>
|
|
<span class="lineno"> 823 </span><span class="spaces"> </span><span class="nottickedoff">setter obj val = </span>
|
|
<span class="lineno"> 824 </span><span class="spaces"> </span><span class="nottickedoff">obj & (oTranslate . _2) +~ val-getter obj</span></span>
|
|
<span class="lineno"> 825 </span>
|
|
<span class="lineno"> 826 </span>-- | Derived location of the left-most point of an object + margin.
|
|
<span class="lineno"> 827 </span>oLeftX :: Lens' (ObjectData a) Double
|
|
<span class="lineno"> 828 </span><span class="decl"><span class="nottickedoff">oLeftX = lens getter setter</span>
|
|
<span class="lineno"> 829 </span><span class="spaces"> </span><span class="nottickedoff">where</span>
|
|
<span class="lineno"> 830 </span><span class="spaces"> </span><span class="nottickedoff">getter obj =</span>
|
|
<span class="lineno"> 831 </span><span class="spaces"> </span><span class="nottickedoff">let left = obj ^. oMarginLeft</span>
|
|
<span class="lineno"> 832 </span><span class="spaces"> </span><span class="nottickedoff">minx = obj ^. oBBMinX</span>
|
|
<span class="lineno"> 833 </span><span class="spaces"> </span><span class="nottickedoff">dx = obj ^. oTranslate . _1</span>
|
|
<span class="lineno"> 834 </span><span class="spaces"> </span><span class="nottickedoff">in dx+minx-left</span>
|
|
<span class="lineno"> 835 </span><span class="spaces"> </span><span class="nottickedoff">setter obj val =</span>
|
|
<span class="lineno"> 836 </span><span class="spaces"> </span><span class="nottickedoff">obj & (oTranslate . _1) +~ val-getter obj</span></span>
|
|
<span class="lineno"> 837 </span>
|
|
<span class="lineno"> 838 </span>-- | Derived location of the right-most point of an object + margin.
|
|
<span class="lineno"> 839 </span>oRightX :: Lens' (ObjectData a) Double
|
|
<span class="lineno"> 840 </span><span class="decl"><span class="nottickedoff">oRightX = lens getter setter</span>
|
|
<span class="lineno"> 841 </span><span class="spaces"> </span><span class="nottickedoff">where</span>
|
|
<span class="lineno"> 842 </span><span class="spaces"> </span><span class="nottickedoff">getter obj =</span>
|
|
<span class="lineno"> 843 </span><span class="spaces"> </span><span class="nottickedoff">let right = obj ^. oMarginRight</span>
|
|
<span class="lineno"> 844 </span><span class="spaces"> </span><span class="nottickedoff">minx = obj ^. oBBMinX</span>
|
|
<span class="lineno"> 845 </span><span class="spaces"> </span><span class="nottickedoff">w = obj ^. oBBWidth</span>
|
|
<span class="lineno"> 846 </span><span class="spaces"> </span><span class="nottickedoff">dx = obj ^. oTranslate . _1</span>
|
|
<span class="lineno"> 847 </span><span class="spaces"> </span><span class="nottickedoff">in dx+minx+w+right</span>
|
|
<span class="lineno"> 848 </span><span class="spaces"> </span><span class="nottickedoff">setter obj val =</span>
|
|
<span class="lineno"> 849 </span><span class="spaces"> </span><span class="nottickedoff">obj & (oTranslate . _1) +~ val-getter obj</span></span>
|
|
<span class="lineno"> 850 </span>
|
|
<span class="lineno"> 851 </span>-- | Derived location of an object's center point.
|
|
<span class="lineno"> 852 </span>oCenterXY :: Lens' (ObjectData a) (Double, Double)
|
|
<span class="lineno"> 853 </span><span class="decl"><span class="nottickedoff">oCenterXY = lens getter setter</span>
|
|
<span class="lineno"> 854 </span><span class="spaces"> </span><span class="nottickedoff">where</span>
|
|
<span class="lineno"> 855 </span><span class="spaces"> </span><span class="nottickedoff">getter obj =</span>
|
|
<span class="lineno"> 856 </span><span class="spaces"> </span><span class="nottickedoff">let minx = obj ^. oBBMinX</span>
|
|
<span class="lineno"> 857 </span><span class="spaces"> </span><span class="nottickedoff">miny = obj ^. oBBMinY</span>
|
|
<span class="lineno"> 858 </span><span class="spaces"> </span><span class="nottickedoff">w = obj ^. oBBWidth</span>
|
|
<span class="lineno"> 859 </span><span class="spaces"> </span><span class="nottickedoff">h = obj ^. oBBHeight</span>
|
|
<span class="lineno"> 860 </span><span class="spaces"> </span><span class="nottickedoff">(dx,dy) = obj ^. oTranslate</span>
|
|
<span class="lineno"> 861 </span><span class="spaces"> </span><span class="nottickedoff">in (dx+minx+w/2, dy+miny+h/2)</span>
|
|
<span class="lineno"> 862 </span><span class="spaces"> </span><span class="nottickedoff">setter obj (dx, dy) =</span>
|
|
<span class="lineno"> 863 </span><span class="spaces"> </span><span class="nottickedoff">let (x,y) = getter obj in</span>
|
|
<span class="lineno"> 864 </span><span class="spaces"> </span><span class="nottickedoff">obj & (oTranslate . _1) +~ dx-x</span>
|
|
<span class="lineno"> 865 </span><span class="spaces"> </span><span class="nottickedoff">& (oTranslate . _2) +~ dy-y</span></span>
|
|
<span class="lineno"> 866 </span>
|
|
<span class="lineno"> 867 </span>-- | Object's top margin.
|
|
<span class="lineno"> 868 </span>oMarginTop :: Lens' (ObjectData a) Double
|
|
<span class="lineno"> 869 </span><span class="decl"><span class="nottickedoff">oMarginTop = oMargin . _1</span></span>
|
|
<span class="lineno"> 870 </span>
|
|
<span class="lineno"> 871 </span>-- | Object's right margin.
|
|
<span class="lineno"> 872 </span>oMarginRight :: Lens' (ObjectData a) Double
|
|
<span class="lineno"> 873 </span><span class="decl"><span class="nottickedoff">oMarginRight = oMargin . _2</span></span>
|
|
<span class="lineno"> 874 </span>
|
|
<span class="lineno"> 875 </span>-- | Object's bottom margin.
|
|
<span class="lineno"> 876 </span>oMarginBottom :: Lens' (ObjectData a) Double
|
|
<span class="lineno"> 877 </span><span class="decl"><span class="nottickedoff">oMarginBottom = oMargin . _3</span></span>
|
|
<span class="lineno"> 878 </span>
|
|
<span class="lineno"> 879 </span>-- | Object's left margin.
|
|
<span class="lineno"> 880 </span>oMarginLeft :: Lens' (ObjectData a) Double
|
|
<span class="lineno"> 881 </span><span class="decl"><span class="nottickedoff">oMarginLeft = oMargin . _4</span></span>
|
|
<span class="lineno"> 882 </span>
|
|
<span class="lineno"> 883 </span>-- | Object's minimal X-coordinate..
|
|
<span class="lineno"> 884 </span>oBBMinX :: Getter (ObjectData a) Double
|
|
<span class="lineno"> 885 </span><span class="decl"><span class="nottickedoff">oBBMinX = oBB . _1</span></span>
|
|
<span class="lineno"> 886 </span>
|
|
<span class="lineno"> 887 </span>-- | Object's minimal Y-coordinate..
|
|
<span class="lineno"> 888 </span>oBBMinY :: Getter (ObjectData a) Double
|
|
<span class="lineno"> 889 </span><span class="decl"><span class="nottickedoff">oBBMinY = oBB . _2</span></span>
|
|
<span class="lineno"> 890 </span>
|
|
<span class="lineno"> 891 </span>-- | Object's width without margin.
|
|
<span class="lineno"> 892 </span>oBBWidth :: Getter (ObjectData a) Double
|
|
<span class="lineno"> 893 </span><span class="decl"><span class="nottickedoff">oBBWidth = oBB . _3</span></span>
|
|
<span class="lineno"> 894 </span>
|
|
<span class="lineno"> 895 </span>-- | Object's height without margin.
|
|
<span class="lineno"> 896 </span>oBBHeight :: Getter (ObjectData a) Double
|
|
<span class="lineno"> 897 </span><span class="decl"><span class="nottickedoff">oBBHeight = oBB . _4</span></span>
|
|
<span class="lineno"> 898 </span>
|
|
<span class="lineno"> 899 </span>-------------------------------------------------------------------------------
|
|
<span class="lineno"> 900 </span>-- Object modifiers
|
|
<span class="lineno"> 901 </span>
|
|
<span class="lineno"> 902 </span>-- | Modify object properties.
|
|
<span class="lineno"> 903 </span>oModify :: Object s a -> (ObjectData a -> ObjectData a) -> Scene s ()
|
|
<span class="lineno"> 904 </span><span class="decl"><span class="nottickedoff">oModify o fn = modifyVar (objectData o) fn</span></span>
|
|
<span class="lineno"> 905 </span>
|
|
<span class="lineno"> 906 </span>-- | Modify object properties using a stateful API.
|
|
<span class="lineno"> 907 </span>oModifyS :: Object s a -> (State (ObjectData a) b) -> Scene s ()
|
|
<span class="lineno"> 908 </span><span class="decl"><span class="nottickedoff">oModifyS o fn = oModify o (execState fn)</span></span>
|
|
<span class="lineno"> 909 </span>
|
|
<span class="lineno"> 910 </span>-- | Query object property.
|
|
<span class="lineno"> 911 </span>oRead :: Object s a -> Getting b (ObjectData a) b -> Scene s b
|
|
<span class="lineno"> 912 </span><span class="decl"><span class="nottickedoff">oRead o l = view l <$> readVar (objectData o)</span></span>
|
|
<span class="lineno"> 913 </span>
|
|
<span class="lineno"> 914 </span>-- | Modify object properties over a set duration.
|
|
<span class="lineno"> 915 </span>oTween :: Object s a -> Duration -> (Double -> ObjectData a -> ObjectData a) -> Scene s ()
|
|
<span class="lineno"> 916 </span><span class="decl"><span class="nottickedoff">oTween o d fn = do</span>
|
|
<span class="lineno"> 917 </span><span class="spaces"> </span><span class="nottickedoff">-- Read 'easing' var here instead of taking it from 'v'.</span>
|
|
<span class="lineno"> 918 </span><span class="spaces"> </span><span class="nottickedoff">-- This allows different easing functions even at the same timestamp.</span>
|
|
<span class="lineno"> 919 </span><span class="spaces"> </span><span class="nottickedoff">ease <- oRead o oEasing</span>
|
|
<span class="lineno"> 920 </span><span class="spaces"> </span><span class="nottickedoff">tweenVar (objectData o) d (\v t -> fn (ease t) v)</span></span>
|
|
<span class="lineno"> 921 </span>
|
|
<span class="lineno"> 922 </span>-- | Modify object properties over a set duration using a stateful API.
|
|
<span class="lineno"> 923 </span>oTweenS :: Object s a -> Duration -> (Double -> State (ObjectData a) b) -> Scene s ()
|
|
<span class="lineno"> 924 </span><span class="decl"><span class="nottickedoff">oTweenS o d fn = oTween o d (\t -> execState (fn t))</span></span>
|
|
<span class="lineno"> 925 </span>
|
|
<span class="lineno"> 926 </span>-- | Modify object value over a set duration. This is a convenience function
|
|
<span class="lineno"> 927 </span>-- for modifying `oValue`.
|
|
<span class="lineno"> 928 </span>oTweenV :: Renderable a => Object s a -> Duration -> (Double -> a -> a) -> Scene s ()
|
|
<span class="lineno"> 929 </span><span class="decl"><span class="nottickedoff">oTweenV o d fn = oTween o d (\t -> oValue %~ fn t)</span></span>
|
|
<span class="lineno"> 930 </span>
|
|
<span class="lineno"> 931 </span>-- | Modify object value over a set duration using a stateful API. This is a
|
|
<span class="lineno"> 932 </span>-- convenience function for modifying `oValue`.
|
|
<span class="lineno"> 933 </span>oTweenVS :: Renderable a => Object s a -> Duration -> (Double -> State a b) -> Scene s ()
|
|
<span class="lineno"> 934 </span><span class="decl"><span class="nottickedoff">oTweenVS o d fn = oTween o d (\t -> oValue %~ execState (fn t))</span></span>
|
|
<span class="lineno"> 935 </span>
|
|
<span class="lineno"> 936 </span>-- | Create new object.
|
|
<span class="lineno"> 937 </span>oNew :: Renderable a => a -> Scene s (Object s a)
|
|
<span class="lineno"> 938 </span><span class="decl"><span class="nottickedoff">oNew = newObject</span></span>
|
|
<span class="lineno"> 939 </span>
|
|
<span class="lineno"> 940 </span>-- | Create new object.
|
|
<span class="lineno"> 941 </span>newObject :: Renderable a => a -> Scene s (Object s a)
|
|
<span class="lineno"> 942 </span><span class="decl"><span class="nottickedoff">newObject val = do</span>
|
|
<span class="lineno"> 943 </span><span class="spaces"> </span><span class="nottickedoff">ref <- newVar ObjectData</span>
|
|
<span class="lineno"> 944 </span><span class="spaces"> </span><span class="nottickedoff">{ _oTranslate = (0,0)</span>
|
|
<span class="lineno"> 945 </span><span class="spaces"> </span><span class="nottickedoff">, _oValueRef = val</span>
|
|
<span class="lineno"> 946 </span><span class="spaces"> </span><span class="nottickedoff">, _oSVG = svg</span>
|
|
<span class="lineno"> 947 </span><span class="spaces"> </span><span class="nottickedoff">, _oContext = id</span>
|
|
<span class="lineno"> 948 </span><span class="spaces"> </span><span class="nottickedoff">, _oMargin = (0.5,0.5,0.5,0.5)</span>
|
|
<span class="lineno"> 949 </span><span class="spaces"> </span><span class="nottickedoff">, _oBB = boundingBox svg</span>
|
|
<span class="lineno"> 950 </span><span class="spaces"> </span><span class="nottickedoff">, _oOpacity = 1</span>
|
|
<span class="lineno"> 951 </span><span class="spaces"> </span><span class="nottickedoff">, _oShown = False</span>
|
|
<span class="lineno"> 952 </span><span class="spaces"> </span><span class="nottickedoff">, _oZIndex = 1</span>
|
|
<span class="lineno"> 953 </span><span class="spaces"> </span><span class="nottickedoff">, _oEasing = curveS 2</span>
|
|
<span class="lineno"> 954 </span><span class="spaces"> </span><span class="nottickedoff">, _oScale = 1</span>
|
|
<span class="lineno"> 955 </span><span class="spaces"> </span><span class="nottickedoff">, _oScaleOrigin = (0,0)</span>
|
|
<span class="lineno"> 956 </span><span class="spaces"> </span><span class="nottickedoff">}</span>
|
|
<span class="lineno"> 957 </span><span class="spaces"> </span><span class="nottickedoff">sprite <- newSprite $ do</span>
|
|
<span class="lineno"> 958 </span><span class="spaces"> </span><span class="nottickedoff">~ObjectData{..} <- unVar ref</span>
|
|
<span class="lineno"> 959 </span><span class="spaces"> </span><span class="nottickedoff">pure $</span>
|
|
<span class="lineno"> 960 </span><span class="spaces"> </span><span class="nottickedoff">if _oShown</span>
|
|
<span class="lineno"> 961 </span><span class="spaces"> </span><span class="nottickedoff">then</span>
|
|
<span class="lineno"> 962 </span><span class="spaces"> </span><span class="nottickedoff">uncurry translate _oTranslate $</span>
|
|
<span class="lineno"> 963 </span><span class="spaces"> </span><span class="nottickedoff">uncurry translate (_oScaleOrigin & both %~ negate) $</span>
|
|
<span class="lineno"> 964 </span><span class="spaces"> </span><span class="nottickedoff">scale _oScale $</span>
|
|
<span class="lineno"> 965 </span><span class="spaces"> </span><span class="nottickedoff">uncurry translate _oScaleOrigin $</span>
|
|
<span class="lineno"> 966 </span><span class="spaces"> </span><span class="nottickedoff">withGroupOpacity _oOpacity $</span>
|
|
<span class="lineno"> 967 </span><span class="spaces"> </span><span class="nottickedoff">_oContext _oSVG</span>
|
|
<span class="lineno"> 968 </span><span class="spaces"> </span><span class="nottickedoff">else None</span>
|
|
<span class="lineno"> 969 </span><span class="spaces"> </span><span class="nottickedoff">spriteModify sprite $ do</span>
|
|
<span class="lineno"> 970 </span><span class="spaces"> </span><span class="nottickedoff">~ObjectData{_oZIndex=z} <- unVar ref</span>
|
|
<span class="lineno"> 971 </span><span class="spaces"> </span><span class="nottickedoff">pure $ \(img,_) -> (img,z)</span>
|
|
<span class="lineno"> 972 </span><span class="spaces"> </span><span class="nottickedoff">return Object</span>
|
|
<span class="lineno"> 973 </span><span class="spaces"> </span><span class="nottickedoff">{ objectSprite = sprite</span>
|
|
<span class="lineno"> 974 </span><span class="spaces"> </span><span class="nottickedoff">, objectData = ref }</span>
|
|
<span class="lineno"> 975 </span><span class="spaces"> </span><span class="nottickedoff">where</span>
|
|
<span class="lineno"> 976 </span><span class="spaces"> </span><span class="nottickedoff">svg = toSVG val</span></span>
|
|
<span class="lineno"> 977 </span>
|
|
<span class="lineno"> 978 </span>-------------------------------------------------------------------------------
|
|
<span class="lineno"> 979 </span>-- Graphical transformations
|
|
<span class="lineno"> 980 </span>
|
|
<span class="lineno"> 981 </span>-- | Instantly show object.
|
|
<span class="lineno"> 982 </span>oShow :: Object s a -> Scene s ()
|
|
<span class="lineno"> 983 </span><span class="decl"><span class="nottickedoff">oShow o = oModify o $ oShown .~ True</span></span>
|
|
<span class="lineno"> 984 </span>
|
|
<span class="lineno"> 985 </span>-- | Instantly hide object.
|
|
<span class="lineno"> 986 </span>oHide :: Object s a -> Scene s ()
|
|
<span class="lineno"> 987 </span><span class="decl"><span class="nottickedoff">oHide o = oModify o $ oShown .~ False</span></span>
|
|
<span class="lineno"> 988 </span>
|
|
<span class="lineno"> 989 </span>-- | Fade in object over a set duration.
|
|
<span class="lineno"> 990 </span>oFadeIn :: Object s a -> Duration -> Scene s ()
|
|
<span class="lineno"> 991 </span><span class="decl"><span class="nottickedoff">oFadeIn o d = do</span>
|
|
<span class="lineno"> 992 </span><span class="spaces"> </span><span class="nottickedoff">oModify o $ </span>
|
|
<span class="lineno"> 993 </span><span class="spaces"> </span><span class="nottickedoff">oShown .~ True</span>
|
|
<span class="lineno"> 994 </span><span class="spaces"> </span><span class="nottickedoff">oTweenS o d $ \t -></span>
|
|
<span class="lineno"> 995 </span><span class="spaces"> </span><span class="nottickedoff">oOpacity *= t</span></span>
|
|
<span class="lineno"> 996 </span>
|
|
<span class="lineno"> 997 </span>-- | Fade out object over a set duration.
|
|
<span class="lineno"> 998 </span>oFadeOut :: Object s a -> Duration -> Scene s ()
|
|
<span class="lineno"> 999 </span><span class="decl"><span class="nottickedoff">oFadeOut o d = do</span>
|
|
<span class="lineno"> 1000 </span><span class="spaces"> </span><span class="nottickedoff">oModify o $ </span>
|
|
<span class="lineno"> 1001 </span><span class="spaces"> </span><span class="nottickedoff">oShown .~ True</span>
|
|
<span class="lineno"> 1002 </span><span class="spaces"> </span><span class="nottickedoff">oTweenS o d $ \t -></span>
|
|
<span class="lineno"> 1003 </span><span class="spaces"> </span><span class="nottickedoff">oOpacity *= 1-t</span></span>
|
|
<span class="lineno"> 1004 </span>
|
|
<span class="lineno"> 1005 </span>-- | Scale in object over a set duration.
|
|
<span class="lineno"> 1006 </span>oGrow :: Object s a -> Duration -> Scene s ()
|
|
<span class="lineno"> 1007 </span><span class="decl"><span class="nottickedoff">oGrow o d = do</span>
|
|
<span class="lineno"> 1008 </span><span class="spaces"> </span><span class="nottickedoff">oModify o $ </span>
|
|
<span class="lineno"> 1009 </span><span class="spaces"> </span><span class="nottickedoff">oShown .~ True</span>
|
|
<span class="lineno"> 1010 </span><span class="spaces"> </span><span class="nottickedoff">oTweenS o d $ \t -></span>
|
|
<span class="lineno"> 1011 </span><span class="spaces"> </span><span class="nottickedoff">oScale *= t</span></span>
|
|
<span class="lineno"> 1012 </span>
|
|
<span class="lineno"> 1013 </span>-- | Scale out object over a set duration.
|
|
<span class="lineno"> 1014 </span>oShrink :: Object s a -> Duration -> Scene s ()
|
|
<span class="lineno"> 1015 </span><span class="decl"><span class="nottickedoff">oShrink o d =</span>
|
|
<span class="lineno"> 1016 </span><span class="spaces"> </span><span class="nottickedoff">oTweenS o d $ \t -></span>
|
|
<span class="lineno"> 1017 </span><span class="spaces"> </span><span class="nottickedoff">oScale *= 1-t</span></span>
|
|
<span class="lineno"> 1018 </span>
|
|
<span class="lineno"> 1019 </span>-- FIXME: Also transform attributes: 'opacity', 'scale', 'scaleOrigin'.
|
|
<span class="lineno"> 1020 </span>-- | Morph source object into target object over a set duration.
|
|
<span class="lineno"> 1021 </span>oTransform :: Object s a -> Object s b -> Duration -> Scene s ()
|
|
<span class="lineno"> 1022 </span><span class="decl"><span class="nottickedoff">oTransform src dst d = do</span>
|
|
<span class="lineno"> 1023 </span><span class="spaces"> </span><span class="nottickedoff">srcSvg <- oRead src oSVG</span>
|
|
<span class="lineno"> 1024 </span><span class="spaces"> </span><span class="nottickedoff">srcCtx <- oRead src oContext</span>
|
|
<span class="lineno"> 1025 </span><span class="spaces"> </span><span class="nottickedoff">srcEase <- oRead src oEasing</span>
|
|
<span class="lineno"> 1026 </span><span class="spaces"> </span><span class="nottickedoff">srcLoc <- oRead src oTranslate</span>
|
|
<span class="lineno"> 1027 </span><span class="spaces"> </span><span class="nottickedoff">oModify src $ oShown .~ False</span>
|
|
<span class="lineno"> 1028 </span><span class="spaces"> </span><span class="nottickedoff"></span>
|
|
<span class="lineno"> 1029 </span><span class="spaces"> </span><span class="nottickedoff">dstSvg <- oRead dst oSVG</span>
|
|
<span class="lineno"> 1030 </span><span class="spaces"> </span><span class="nottickedoff">dstCtx <- oRead dst oContext</span>
|
|
<span class="lineno"> 1031 </span><span class="spaces"> </span><span class="nottickedoff">dstLoc <- oRead dst oTranslate</span>
|
|
<span class="lineno"> 1032 </span><span class="spaces"></span><span class="nottickedoff"></span>
|
|
<span class="lineno"> 1033 </span><span class="spaces"> </span><span class="nottickedoff">m <- newObject $ Morph 0 (srcCtx srcSvg) (dstCtx dstSvg)</span>
|
|
<span class="lineno"> 1034 </span><span class="spaces"> </span><span class="nottickedoff">oModifyS m $ do</span>
|
|
<span class="lineno"> 1035 </span><span class="spaces"> </span><span class="nottickedoff">oShown .= True</span>
|
|
<span class="lineno"> 1036 </span><span class="spaces"> </span><span class="nottickedoff">oEasing .= srcEase</span>
|
|
<span class="lineno"> 1037 </span><span class="spaces"> </span><span class="nottickedoff">oTranslate .= srcLoc</span>
|
|
<span class="lineno"> 1038 </span><span class="spaces"> </span><span class="nottickedoff">fork $ oTween m d $ \t -> oTranslate %~ moveTo t dstLoc</span>
|
|
<span class="lineno"> 1039 </span><span class="spaces"> </span><span class="nottickedoff">oTweenV m d $ \t -> morphDelta .~ t</span>
|
|
<span class="lineno"> 1040 </span><span class="spaces"> </span><span class="nottickedoff">oModify m $ oShown .~ False</span>
|
|
<span class="lineno"> 1041 </span><span class="spaces"> </span><span class="nottickedoff">oModify dst $ oShown .~ True</span>
|
|
<span class="lineno"> 1042 </span><span class="spaces"> </span><span class="nottickedoff">where</span>
|
|
<span class="lineno"> 1043 </span><span class="spaces"> </span><span class="nottickedoff">moveTo t (dstX, dstY) (srcX, srcY) =</span>
|
|
<span class="lineno"> 1044 </span><span class="spaces"> </span><span class="nottickedoff">(fromToS srcX dstX t, fromToS srcY dstY t)</span></span>
|
|
<span class="lineno"> 1045 </span>
|
|
<span class="lineno"> 1046 </span>
|
|
<span class="lineno"> 1047 </span>-------------------------------------------------------------------------------
|
|
<span class="lineno"> 1048 </span>-- Built-in objects
|
|
<span class="lineno"> 1049 </span>
|
|
<span class="lineno"> 1050 </span>-- | Basic object mapping to \<circle\/\> in SVG.
|
|
<span class="lineno"> 1051 </span>newtype Circle = Circle {<span class="nottickedoff"><span class="decl"><span class="nottickedoff">_circleRadius</span></span></span> :: Double}
|
|
<span class="lineno"> 1052 </span>
|
|
<span class="lineno"> 1053 </span>-- | Circle radius in local units.
|
|
<span class="lineno"> 1054 </span>circleRadius :: Lens' Circle Double
|
|
<span class="lineno"> 1055 </span><span class="decl"><span class="nottickedoff">circleRadius = iso _circleRadius Circle</span></span>
|
|
<span class="lineno"> 1056 </span>
|
|
<span class="lineno"> 1057 </span>instance Renderable Circle where
|
|
<span class="lineno"> 1058 </span> <span class="decl"><span class="nottickedoff">toSVG (Circle r) = mkCircle r</span></span>
|
|
<span class="lineno"> 1059 </span>
|
|
<span class="lineno"> 1060 </span>-- | Basic object mapping to \<rect\/\> in SVG.
|
|
<span class="lineno"> 1061 </span>data Rectangle = Rectangle { <span class="nottickedoff"><span class="decl"><span class="nottickedoff">_rectWidth</span></span></span> :: Double, <span class="nottickedoff"><span class="decl"><span class="nottickedoff">_rectHeight</span></span></span> :: Double }
|
|
<span class="lineno"> 1062 </span>
|
|
<span class="lineno"> 1063 </span>-- | Rectangle width in local units.
|
|
<span class="lineno"> 1064 </span>rectWidth :: Lens' Rectangle Double
|
|
<span class="lineno"> 1065 </span><span class="decl"><span class="nottickedoff">rectWidth = lens _rectWidth $ \obj val -> obj{_rectWidth=val}</span></span>
|
|
<span class="lineno"> 1066 </span>
|
|
<span class="lineno"> 1067 </span>-- | Rectangle height in local units.
|
|
<span class="lineno"> 1068 </span>rectHeight :: Lens' Rectangle Double
|
|
<span class="lineno"> 1069 </span><span class="decl"><span class="nottickedoff">rectHeight = lens _rectHeight $ \obj val -> obj{_rectHeight=val}</span></span>
|
|
<span class="lineno"> 1070 </span>
|
|
<span class="lineno"> 1071 </span>instance Renderable Rectangle where
|
|
<span class="lineno"> 1072 </span> <span class="decl"><span class="nottickedoff">toSVG (Rectangle w h) = mkRect w h</span></span>
|
|
<span class="lineno"> 1073 </span>
|
|
<span class="lineno"> 1074 </span>-- | Object representing an interpolation between SVG nodes.
|
|
<span class="lineno"> 1075 </span>data Morph = Morph { <span class="nottickedoff"><span class="decl"><span class="nottickedoff">_morphDelta</span></span></span> :: Double, <span class="nottickedoff"><span class="decl"><span class="nottickedoff">_morphSrc</span></span></span> :: SVG, <span class="nottickedoff"><span class="decl"><span class="nottickedoff">_morphDst</span></span></span> :: SVG }
|
|
<span class="lineno"> 1076 </span>
|
|
<span class="lineno"> 1077 </span>-- | Control variable for the interpolation. A value of 0 gives the
|
|
<span class="lineno"> 1078 </span>-- source SVG and 1 gives the target svg.
|
|
<span class="lineno"> 1079 </span>morphDelta :: Lens' Morph Double
|
|
<span class="lineno"> 1080 </span><span class="decl"><span class="nottickedoff">morphDelta = lens _morphDelta $ \obj val -> obj{_morphDelta = val}</span></span>
|
|
<span class="lineno"> 1081 </span>
|
|
<span class="lineno"> 1082 </span>-- | Source shape.
|
|
<span class="lineno"> 1083 </span>morphSrc :: Lens' Morph SVG
|
|
<span class="lineno"> 1084 </span><span class="decl"><span class="nottickedoff">morphSrc = lens _morphSrc $ \obj val -> obj{_morphSrc = val}</span></span>
|
|
<span class="lineno"> 1085 </span>
|
|
<span class="lineno"> 1086 </span>-- | Target shape.
|
|
<span class="lineno"> 1087 </span>morphDst :: Lens' Morph SVG
|
|
<span class="lineno"> 1088 </span><span class="decl"><span class="nottickedoff">morphDst = lens _morphDst $ \obj val -> obj{_morphDst = val}</span></span>
|
|
<span class="lineno"> 1089 </span>
|
|
<span class="lineno"> 1090 </span>instance Renderable Morph where
|
|
<span class="lineno"> 1091 </span> <span class="decl"><span class="nottickedoff">toSVG (Morph t src dst) = morph linear src dst t</span></span>
|
|
<span class="lineno"> 1092 </span>
|
|
<span class="lineno"> 1093 </span>-- | Cameras can take control of objects and manipulate them
|
|
<span class="lineno"> 1094 </span>-- with convenient pan and zoom operations.
|
|
<span class="lineno"> 1095 </span>data Camera = Camera
|
|
<span class="lineno"> 1096 </span>instance Renderable Camera where
|
|
<span class="lineno"> 1097 </span> <span class="decl"><span class="nottickedoff">toSVG Camera = None</span></span>
|
|
<span class="lineno"> 1098 </span>
|
|
<span class="lineno"> 1099 </span>-- | Connect an object to a camera such that
|
|
<span class="lineno"> 1100 </span>-- camera settings (position, zoom, and rotation) is
|
|
<span class="lineno"> 1101 </span>-- applied to the object.
|
|
<span class="lineno"> 1102 </span>--
|
|
<span class="lineno"> 1103 </span>-- Example
|
|
<span class="lineno"> 1104 </span>--
|
|
<span class="lineno"> 1105 </span>-- > do cam <- newObject Camera
|
|
<span class="lineno"> 1106 </span>-- > circ <- newObject $ Circle 2
|
|
<span class="lineno"> 1107 </span>-- > oModifyS circ $
|
|
<span class="lineno"> 1108 </span>-- > oContext .= withFillOpacity 1 . withFillColor "blue"
|
|
<span class="lineno"> 1109 </span>-- > oShow circ
|
|
<span class="lineno"> 1110 </span>-- > cameraAttach cam circ
|
|
<span class="lineno"> 1111 </span>-- > cameraZoom cam 1 2
|
|
<span class="lineno"> 1112 </span>-- > cameraZoom cam 1 1
|
|
<span class="lineno"> 1113 </span>--
|
|
<span class="lineno"> 1114 </span>-- <<docs/gifs/doc_cameraAttach.gif>>
|
|
<span class="lineno"> 1115 </span>cameraAttach :: Object s Camera -> Object s a -> Scene s ()
|
|
<span class="lineno"> 1116 </span><span class="decl"><span class="nottickedoff">cameraAttach cam obj =</span>
|
|
<span class="lineno"> 1117 </span><span class="spaces"> </span><span class="nottickedoff">spriteModify (objectSprite obj) $ do</span>
|
|
<span class="lineno"> 1118 </span><span class="spaces"> </span><span class="nottickedoff">camData <- unVar (objectData cam)</span>
|
|
<span class="lineno"> 1119 </span><span class="spaces"> </span><span class="nottickedoff">return $ \(svg,zindex) -></span>
|
|
<span class="lineno"> 1120 </span><span class="spaces"> </span><span class="nottickedoff">let (x,y) = camData^.oTranslate</span>
|
|
<span class="lineno"> 1121 </span><span class="spaces"> </span><span class="nottickedoff">ctx =</span>
|
|
<span class="lineno"> 1122 </span><span class="spaces"> </span><span class="nottickedoff">translate (-x) (-y) .</span>
|
|
<span class="lineno"> 1123 </span><span class="spaces"> </span><span class="nottickedoff">uncurry translate (camData^.oScaleOrigin) .</span>
|
|
<span class="lineno"> 1124 </span><span class="spaces"> </span><span class="nottickedoff">scale (camData^.oScale) .</span>
|
|
<span class="lineno"> 1125 </span><span class="spaces"> </span><span class="nottickedoff">uncurry translate (camData^.oScaleOrigin & both %~ negate)</span>
|
|
<span class="lineno"> 1126 </span><span class="spaces"> </span><span class="nottickedoff">in (ctx svg, zindex)</span></span>
|
|
<span class="lineno"> 1127 </span>
|
|
<span class="lineno"> 1128 </span>-- |
|
|
<span class="lineno"> 1129 </span>--
|
|
<span class="lineno"> 1130 </span>-- Example
|
|
<span class="lineno"> 1131 </span>--
|
|
<span class="lineno"> 1132 </span>-- > do cam <- newObject Camera
|
|
<span class="lineno"> 1133 </span>-- > circ <- newObject $ Circle 2; oShow circ
|
|
<span class="lineno"> 1134 </span>-- > oModify circ $ oTranslate .~ (-3,0)
|
|
<span class="lineno"> 1135 </span>-- > box <- newObject $ Rectangle 4 4; oShow box
|
|
<span class="lineno"> 1136 </span>-- > oModify box $ oTranslate .~ (3,0)
|
|
<span class="lineno"> 1137 </span>-- > cameraAttach cam circ
|
|
<span class="lineno"> 1138 </span>-- > cameraAttach cam box
|
|
<span class="lineno"> 1139 </span>-- > cameraFocus cam (-3,0)
|
|
<span class="lineno"> 1140 </span>-- > cameraZoom cam 2 2 -- Zoom in
|
|
<span class="lineno"> 1141 </span>-- > cameraZoom cam 2 1 -- Zoom out
|
|
<span class="lineno"> 1142 </span>-- > cameraFocus cam (3,0)
|
|
<span class="lineno"> 1143 </span>-- > cameraZoom cam 2 2 -- Zoom in
|
|
<span class="lineno"> 1144 </span>-- > cameraZoom cam 2 1 -- Zoom out
|
|
<span class="lineno"> 1145 </span>--
|
|
<span class="lineno"> 1146 </span>-- <<docs/gifs/doc_cameraFocus.gif>>
|
|
<span class="lineno"> 1147 </span>cameraFocus :: Object s Camera -> (Double, Double) -> Scene s ()
|
|
<span class="lineno"> 1148 </span><span class="decl"><span class="nottickedoff">cameraFocus cam (x,y) = do</span>
|
|
<span class="lineno"> 1149 </span><span class="spaces"> </span><span class="nottickedoff">(ox, oy) <- oRead cam oScaleOrigin</span>
|
|
<span class="lineno"> 1150 </span><span class="spaces"> </span><span class="nottickedoff">(tx, ty) <- oRead cam oTranslate</span>
|
|
<span class="lineno"> 1151 </span><span class="spaces"> </span><span class="nottickedoff">s <- oRead cam oScale</span>
|
|
<span class="lineno"> 1152 </span><span class="spaces"> </span><span class="nottickedoff">let newLocation = (x-((x-ox)*s+ox-tx), y-((y-oy)*s+oy-ty))</span>
|
|
<span class="lineno"> 1153 </span><span class="spaces"> </span><span class="nottickedoff">oModifyS cam $ do</span>
|
|
<span class="lineno"> 1154 </span><span class="spaces"> </span><span class="nottickedoff">oTranslate .= newLocation</span>
|
|
<span class="lineno"> 1155 </span><span class="spaces"> </span><span class="nottickedoff">oScaleOrigin .= (x,y)</span></span>
|
|
<span class="lineno"> 1156 </span>
|
|
<span class="lineno"> 1157 </span>-- | Instantaneously set camera zoom level.
|
|
<span class="lineno"> 1158 </span>cameraSetZoom :: Object s Camera -> Double -> Scene s ()
|
|
<span class="lineno"> 1159 </span><span class="decl"><span class="nottickedoff">cameraSetZoom cam s =</span>
|
|
<span class="lineno"> 1160 </span><span class="spaces"> </span><span class="nottickedoff">oModifyS cam $</span>
|
|
<span class="lineno"> 1161 </span><span class="spaces"> </span><span class="nottickedoff">oScale .= s</span></span>
|
|
<span class="lineno"> 1162 </span>
|
|
<span class="lineno"> 1163 </span>-- | Change camera zoom level over a set duration.
|
|
<span class="lineno"> 1164 </span>cameraZoom :: Object s Camera -> Duration -> Double -> Scene s ()
|
|
<span class="lineno"> 1165 </span><span class="decl"><span class="nottickedoff">cameraZoom cam d s =</span>
|
|
<span class="lineno"> 1166 </span><span class="spaces"> </span><span class="nottickedoff">oTweenS cam d $ \t -></span>
|
|
<span class="lineno"> 1167 </span><span class="spaces"> </span><span class="nottickedoff">oScale %= \v -> fromToS v s t</span></span>
|
|
<span class="lineno"> 1168 </span>
|
|
<span class="lineno"> 1169 </span>-- | Instantaneously set camera location.
|
|
<span class="lineno"> 1170 </span>cameraSetPan :: Object s Camera -> (Double, Double) -> Scene s ()
|
|
<span class="lineno"> 1171 </span><span class="decl"><span class="nottickedoff">cameraSetPan cam location =</span>
|
|
<span class="lineno"> 1172 </span><span class="spaces"> </span><span class="nottickedoff">oModifyS cam $ do</span>
|
|
<span class="lineno"> 1173 </span><span class="spaces"> </span><span class="nottickedoff">oTranslate .= location</span></span>
|
|
<span class="lineno"> 1174 </span>
|
|
<span class="lineno"> 1175 </span>-- | Change camera location over a set duration.
|
|
<span class="lineno"> 1176 </span>cameraPan :: Object s Camera -> Duration -> (Double, Double) -> Scene s ()
|
|
<span class="lineno"> 1177 </span><span class="decl"><span class="nottickedoff">cameraPan cam d (x,y) =</span>
|
|
<span class="lineno"> 1178 </span><span class="spaces"> </span><span class="nottickedoff">oTweenS cam d $ \t -> do</span>
|
|
<span class="lineno"> 1179 </span><span class="spaces"> </span><span class="nottickedoff">oTranslate._1 %= \v -> fromToS v x t</span>
|
|
<span class="lineno"> 1180 </span><span class="spaces"> </span><span class="nottickedoff">oTranslate._2 %= \v -> fromToS v y t</span></span>
|
|
|
|
</pre>
|
|
</body>
|
|
</html>
|