diff --git a/hpc_index.html b/hpc_index.html index da8b21e..52c496e 100644 --- a/hpc_index.html +++ b/hpc_index.html @@ -104,7 +104,7 @@ table.dashboard { border-collapse: collapse ; border: solid 1px black } 5%1/19
0%0/50
4%39/826
  module reanimate-0.4.1.0-inplace/Reanimate.Scene -30%40/130
60%15/25
36%545/1473
+30%40/130
60%15/25
36%545/1483
  module reanimate-0.4.1.0-inplace/Reanimate.Svg 38%5/13
18%15/80
41%323/777
@@ -128,5 +128,5 @@ table.dashboard { border-collapse: collapse ; border: solid 1px black } 100%6/6
50%1/2
95%43/45
  Program Coverage Total -30%247/803
15%131/833
29%4647/15874
+30%247/803
15%131/833
29%4647/15884
diff --git a/hpc_index_alt.html b/hpc_index_alt.html index 043aa16..11d77a8 100644 --- a/hpc_index_alt.html +++ b/hpc_index_alt.html @@ -14,7 +14,7 @@ table.dashboard { border-collapse: collapse ; border: solid 1px black } 100%14/14
60%3/5
99%1176/1180
  module reanimate-0.4.1.0-inplace/Reanimate.Scene -30%40/130
60%15/25
36%545/1473
+30%40/130
60%15/25
36%545/1483
  module reanimate-0.4.1.0-inplace/Reanimate.Svg.LineCommand 75%12/16
58%43/74
69%659/943
@@ -128,5 +128,5 @@ table.dashboard { border-collapse: collapse ; border: solid 1px black } 15%3/20
- 0/0 14%7/49
  Program Coverage Total -30%247/803
15%131/833
29%4647/15874
+30%247/803
15%131/833
29%4647/15884
diff --git a/hpc_index_exp.html b/hpc_index_exp.html index aaeb97a..608e688 100644 --- a/hpc_index_exp.html +++ b/hpc_index_exp.html @@ -47,7 +47,7 @@ table.dashboard { border-collapse: collapse ; border: solid 1px black } 33%5/15
5%1/20
40%133/325
  module reanimate-0.4.1.0-inplace/Reanimate.Scene -30%40/130
60%15/25
36%545/1473
+30%40/130
60%15/25
36%545/1483
  module reanimate-0.4.1.0-inplace/Reanimate.Builtin.Slide 33%1/3
- 0/0 30%18/60
@@ -128,5 +128,5 @@ table.dashboard { border-collapse: collapse ; border: solid 1px black } 0%0/1
0%0/4
0%0/61
  Program Coverage Total -30%247/803
15%131/833
29%4647/15874
+30%247/803
15%131/833
29%4647/15884
diff --git a/hpc_index_fun.html b/hpc_index_fun.html index d278f25..3b3d720 100644 --- a/hpc_index_fun.html +++ b/hpc_index_fun.html @@ -65,7 +65,7 @@ table.dashboard { border-collapse: collapse ; border: solid 1px black } 33%1/3
0%0/14
21%28/128
  module reanimate-0.4.1.0-inplace/Reanimate.Scene -30%40/130
60%15/25
36%545/1473
+30%40/130
60%15/25
36%545/1483
  module reanimate-0.4.1.0-inplace/Reanimate.Internal.CubicBezier 23%20/86
7%2/26
30%102/337
@@ -128,5 +128,5 @@ table.dashboard { border-collapse: collapse ; border: solid 1px black } 0%0/1
0%0/4
0%0/61
  Program Coverage Total -30%247/803
