Download presentation
Presentation is loading. Please wait.
1
Chapter 17 Rendering Reactive Animations
2
Motivation In the previous chapter we learned just enough about advanced IO and concurrency to develop a “renderer” for FAL. That renderer is called “reactimate”, and has type: reactimate :: String -> Behavior a -> (a -> IO Graphic) -> IO () But first, we need a way to extract an infinite stream of time-stamped user actions from the operating system. We want the values in the stream to be: “Just ua” if there is a user action “ua” present at the time we ask for it, and “Nothing” if there is not.
3
windowUser The stream of user actions will be supplied by: windowUser :: Window -> IO (([Maybe UserAction],[Time]), IO ()) Executing the command: ((us,ts), addEvents) <- windowUser w yields a user action stream “us” and a time stream “ts”. also yields an IO action “addEvents” that causes the OS to update “us” with whatever user actions happen to be pending at that time, followed by a “Nothing”. Note: “addEvents” is an IO action – it does nothing until executed. “reactimate” will call windowUser, process all user actions in “us” until it sees “Nothing”, then execute “addEvents”, and repeat.
4
Using First-Class Channels “windowUser” will use first-class channels. As a helper function, we define: makeStream :: IO ([a], a -> IO ()) makeStream = do ch <- newChan contents <- getChanContents ch return (contents, writeChan ch) “makeStream” creates a new channel, converts its contents into a stream using “getChannelContents”, and returns that stream along with a function to write into the channel.
5
Definition of windowUser windowUser :: Window -> IO (([Maybe UserAction],[Time]), IO ()) windowUser w = do (evs, addEv) return () Just e -> do addEv (Just e, rt) loop rt let addEvents = do t <- timeGetTime let rt = w32ToTime (t-t0) loop rt addEv (Nothing, rt) return ((map fst evs, map snd evs), addEvents) w32ToTime t = intToFloat (word32ToInt t) / 1000
6
Turning Nothing into Something Recall that the non-occurrence of an event corresponds to a time when we wish to sample the picture. So we need to convert non-occurrences into occurrences: sample :: Event () sample = Event (\(us,_) -> map aux us) where aux Nothing= Just () aux (Just _)= Nothing Then, for a given FAL program “franProg”, we can describe the individual picture values that we want as an event stream: sample `snapshot_` franProg :: Event Picture This leads finally to the definition of “reactimate”.
7
Reactimate reactimate :: String -> Behavior a -> (a -> IO Graphic) -> IO () reactimate title franProg toGraphic = runGraphics $ do w <- openWindowEx title (Just (0,0)) (Just (xWin,yWin)) drawBufferedGraphic (Just 30) (user, addEvents) <- windowUser w addEvents let drawPic (Just p) = do g <- toGraphic p setGraphic w g addEvents getWindowTick w drawPic Nothing = return () mapM_ drawPic (runEvent (sample `snapshot_` franProg) user) runEvent (Event fe) u = fe u
Similar presentations
© 2025 SlidePlayer.com. Inc.
All rights reserved.