
Dear All, I'm trying to get my hands wet with the reactive library, but already the simplest example I cooked up is failing to work properly (and leaks memory, and uses relatively lots of cpu time). The problem appears when I try to merge my two events with `mappend`. One event should exit on pressing ESC, the other draws colored circles on pressing the left mouse button. They work correctly separately. Could somebody explain me what's happening, or whether I'm making a basic mistake? The code is below, I hope the formatting survives the various email systems. I don't know if that matters or not, but I'm using OS X. Thanks, Balazs module Main where
import Control.Monad import Data.Monoid
import FRP.Reactive import FRP.Reactive.GLUT.Adapter
import Graphics.Rendering.OpenGL hiding (normalize) import Graphics.UI.GLUT hiding (normalize,Char)
import System.Exit
-------------------------------------------------------
nop :: Monad m => m () nop = return ()
data Vec2 = Vec2 !Float !Float
(&+) (Vec2 x1 y1) (Vec2 x2 y2) = Vec2 (x1+x2) (y1+y2)
sinCosRadius a r = Vec2 (r * cos a) (r * sin a)
instance Vertex Vec2 where vertex (Vec2 x y) = vertex (Vertex2 x y)
-------------------------------------------------------
display :: Action -> Action display action = do clear [ ColorBuffer , DepthBuffer ]
siz@(Size xs ys) <- get windowSize matrixMode $= Projection loadIdentity let q = fromIntegral xs / fromIntegral ys r = 1 / q if q >= 1 then ortho 0 1 r 0 (-1) 1 else ortho 0 q 1 0 (-1) 1 viewport $= ( Position 0 0 , siz ) matrixMode $= Modelview 0 loadIdentity
action postRedisplay Nothing swapBuffers
data Col = RR | GG | BB
nextCol RR = GG nextCol GG = BB nextCol BB = RR
setCol RR = color (Color3 1 0 (0::Float)) setCol GG = color (Color3 0 1 (0::Float)) setCol BB = color (Color3 0 0 (1::Float))
drawWithCol col = do setCol col let center = Vec2 0.25 0.25 radius = 0.1 n = 32 renderPrimitive TriangleFan $ do vertex center let phi j = 2*pi * fromIntegral j / fromIntegral n forM_ [0..n] $ \i -> vertex (center &+ sinCosRadius (phi i) radius)
myUI :: UI -> Behaviour Action myUI ui = uiB where
mp = mousePosition ui lb = leftButtonPressed ui rb = leftButtonPressed ui ky = keyPressed ui
colE = mealy_ RR nextCol lb drawE = fmap drawWithCol colE
exitE = justE (fmap esc ky) where esc k = case k of Char '\ESC' -> Just exitSuccess _ -> Nothing
uiE = fmap display drawE `mappend` exitE uiB = stepper nop uiE
-------------------------------------------------------
main = do initialize "alma" [] initialWindowSize $= Size 512 384 initialDisplayMode $= [ RGBAMode , WithDepthBuffer , DoubleBuffered ] createWindow "reactive test" adapt myUI