15%131/833
29%4647/15874
+30%247/803
15%131/833
29%4647/15884
diff --git a/playground/snippets.js b/playground/snippets.js index 02332c5..3cf488a 100644 --- a/playground/snippets.js +++ b/playground/snippets.js @@ -7,5 +7,6 @@ const snippets = [{"title": "Hello World","url": "https://reanimate.clozecards.c ,{"title": "Easing Functions","url": "https://reanimate.clozecards.com/P4F3jzh2Mcj/45.svg","code": "animation :: Animation\nanimation = docEnv $ pauseAtEnd 1 $ sceneAnimation $ do\n showEasing 0 \"curveS\" (curveS 2)\n showEasing 1 \"bellS\" (bellS 2)\n showEasing 2 \"constantS\" (constantS 0.7)\n showEasing 3 \"oscillateS\" oscillateS\n showEasing 4 \"powerS\" (powerS 2)\n showEasing 5 \"reverseS\" reverseS\n showEasing 6 \"id\" id\n\nshowEasing nth txt fn = do\n let yOffset | even nth = 0\n | odd nth = -1\n xOffset = -6 + fromIntegral nth*2\n newSpriteSVG_ $\n \ttranslate xOffset yOffset $\n label txt\n fork $ play $ mapA (translate xOffset 0) $\n mapA (rotate 90) $\n mapA (scale (screenHeight/screenWidth * 0.6)) $\n signalA fn drawProgress\n\nlabel txt =\n translate 0 (-2.5) $\n scale 0.7 $\n center $\n withStrokeWidth 0 $\n withFillOpacity 1 $\n svg\n where\n svg = latex txt\n"} ,{"title": "Easing Graphs","url": "https://reanimate.clozecards.com/FEyCDsj0V82/255.svg","code": "colorPalette = parula -- try: viridis, sinebow, turbo, cividis\nfns =\n [(\"curveS\", curveS 2)\n ,(\"bellS\", bellS 2)\n ,(\"constantS\", constantS 0.7)\n ,(\"oscillateS\", oscillateS)\n ,(\"powerS\", powerS 2)\n ,(\"reverseS\", reverseS)\n ,(\"id\", id)\n ]\n\nanimation :: Animation\nanimation = docEnv $ pauseAtEnd 1 $ sceneAnimation $ do\n newSpriteSVG_ $ mkBackground \"white\"\n play $ signalA (curveS 2) $ animate $ \\t -> partialSvg t grid\n newSpriteSVG_ grid\n wait 1\n flip mapM_ (zip [0..] fns) $ \\(nth, (txt, fn)) -> do\n let color = promotePixel $ colorPalette (nth / fromIntegral (length fns-1))\n showEasing nth txt fn color\n {- showEasing 3 \"oscillateS\" oscillateS\n showEasing 4 \"powerS\" (powerS 2)\n showEasing 5 \"reverseS\" reverseS\n showEasing 6 \"id\" id -}\n\ngridOffset = -2\ngridHeight = 5\ngridWidth = 8\n\ngrid :: SVG\ngrid = translate gridOffset 0 $\n withStrokeWidth defaultStrokeWidth $\n withStrokeColor \"grey\" $ mkGroup\n [ mkPath $ concat\n [[ SVG.MoveTo SVG.OriginAbsolute [V2 (-gridWidth/2) (gridHeight/2-n)]\n ,SVG.HorizontalTo SVG.OriginRelative [gridWidth] ]\n | n <- [1..gridHeight-1]\n ]\n , mkPath \n [ SVG.MoveTo SVG.OriginAbsolute [V2 (-gridWidth/2) (gridHeight/2)]\n , SVG.VerticalTo SVG.OriginRelative [-gridHeight]\n , SVG.HorizontalTo SVG.OriginRelative [gridWidth]\n , SVG.VerticalTo SVG.OriginRelative [gridHeight]\n , SVG.EndPath\n ]\n ]\n\nshowEasing nth txt fn color = do\n let steps = 100\n slope = withStrokeColorPixel color $\n translate gridOffset 0 $ mkLinePath\n [ ((x/steps-0.5)*gridWidth, (y-0.5)*gridHeight)\n | x <- [0..steps]\n , let y = fn (x/steps) ]\n s <- newSpriteSVG $\n withFillColorPixel color $\n translate (gridWidth/2+gridOffset+0.5) (gridHeight/2-nth) $\n label txt\n spriteE s $ overBeginning 0.2 fadeInE\n play $ animate $ \\t -> partialSvg t slope\n newSpriteSVG_ slope\n wait 1\n \nlabel txt = withStrokeColor \"black\" $\n withStrokeWidth (defaultStrokeWidth*2) $\n withFillOpacity 1 $\n latex txt\n"} ,{"title": "Object Positions","url": "https://reanimate.clozecards.com/IAQhjO0Ke7h/195.svg","code": "env =\n addStatic (mkBackground \"white\") .\n mapA (withStrokeColor \"black\")\n\nanimation :: Animation\nanimation = env $\n sceneAnimation $ do\n -- Configure objects\n txt <- newText \"Center\"\n top <- newText \"Top\"\n oModifyS top $ \n oTopY .= screenTop\n topR <- newText \"Top right\"\n oModifyS topR $ do\n oTopY .= screenTop\n oRightX .= screenRight\n botR <- newText \"Bottom right\"\n oModifyS botR $ do\n oBottomY .= screenBottom\n oRightX .= screenRight\n botL <- newText \"Bottom left\"\n oModifyS botL $ do\n oBottomY .= screenBottom\n oLeftX .= screenLeft\n topL <- newText \"Top left\"\n oModifyS topL $ do\n oTopY .= screenTop\n oLeftX .= screenLeft\n -- Show objects\n oShow txt\n wait 1\n switchTo txt top\n switchTo top topR\n switchTo topR botR\n switchTo botR botL\n switchTo botL topL\n switchTo topL txt\n\nswitchTo src dst = do\n fork $ oFadeOut src 1\n oModify dst $ oOpacity .~ 1\n oFadeIn dst 1\n wait 1\n\nnewText txt =\n newObject $ scale 1.5 $ center $ latex txt\n"} + ,{"title": "Camera","url": "https://reanimate.clozecards.com/M0zmmcMpBkj/150.svg","code": "animation :: Animation\nanimation = docEnv $ mapA (withFillOpacity 1) $ sceneAnimation $ do\n cam <- newObject Camera\n\n txt <- newObject $ center $ latex \"Fixed (non-cam)\"\n oModifyS txt $ do\n oTopY .= screenTop \n oZIndex .= 2\n\n circle <- newObject $ Circle 1\n cameraAttach cam circle\n oModify circle $ oContext .~ withFillColor \"blue\"\n circleRight <- oRead circle oRightX\n\n box <- newObject $ Rectangle 2 2\n cameraAttach cam box\n oModify box $ oContext .~ withFillColor \"green\"\n oModify box $ oLeftX .~ circleRight\n boxCenter <- oRead box oCenterXY\n\n small <- newObject $ center $ latex \"This text is very small\"\n cameraAttach cam small\n oModifyS small $ do\n oCenterXY .= boxCenter\n oScale .= 0.1\n \n oShow txt\n oShow small\n oShow circle\n oShow box\n\n wait 1\n\n cameraFocus cam boxCenter\n waitOn $ do\n fork $ cameraPan cam 3 boxCenter\n fork $ cameraZoom cam 3 15\n \n wait 2\n waitOn $ do\n fork $ cameraZoom cam 3 1\n waitOn $ do\n fork $ cameraPan cam 1 (0,0)\n"} ]; -const playgroundVersion = "2020-08-25 (fd9fc)"; +const playgroundVersion = "2020-08-25 (48b2a)"; diff --git a/reanimate-0.4.1.0-inplace/Reanimate.Scene.hs.html b/reanimate-0.4.1.0-inplace/Reanimate.Scene.hs.html index 96abedf..7098490 100644 --- a/reanimate-0.4.1.0-inplace/Reanimate.Scene.hs.html +++ b/reanimate-0.4.1.0-inplace/Reanimate.Scene.hs.html @@ -979,164 +979,167 @@ span.spaces { background: white } 960 withGroupOpacity _oOpacity $ 961 _oContext _oSVG 962 else None - 963 return Object - 964 { objectSprite = sprite - 965 , objectData = ref } - 966 where - 967 svg = toSVG val - 968 - 969 ------------------------------------------------------------------------------- - 970 -- Graphical transformations + 963 spriteModify sprite $ do + 964 ~ObjectData{_oZIndex=z} <- unVar ref + 965 pure $ \(img,_) -> (img,z) + 966 return Object + 967 { objectSprite = sprite + 968 , objectData = ref } + 969 where + 970 svg = toSVG val 971 - 972 -- | Instantly show object. - 973 oShow :: Object s a -> Scene s () - 974 oShow o = oModify o $ oShown .~ True - 975 - 976 -- | Instantly hide object. - 977 oHide :: Object s a -> Scene s () - 978 oHide o = oModify o $ oShown .~ False - 979 - 980 -- | Fade in object over a set duration. - 981 oFadeIn :: Object s a -> Duration -> Scene s () - 982 oFadeIn o d = do - 983 oModify o $ - 984 oShown .~ True - 985 oTweenS o d $ \t -> - 986 oOpacity *= t - 987 - 988 -- | Fade out object over a set duration. - 989 oFadeOut :: Object s a -> Duration -> Scene s () - 990 oFadeOut o d = do - 991 oModify o $ - 992 oShown .~ True - 993 oTweenS o d $ \t -> - 994 oOpacity *= 1-t - 995 - 996 -- | Scale in object over a set duration. - 997 oGrow :: Object s a -> Duration -> Scene s () - 998 oGrow o d = do - 999 oModify o $ - 1000 oShown .~ True - 1001 oTweenS o d $ \t -> - 1002 oScale *= t - 1003 - 1004 -- | Scale out object over a set duration. - 1005 oShrink :: Object s a -> Duration -> Scene s () - 1006 oShrink o d = - 1007 oTweenS o d $ \t -> - 1008 oScale *= 1-t - 1009 - 1010 -- FIXME: Also transform attributes: 'opacity', 'scale', 'scaleOrigin'. - 1011 -- | Morph source object into target object over a set duration. - 1012 oTransform :: Object s a -> Object s b -> Duration -> Scene s () - 1013 oTransform src dst d = do - 1014 srcSvg <- oRead src oSVG - 1015 srcCtx <- oRead src oContext - 1016 srcEase <- oRead src oEasing - 1017 srcLoc <- oRead src oTranslate - 1018 oModify src $ oShown .~ False - 1019 - 1020 dstSvg <- oRead dst oSVG - 1021 dstCtx <- oRead dst oContext - 1022 dstLoc <- oRead dst oTranslate - 1023 - 1024 m <- newObject $ Morph 0 (srcCtx srcSvg) (dstCtx dstSvg) - 1025 oModifyS m $ do - 1026 oShown .= True - 1027 oEasing .= srcEase - 1028 oTranslate .= srcLoc - 1029 fork $ oTween m d $ \t -> oTranslate %~ moveTo t dstLoc - 1030 oTweenV m d $ \t -> morphDelta .~ t - 1031 oModify m $ oShown .~ False - 1032 oModify dst $ oShown .~ True - 1033 where - 1034 moveTo t (dstX, dstY) (srcX, srcY) = - 1035 (fromToS srcX dstX t, fromToS srcY dstY t) - 1036 - 1037 - 1038 ------------------------------------------------------------------------------- - 1039 -- Built-in objects + 972 ------------------------------------------------------------------------------- + 973 -- Graphical transformations + 974 + 975 -- | Instantly show object. + 976 oShow :: Object s a -> Scene s () + 977 oShow o = oModify o $ oShown .~ True + 978 + 979 -- | Instantly hide object. + 980 oHide :: Object s a -> Scene s () + 981 oHide o = oModify o $ oShown .~ False + 982 + 983 -- | Fade in object over a set duration. + 984 oFadeIn :: Object s a -> Duration -> Scene s () + 985 oFadeIn o d = do + 986 oModify o $ + 987 oShown .~ True + 988 oTweenS o d $ \t -> + 989 oOpacity *= t + 990 + 991 -- | Fade out object over a set duration. + 992 oFadeOut :: Object s a -> Duration -> Scene s () + 993 oFadeOut o d = do + 994 oModify o $ + 995 oShown .~ True + 996 oTweenS o d $ \t -> + 997 oOpacity *= 1-t + 998 + 999 -- | Scale in object over a set duration. + 1000 oGrow :: Object s a -> Duration -> Scene s () + 1001 oGrow o d = do + 1002 oModify o $ + 1003 oShown .~ True + 1004 oTweenS o d $ \t -> + 1005 oScale *= t + 1006 + 1007 -- | Scale out object over a set duration. + 1008 oShrink :: Object s a -> Duration -> Scene s () + 1009 oShrink o d = + 1010 oTweenS o d $ \t -> + 1011 oScale *= 1-t + 1012 + 1013 -- FIXME: Also transform attributes: 'opacity', 'scale', 'scaleOrigin'. + 1014 -- | Morph source object into target object over a set duration. + 1015 oTransform :: Object s a -> Object s b -> Duration -> Scene s () + 1016 oTransform src dst d = do + 1017 srcSvg <- oRead src oSVG + 1018 srcCtx <- oRead src oContext + 1019 srcEase <- oRead src oEasing + 1020 srcLoc <- oRead src oTranslate + 1021 oModify src $ oShown .~ False + 1022 + 1023 dstSvg <- oRead dst oSVG + 1024 dstCtx <- oRead dst oContext + 1025 dstLoc <- oRead dst oTranslate + 1026 + 1027 m <- newObject $ Morph 0 (srcCtx srcSvg) (dstCtx dstSvg) + 1028 oModifyS m $ do + 1029 oShown .= True + 1030 oEasing .= srcEase + 1031 oTranslate .= srcLoc + 1032 fork $ oTween m d $ \t -> oTranslate %~ moveTo t dstLoc + 1033 oTweenV m d $ \t -> morphDelta .~ t + 1034 oModify m $ oShown .~ False + 1035 oModify dst $ oShown .~ True + 1036 where + 1037 moveTo t (dstX, dstY) (srcX, srcY) = + 1038 (fromToS srcX dstX t, fromToS srcY dstY t) + 1039 1040 - 1041 newtype Circle = Circle {_circleRadius :: Double} - 1042 - 1043 circleRadius :: Iso' Circle Double - 1044 circleRadius = iso _circleRadius Circle + 1041 ------------------------------------------------------------------------------- + 1042 -- Built-in objects + 1043 + 1044 newtype Circle = Circle {_circleRadius :: Double} 1045 - 1046 instance Renderable Circle where - 1047 toSVG (Circle r) = mkCircle r + 1046 circleRadius :: Iso' Circle Double + 1047 circleRadius = iso _circleRadius Circle 1048 - 1049 data Rectangle = Rectangle { _rectWidth :: Double, _rectHeight :: Double } - 1050 - 1051 rectWidth :: Lens' Rectangle Double - 1052 rectWidth = lens _rectWidth $ \obj val -> obj{_rectWidth=val} + 1049 instance Renderable Circle where + 1050 toSVG (Circle r) = mkCircle r + 1051 + 1052 data Rectangle = Rectangle { _rectWidth :: Double, _rectHeight :: Double } 1053 - 1054 rectHeight :: Lens' Rectangle Double - 1055 rectHeight = lens _rectHeight $ \obj val -> obj{_rectHeight=val} + 1054 rectWidth :: Lens' Rectangle Double + 1055 rectWidth = lens _rectWidth $ \obj val -> obj{_rectWidth=val} 1056 - 1057 instance Renderable Rectangle where - 1058 toSVG (Rectangle w h) = mkRect w h + 1057 rectHeight :: Lens' Rectangle Double + 1058 rectHeight = lens _rectHeight $ \obj val -> obj{_rectHeight=val} 1059 - 1060 data Morph = Morph { _morphDelta :: Double, _morphSrc :: SVG, _morphDst :: SVG } - 1061 - 1062 morphDelta :: Lens' Morph Double - 1063 morphDelta = lens _morphDelta $ \obj val -> obj{_morphDelta = val} + 1060 instance Renderable Rectangle where + 1061 toSVG (Rectangle w h) = mkRect w h + 1062 + 1063 data Morph = Morph { _morphDelta :: Double, _morphSrc :: SVG, _morphDst :: SVG } 1064 - 1065 morphSrc :: Lens' Morph SVG - 1066 morphSrc = lens _morphSrc $ \obj val -> obj{_morphSrc = val} + 1065 morphDelta :: Lens' Morph Double + 1066 morphDelta = lens _morphDelta $ \obj val -> obj{_morphDelta = val} 1067 - 1068 morphDst :: Lens' Morph SVG - 1069 morphDst = lens _morphDst $ \obj val -> obj{_morphDst = val} + 1068 morphSrc :: Lens' Morph SVG + 1069 morphSrc = lens _morphSrc $ \obj val -> obj{_morphSrc = val} 1070 - 1071 instance Renderable Morph where - 1072 toSVG (Morph t src dst) = morph linear src dst t + 1071 morphDst :: Lens' Morph SVG + 1072 morphDst = lens _morphDst $ \obj val -> obj{_morphDst = val} 1073 - 1074 data Camera = Camera - 1075 instance Renderable Camera where - 1076 toSVG Camera = None - 1077 - 1078 cameraAttach :: Object s Camera -> Object s a -> Scene s () - 1079 cameraAttach cam obj = - 1080 spriteModify (objectSprite obj) $ do - 1081 camData <- unVar (objectData cam) - 1082 return $ \(svg,zindex) -> - 1083 let (x,y) = camData^.oTranslate - 1084 ctx = - 1085 translate (-x) (-y) . - 1086 uncurry translate (camData^.oScaleOrigin) . - 1087 scale (camData^.oScale) . - 1088 uncurry translate (camData^.oScaleOrigin & both %~ negate) - 1089 in (ctx svg, zindex) - 1090 - 1091 cameraFocus :: Object s Camera -> (Double, Double) -> Scene s () - 1092 cameraFocus cam (x,y) = do - 1093 (ox, oy) <- oRead cam oScaleOrigin - 1094 (tx, ty) <- oRead cam oTranslate - 1095 s <- oRead cam oScale - 1096 let newLocation = (x-((x-ox)*s+ox-tx), y-((y-oy)*s+oy-ty)) - 1097 oModifyS cam $ do - 1098 oTranslate .= newLocation - 1099 oScaleOrigin .= (x,y) - 1100 - 1101 cameraSetZoom :: Object s Camera -> Double -> Scene s () - 1102 cameraSetZoom cam s = - 1103 oModifyS cam $ - 1104 oScale .= s - 1105 - 1106 cameraZoom :: Object s Camera -> Duration -> Double -> Scene s () - 1107 cameraZoom cam d s = - 1108 oTweenS cam d $ \t -> - 1109 oScale %= \v -> fromToS v s t - 1110 - 1111 cameraSetPan :: Object s Camera -> (Double, Double) -> Scene s () - 1112 cameraSetPan cam location = - 1113 oModifyS cam $ do - 1114 oTranslate .= location - 1115 - 1116 cameraPan :: Object s Camera -> Duration -> (Double, Double) -> Scene s () - 1117 cameraPan cam d (x,y) = - 1118 oTweenS cam d $ \t -> do - 1119 oTranslate._1 %= \v -> fromToS v x t - 1120 oTranslate._2 %= \v -> fromToS v y t + 1074 instance Renderable Morph where + 1075 toSVG (Morph t src dst) = morph linear src dst t + 1076 + 1077 data Camera = Camera + 1078 instance Renderable Camera where + 1079 toSVG Camera = None + 1080 + 1081 cameraAttach :: Object s Camera -> Object s a -> Scene s () + 1082 cameraAttach cam obj = + 1083 spriteModify (objectSprite obj) $ do + 1084 camData <- unVar (objectData cam) + 1085 return $ \(svg,zindex) -> + 1086 let (x,y) = camData^.oTranslate + 1087 ctx = + 1088 translate (-x) (-y) . + 1089 uncurry translate (camData^.oScaleOrigin) . + 1090 scale (camData^.oScale) . + 1091 uncurry translate (camData^.oScaleOrigin & both %~ negate) + 1092 in (ctx svg, zindex) + 1093 + 1094 cameraFocus :: Object s Camera -> (Double, Double) -> Scene s () + 1095 cameraFocus cam (x,y) = do + 1096 (ox, oy) <- oRead cam oScaleOrigin + 1097 (tx, ty) <- oRead cam oTranslate + 1098 s <- oRead cam oScale + 1099 let newLocation = (x-((x-ox)*s+ox-tx), y-((y-oy)*s+oy-ty)) + 1100 oModifyS cam $ do + 1101 oTranslate .= newLocation + 1102 oScaleOrigin .= (x,y) + 1103 + 1104 cameraSetZoom :: Object s Camera -> Double -> Scene s () + 1105 cameraSetZoom cam s = + 1106 oModifyS cam $ + 1107 oScale .= s + 1108 + 1109 cameraZoom :: Object s Camera -> Duration -> Double -> Scene s () + 1110 cameraZoom cam d s = + 1111 oTweenS cam d $ \t -> + 1112 oScale %= \v -> fromToS v s t + 1113 + 1114 cameraSetPan :: Object s Camera -> (Double, Double) -> Scene s () + 1115 cameraSetPan cam location = + 1116 oModifyS cam $ do + 1117 oTranslate .= location + 1118 + 1119 cameraPan :: Object s Camera -> Duration -> (Double, Double) -> Scene s () + 1120 cameraPan cam d (x,y) = + 1121 oTweenS cam d $ \t -> do + 1122 oTranslate._1 %= \v -> fromToS v x t + 1123 oTranslate._2 %= \v -> fromToS v y t