{-# LANGUAGE OverloadedStrings #-} import Control.Concurrent import Graphics.GL import Linear import System.Random import Data.Time import Control.Monad import Control.Monad.State import Data.Bits import Text.Show.Pretty import Data.Maybe import Halive.Utils import Cube import Shader import Window import SDL hiding (get) import qualified SDL as SDL import qualified Green as Green -- Try changing the green amount -- while the program is running main :: IO () main = do putStrLn "MAIN BEGIN" -- error "DANG!" -- It's ok if your program crashes, it shouldn't crash Halive -- Wrap any persistent state in 'reacquire' plus a unique asset ID. -- Reacquire uses foreign-store to only run your setup function once, -- and then return it again on subsequent recompilations. -- In this case, GLFW doesn't like being initialized more than once -- per process, so this solves the problem handily. -- (Our window stays persistent as well thanks to this, -- so it would probably be a good idea anyway!) (win, _ctx) <- reacquire "win" $ createGLWindow "Hot SDL" -- You can change the window title here. --GLFW.setWindowTitle win "Hot Swap!" -- Changing the shaders' contents will trigger Halive as well! program <- createShaderProgram "demo/cube.vert" "demo/cube.frag" cube <- makeCube program -- Any GL state will stick around, so be aware of that. glEnable GL_DEPTH_TEST -- Sometimes it's useful to know if we're running under Halive or not putStrLn . ("Running under Halive: " ++ ) . show =<< isHaliveActive -- Reacquire our state from the last run, if any - otherwise create a new state initialState <- reacquire "state" (return ([]::[V3 GLfloat])) void . flip runStateT initialState . whileWindow win $ \events -> do -- Store our state persistently in a named slot persistState "state" -- Try turning on a stream of events -- unless (null events) $ -- liftIO $ pPrint events winSize@(V2 w h) <- fmap realToFrac <$> SDL.get (SDL.windowSize win) now <- realToFrac . utctDayTime <$> liftIO getCurrentTime -- print now -- Try turning on a stream of now logs let redFreq = 0.6 * pi -- Try changing the red and blue frequencies. red = sin (now * redFreq) blueFreq = 0.5 * pi blue = sin (now * blueFreq) --putStrLn "glClearColor" glClearColor red 0.3 blue 1 --putStrLn "glClear" glClear (GL_COLOR_BUFFER_BIT .|. GL_DEPTH_BUFFER_BIT) -- Render our scene --putStrLn "getWinSize" let projection = perspective 45 (w / h) 0.01 1000 model = mkTransformation (axisAngle (V3 0 1 1) now) (V3 (sin now) 0 (-4)) view = lookAt (V3 0 2 5) (V3 0 0 (-4)) (V3 0 1 0) projView = projection !*! view mvp = projView !*! model --putStrLn "renderCube" renderCube cube mvp -- Accumulate mouse drags as cube trails forM_ (catMaybes $ map matchMouse events) $ \cursorPos -> do isMouseDown <- SDL.getMouseButtons when (isMouseDown ButtonLeft) $ do let worldPos = windowPosToWorldPos winSize projView cursorPos 20 modify' ((worldPos :) . take 40) positions <- get forM_ positions $ \cursorPos -> do let model = mkTransformation (axisAngle (V3 0 1 1) now) cursorPos mvp = projView !*! model renderCube cube mvp --putStrLn "glSwapWindow" SDL.glSwapWindow win matchMouse Event { eventPayload = MouseMotionEvent MouseMotionEventData { mouseMotionEventWhich = Mouse 0 , mouseMotionEventPos = P pos } } = Just (fromIntegral <$> pos) matchMouse _ = Nothing