{-# language BlockArguments #-} {-# language LambdaCase #-} {-# language OverloadedStrings #-} -- | Port of [example_sdl2_sdlrenderer2](https://github.com/ocornut/imgui/blob/54c1bdecebf3c9bb9259c07c5f5666bb4bd5c3ea/examples/example_sdl2_sdlrenderer2/main.cpp). -- -- Minor differences: -- - No changing of the clear color via @ImGui::ColorEdit3@ as a Haskell binding -- doesn't yet exist for this function. -- - No high DPI renderer scaling as this seems to be in flux [upstream](https://github.com/ocornut/imgui/issues/6065) module Main ( main ) where import Control.Exception (bracket, bracket_) import Control.Monad.IO.Class (MonadIO(liftIO)) import Control.Monad.Managed (managed, managed_, runManaged) import Data.IORef (IORef, newIORef) import Data.Text (pack) import DearImGui import DearImGui.SDL (pollEventWithImGui, sdl2NewFrame, sdl2Shutdown) import DearImGui.SDL.Renderer ( sdl2InitForSDLRenderer, sdlRendererInit, sdlRendererNewFrame, sdlRendererRenderDrawData , sdlRendererShutdown ) import SDL (V4(V4), ($=), ($~), get) import Text.Printf (printf) import qualified SDL main :: IO () main = do -- Initialize SDL2 SDL.initializeAll runManaged do -- Create a window using SDL2 window <- do let title = "ImGui + SDL2 Renderer" let config = SDL.defaultWindow { SDL.windowInitialSize = SDL.V2 1280 720 , SDL.windowResizable = True , SDL.windowPosition = SDL.Centered } managed $ bracket (SDL.createWindow title config) SDL.destroyWindow -- Create an SDL2 renderer renderer <- managed do bracket (SDL.createRenderer window (-1) SDL.defaultRenderer) SDL.destroyRenderer -- Create an ImGui context _ <- managed $ bracket createContext destroyContext -- Initialize ImGui's SDL2 backend _ <- managed_ do bracket_ (sdl2InitForSDLRenderer window renderer) sdl2Shutdown -- Initialize ImGui's SDL2 renderer backend _ <- managed_ $ bracket_ (sdlRendererInit renderer) sdlRendererShutdown liftIO $ mainLoop renderer mainLoop :: SDL.Renderer -> IO () mainLoop renderer = do refs <- newRefs go refs where go refs = unlessQuit do -- Tell ImGui we're starting a new frame sdlRendererNewFrame sdl2NewFrame newFrame -- Show the ImGui demo window get (refsShowDemoWindow refs) >>= \case False -> pure () True -> showDemoWindow withWindowOpen "Hello, world!" do text "This is some useful text." _ <- checkbox "Demo Window" $ refsShowDemoWindow refs _ <- checkbox "Another Window" $ refsShowAnotherWindow refs _ <- sliderFloat "float" (refsFloat refs) 0 1 button "Button" >>= \case False -> pure () True -> refsCounter refs $~ succ sameLine counter <- get $ refsCounter refs text $ "counter = " <> pack (show counter) fr <- framerate text $ pack $ printf "Application average %.3f ms/frame (%.1f FPS)" (1000 / fr) fr get (refsShowAnotherWindow refs) >>= \case False -> pure () True -> withCloseableWindow "Another Window" (refsShowAnotherWindow refs) do text "Hello from another window!" button "Close Me" >>= \case False -> pure () True -> refsShowAnotherWindow refs $= False -- Render SDL.rendererDrawColor renderer $= V4 0 0 0 255 SDL.clear renderer render sdlRendererRenderDrawData renderer =<< getDrawData SDL.present renderer go refs -- Process the event loop unlessQuit action = do shouldQuit <- checkEvents if shouldQuit then pure () else action checkEvents = do pollEventWithImGui >>= \case Nothing -> return False Just event -> (isQuit event ||) <$> checkEvents isQuit event = SDL.eventPayload event == SDL.QuitEvent data Refs = Refs { refsShowDemoWindow :: IORef Bool , refsShowAnotherWindow :: IORef Bool , refsFloat :: IORef Float , refsCounter :: IORef Int } newRefs :: IO Refs newRefs = Refs <$> newIORef True <*> newIORef False <*> newIORef 0 <*> newIORef 0