packages feed

dear-imgui 1.2.0 → 1.2.1

raw patch · 13 files changed

+1351/−40 lines, 13 filesdep ~vectorPVP ok

version bump matches the API change (PVP)

Dependency ranges changed: vector

API changes (from Hackage documentation)

+ DearImGui: ClipRange :: a -> a -> ClipRange a
+ DearImGui: class ClipItems t a
+ DearImGui: clipItems :: ClipItems t a => Int -> Int -> t a -> t a
+ DearImGui: data ClipRange a
+ DearImGui: data ImDrawList
+ DearImGui: data ImGuiListClipper
+ DearImGui: getBackgroundDrawList :: MonadIO m => m DrawList
+ DearImGui: getForegroundDrawList :: MonadIO m => m DrawList
+ DearImGui: getWindowDrawList :: MonadIO m => m DrawList
+ DearImGui: imCol32 :: CUChar -> CUChar -> CUChar -> CUChar -> ImU32
+ DearImGui: instance (GHC.Classes.Ord a, GHC.Enum.Enum a, GHC.Num.Num a) => DearImGui.ClipItems DearImGui.ClipRange a
+ DearImGui: instance Data.Vector.Unboxed.Base.Unbox a => DearImGui.ClipItems Data.Vector.Unboxed.Base.Vector a
+ DearImGui: instance DearImGui.ClipItems Data.Vector.Vector a
+ DearImGui: instance DearImGui.ClipItems [] a
+ DearImGui: instance Foreign.Storable.Storable a => DearImGui.ClipItems Data.Vector.Storable.Vector a
+ DearImGui: instance GHC.Classes.Eq a => GHC.Classes.Eq (DearImGui.ClipRange a)
+ DearImGui: instance GHC.Classes.Ord a => GHC.Classes.Ord (DearImGui.ClipRange a)
+ DearImGui: instance GHC.Show.Show a => GHC.Show.Show (DearImGui.ClipRange a)
+ DearImGui: itemCount :: ClipItems t a => t a -> Maybe Int
+ DearImGui: stepItems :: (ClipItems t a, Monad m) => (a -> m ()) -> t a -> m ()
+ DearImGui: type ImU32 = Word32
+ DearImGui: withListClipper :: (ClipItems t a, MonadUnliftIO m) => Maybe Float -> t a -> (a -> m ()) -> m ()
+ DearImGui.Raw: data ImDrawList
+ DearImGui.Raw: data ImGuiListClipper
+ DearImGui.Raw: getBackgroundDrawList :: MonadIO m => m DrawList
+ DearImGui.Raw: getCursorScreenPos :: MonadIO m => m ImVec2
+ DearImGui.Raw: getForegroundDrawList :: MonadIO m => m DrawList
+ DearImGui.Raw: getWindowDrawList :: MonadIO m => m DrawList
+ DearImGui.Raw: imCol32 :: CUChar -> CUChar -> CUChar -> CUChar -> ImU32
+ DearImGui.Raw: type ImU32 = Word32
+ DearImGui.Raw.DrawList: DrawList :: Ptr ImDrawList -> DrawList
+ DearImGui.Raw.DrawList: addBezierCubic :: MonadIO m => DrawList -> Ptr ImVec2 -> Ptr ImVec2 -> Ptr ImVec2 -> Ptr ImVec2 -> ImU32 -> CFloat -> CInt -> m ()
+ DearImGui.Raw.DrawList: addBezierQuadratic :: MonadIO m => DrawList -> Ptr ImVec2 -> Ptr ImVec2 -> Ptr ImVec2 -> ImU32 -> CFloat -> CInt -> m ()
+ DearImGui.Raw.DrawList: addCircle :: MonadIO m => DrawList -> Ptr ImVec2 -> CFloat -> ImU32 -> CInt -> CFloat -> m ()
+ DearImGui.Raw.DrawList: addCircleFilled :: MonadIO m => DrawList -> Ptr ImVec2 -> CFloat -> ImU32 -> CInt -> m ()
+ DearImGui.Raw.DrawList: addConvexPolyFilled :: MonadIO m => DrawList -> Ptr ImVec2 -> CInt -> ImU32 -> m ()
+ DearImGui.Raw.DrawList: addDrawCmd :: MonadIO m => DrawList -> m ()
+ DearImGui.Raw.DrawList: addImage :: MonadIO m => DrawList -> Ptr () -> Ptr ImVec2 -> Ptr ImVec2 -> Ptr ImVec2 -> Ptr ImVec2 -> ImU32 -> m ()
+ DearImGui.Raw.DrawList: addImageQuad :: MonadIO m => DrawList -> Ptr () -> Ptr ImVec2 -> Ptr ImVec2 -> Ptr ImVec2 -> Ptr ImVec2 -> Ptr ImVec2 -> Ptr ImVec2 -> Ptr ImVec2 -> Ptr ImVec2 -> ImU32 -> m ()
+ DearImGui.Raw.DrawList: addImageRounded :: MonadIO m => DrawList -> Ptr () -> Ptr ImVec2 -> Ptr ImVec2 -> Ptr ImVec2 -> Ptr ImVec2 -> ImU32 -> CFloat -> ImDrawFlags -> m ()
+ DearImGui.Raw.DrawList: addLine :: MonadIO m => DrawList -> Ptr ImVec2 -> Ptr ImVec2 -> ImU32 -> CFloat -> m ()
+ DearImGui.Raw.DrawList: addNgon :: MonadIO m => DrawList -> Ptr ImVec2 -> CFloat -> ImU32 -> CInt -> CFloat -> m ()
+ DearImGui.Raw.DrawList: addNgonFilled :: MonadIO m => DrawList -> Ptr ImVec2 -> CFloat -> ImU32 -> CInt -> m ()
+ DearImGui.Raw.DrawList: addPolyLine :: MonadIO m => DrawList -> Ptr ImVec2 -> CInt -> ImU32 -> ImDrawFlags -> CFloat -> m ()
+ DearImGui.Raw.DrawList: addQuad :: MonadIO m => DrawList -> Ptr ImVec2 -> Ptr ImVec2 -> Ptr ImVec2 -> Ptr ImVec2 -> ImU32 -> CFloat -> m ()
+ DearImGui.Raw.DrawList: addQuadFilled :: MonadIO m => DrawList -> Ptr ImVec2 -> Ptr ImVec2 -> Ptr ImVec2 -> Ptr ImVec2 -> ImU32 -> m ()
+ DearImGui.Raw.DrawList: addRect :: MonadIO m => DrawList -> Ptr ImVec2 -> Ptr ImVec2 -> ImU32 -> CFloat -> ImDrawFlags -> CFloat -> m ()
+ DearImGui.Raw.DrawList: addRectFilled :: MonadIO m => DrawList -> Ptr ImVec2 -> Ptr ImVec2 -> ImU32 -> CFloat -> ImDrawFlags -> m ()
+ DearImGui.Raw.DrawList: addRectFilledMultiColor :: MonadIO m => DrawList -> Ptr ImVec2 -> Ptr ImVec2 -> ImU32 -> ImU32 -> ImU32 -> ImU32 -> m ()
+ DearImGui.Raw.DrawList: addText :: MonadIO m => DrawList -> Ptr ImFont -> CFloat -> Ptr ImVec2 -> ImU32 -> CString -> CString -> CFloat -> Ptr ImVec4 -> m ()
+ DearImGui.Raw.DrawList: addText_ :: MonadIO m => DrawList -> Ptr ImVec2 -> ImU32 -> CString -> CString -> m ()
+ DearImGui.Raw.DrawList: addTriangle :: MonadIO m => DrawList -> Ptr ImVec2 -> Ptr ImVec2 -> Ptr ImVec2 -> ImU32 -> CFloat -> m ()
+ DearImGui.Raw.DrawList: addTriangleFilled :: MonadIO m => DrawList -> Ptr ImVec2 -> Ptr ImVec2 -> Ptr ImVec2 -> ImU32 -> m ()
+ DearImGui.Raw.DrawList: cloneOutput :: MonadIO m => DrawList -> m DrawList
+ DearImGui.Raw.DrawList: destroy :: MonadIO m => DrawList -> m ()
+ DearImGui.Raw.DrawList: getClipRectMax :: MonadIO m => DrawList -> m ImVec2
+ DearImGui.Raw.DrawList: getClipRectMin :: MonadIO m => DrawList -> m ImVec2
+ DearImGui.Raw.DrawList: new :: MonadIO m => m DrawList
+ DearImGui.Raw.DrawList: newtype DrawList
+ DearImGui.Raw.DrawList: pathArcTo :: MonadIO m => DrawList -> Ptr ImVec2 -> CFloat -> CFloat -> CFloat -> CInt -> m ()
+ DearImGui.Raw.DrawList: pathArcToFast :: MonadIO m => DrawList -> Ptr ImVec2 -> CFloat -> CInt -> CInt -> m ()
+ DearImGui.Raw.DrawList: pathBezierCubicCurveTo :: MonadIO m => DrawList -> Ptr ImVec2 -> Ptr ImVec2 -> Ptr ImVec2 -> CInt -> m ()
+ DearImGui.Raw.DrawList: pathBezierQuadraticCurveTo :: MonadIO m => DrawList -> Ptr ImVec2 -> Ptr ImVec2 -> CInt -> m ()
+ DearImGui.Raw.DrawList: pathClear :: MonadIO m => DrawList -> m ()
+ DearImGui.Raw.DrawList: pathFillConvex :: MonadIO m => DrawList -> ImU32 -> m ()
+ DearImGui.Raw.DrawList: pathLineTo :: MonadIO m => DrawList -> Ptr ImVec2 -> m ()
+ DearImGui.Raw.DrawList: pathLineToMergeDuplicate :: MonadIO m => DrawList -> Ptr ImVec2 -> m ()
+ DearImGui.Raw.DrawList: pathRect :: MonadIO m => DrawList -> Ptr ImVec2 -> Ptr ImVec2 -> CFloat -> ImDrawFlags -> m ()
+ DearImGui.Raw.DrawList: pathStroke :: MonadIO m => DrawList -> ImU32 -> ImDrawFlags -> CFloat -> m ()
+ DearImGui.Raw.DrawList: popClipRect :: MonadIO m => DrawList -> m ()
+ DearImGui.Raw.DrawList: popTextureID :: MonadIO m => DrawList -> m ()
+ DearImGui.Raw.DrawList: pushClipRect :: MonadIO m => DrawList -> Ptr ImVec2 -> Ptr ImVec2 -> CBool -> m ()
+ DearImGui.Raw.DrawList: pushClipRectFullScreen :: MonadIO m => DrawList -> m ()
+ DearImGui.Raw.DrawList: pushTextureID :: MonadIO m => DrawList -> Ptr () -> m ()
+ DearImGui.Raw.IO: setIniFilename :: MonadIO m => CString -> m ()
+ DearImGui.Raw.IO: setKeyRepeatDelay :: MonadIO m => CFloat -> m ()
+ DearImGui.Raw.IO: setKeyRepeatRate :: MonadIO m => CFloat -> m ()
+ DearImGui.Raw.IO: setLogFilename :: MonadIO m => CString -> m ()
+ DearImGui.Raw.IO: setMouseDoubleClickMaxDist :: MonadIO m => CFloat -> m ()
+ DearImGui.Raw.IO: setMouseDoubleClickTime :: MonadIO m => CFloat -> m ()
+ DearImGui.Raw.IO: setMouseDragThreshold :: MonadIO m => CFloat -> m ()
+ DearImGui.Raw.IO: setUserData :: MonadIO m => Ptr () -> m ()
+ DearImGui.Raw.ListClipper: begin :: MonadIO m => ListClipper -> CInt -> CFloat -> m ()
+ DearImGui.Raw.ListClipper: delete :: MonadIO m => ListClipper -> m ()
+ DearImGui.Raw.ListClipper: displayEnd :: ListClipper -> CInt
+ DearImGui.Raw.ListClipper: displayStart :: ListClipper -> CInt
+ DearImGui.Raw.ListClipper: new :: MonadIO m => m ListClipper
+ DearImGui.Raw.ListClipper: step :: MonadIO m => ListClipper -> m Bool
+ DearImGui.Raw.ListClipper: type ListClipper = Ptr ImGuiListClipper

Files

ChangeLog.md view
@@ -1,5 +1,9 @@ # Changelog for dear-imgui +## [1.2.1]++- Added `DearImGui.Raw.IO` with attribute setters.+ ## [1.2.0]  - Fixed `nullPtr` in place of default arguments.
Main.hs view
@@ -7,6 +7,7 @@  import Control.Monad import Data.IORef+import qualified Data.Vector as Vector import DearImGui import DearImGui.OpenGL3 import DearImGui.SDL@@ -130,6 +131,21 @@   combo "Simple" selected [ "1", "2", "3" ]    endChild++  text "ListClipper"+  withChildOpen "##fixed" (ImVec2 0 200) True ImGuiWindowFlags_None do+    let lotsOfItems = Vector.generate 50 (mappend "Item " . show)+    withListClipper Nothing lotsOfItems text++  text "ListClipper, Haskell-powered"+  withChildOpen "##infinite" (ImVec2 0 200) True ImGuiWindowFlags_None do+    let infiniteItems = map (mappend "Item " . show) [0 :: Int ..]+    withListClipper Nothing infiniteItems text++  text "Ethereal ListClipper"+  withChildOpen "##ethereal" (ImVec2 0 200) True ImGuiWindowFlags_None do+    withListClipper Nothing (ClipRange (0 :: Int) 1000) $+      text . mappend "Item " . show    plotHistogram "A histogram" [ 10, 10, 20, 30, 90 ] 
README.md view
@@ -54,38 +54,35 @@    runManaged do     -- Create a window using SDL. As we're using OpenGL, we need to enable OpenGL too.-    w <- do+    window <- do       let title = "Hello, Dear ImGui!"       let config = defaultWindow { windowGraphicsContext = OpenGLContext defaultOpenGL }       managed $ bracket (createWindow title config) destroyWindow      -- Create an OpenGL context-    glContext <- managed $ bracket (glCreateContext w) glDeleteContext+    glContext <- managed $ bracket (glCreateContext window) glDeleteContext      -- Create an ImGui context     _ <- managed $ bracket createContext destroyContext      -- Initialize ImGui's SDL2 backend-    _ <- managed_ $ bracket_ (sdl2InitForOpenGL w glContext) sdl2Shutdown+    _ <- managed_ $ bracket_ (sdl2InitForOpenGL window glContext) sdl2Shutdown      -- Initialize ImGui's OpenGL backend     _ <- managed_ $ bracket_ openGL2Init openGL2Shutdown -    liftIO $ mainLoop w+    liftIO $ mainLoop window   mainLoop :: Window -> IO ()-mainLoop w = do-  -- Process the event loop-  untilNothingM pollEventWithImGui-+mainLoop window = unlessQuit do   -- Tell ImGui we're starting a new frame   openGL2NewFrame   sdl2NewFrame   newFrame    -- Build the GUI-  bracket_ (begin "Hello, ImGui!") end do+  withWindowOpen "Hello, ImGui!" do     -- Add a text widget     text "Hello, ImGui!" @@ -103,12 +100,25 @@   render   openGL2RenderDrawData =<< getDrawData -  glSwapWindow w+  glSwapWindow window -  mainLoop w+  mainLoop window    where-    untilNothingM m = m >>= maybe (return ()) (\_ -> untilNothingM m)+    -- 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 ```  # Hacking
dear-imgui.cabal view
@@ -1,7 +1,7 @@ cabal-version: 3.0  name: dear-imgui-version: 1.2.0+version: 1.2.1 author: Oliver Charles maintainer: ollie@ocharles.org.uk, aenor.realm@gmail.com license: BSD-3-Clause@@ -24,10 +24,45 @@   imgui/imconfig.h,   imgui/LICENSE.txt +common build-flags+  if flag(debug)+    if os(linux)+      ghc-options: -Wall -g -rtsopts -dcore-lint -debug+      cc-options: -g -O0 -fsanitize=address -fno-omit-frame-pointer+      cxx-options: -g -O0 -fsanitize=address -fno-omit-frame-pointer -std=c++11+    if os(darwin)+      ghc-options: -Wall -g -rtsopts -dcore-lint -debug+      cc-options: -g -O0 -fsanitize=address -fno-omit-frame-pointer+      cxx-options: -g -O0 -fsanitize=address -fno-omit-frame-pointer -std=c++11+    if os(windows)+      ghc-options: -Wall -g -rtsopts -dcore-lint -debug+      cc-options: -g -O0+      cxx-options: -g -O0 -std=c++11+  else+    if os(linux)+      ghc-options: -Wall -O2+      cc-options: -O2+      cxx-options: -std=c++11 -O2+    if os(darwin)+      ghc-options: -Wall -O2+      cc-options: -O2+    if os(windows)+      ghc-options: -Wall -O2+      cc-options: -O2++ source-repository head   type: git   location: https://github.com/haskell-game/dear-imgui.hs +flag debug+  description:+    Enable debug mode.+  default:+    False+  manual:+    True+ flag opengl2   description:     Enable OpenGL 2 backend.@@ -82,8 +117,6 @@         >= 4.12 && < 4.17   default-language:       Haskell2010-  ghc-options:-      -Wall  library   import: common@@ -92,18 +125,20 @@   exposed-modules:     DearImGui     DearImGui.Raw+    DearImGui.Raw.DrawList+    DearImGui.Raw.ListClipper+    DearImGui.Raw.IO   other-modules:     DearImGui.Context     DearImGui.Enums     DearImGui.Structs+  cxx-options: -std=c++11   cxx-sources:     imgui/imgui.cpp     imgui/imgui_demo.cpp     imgui/imgui_draw.cpp     imgui/imgui_tables.cpp     imgui/imgui_widgets.cpp-  cxx-options:-    -std=c++11   extra-libraries:     stdc++   include-dirs:@@ -116,6 +151,7 @@     , inline-c-cpp     , StateVar     , unliftio+    , vector    if flag(opengl2)     exposed-modules:@@ -233,27 +269,26 @@         >= 0.2.11 && < 0.2.15  executable test-  import: common+  import: common, build-flags   main-is: Main.hs   default-language: Haskell2010-  ghc-options: -Wall   if (!flag(examples) || !flag(sdl) || !flag(opengl2))     buildable: False   else-    build-depends: base, sdl2, gl, dear-imgui+    build-depends: base, sdl2, gl, dear-imgui, vector  executable glfw+  import: common, build-flags   main-is: Main.hs   hs-source-dirs: examples/glfw   default-language: Haskell2010-  ghc-options: -Wall   if (!flag(examples) || !flag(glfw) || !flag(opengl2))     buildable: False   else     build-depends: base, GLFW-b, gl, dear-imgui, managed  executable readme-  import: common+  import: common, build-flags   main-is: Readme.hs   hs-source-dirs: examples   build-depends: sdl2, gl, dear-imgui, managed@@ -261,7 +296,7 @@     buildable: False  executable image-  import: common+  import: common, build-flags   main-is: Image.hs   hs-source-dirs: examples/sdl   build-depends: sdl2, gl, dear-imgui, managed, vector@@ -269,12 +304,11 @@     buildable: False  executable vulkan-  import: common+  import: common, build-flags   main-is: Main.hs   other-modules: Attachments, Backend, Input, Util   hs-source-dirs: examples/vulkan   default-language: Haskell2010-  ghc-options: -Wall   if (!flag(examples) || !flag(sdl) || !flag(vulkan))     buildable: False   else
examples/Readme.hs view
@@ -45,10 +45,7 @@   mainLoop :: Window -> IO ()-mainLoop window = do-  -- Process the event loop-  untilNothingM pollEventWithImGui-+mainLoop window = unlessQuit do   -- Tell ImGui we're starting a new frame   openGL2NewFrame   sdl2NewFrame@@ -78,4 +75,17 @@   mainLoop window    where-    untilNothingM m = m >>= maybe (return ()) (\_ -> untilNothingM m)+    -- 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
examples/sdl/Image.hs view
@@ -14,6 +14,7 @@ import Control.Monad.Managed (managed, managed_, runManaged) import DearImGui import qualified DearImGui.Raw as Raw+import qualified DearImGui.Raw.DrawList as DrawList import DearImGui.OpenGL3 import DearImGui.SDL import DearImGui.SDL.OpenGL@@ -134,18 +135,18 @@   sdl2NewFrame   newFrame +  let texture = if flag then fst textures else snd textures+  -- Drawing images require some backend-specific code.+  -- Meanwhile, we have to deal with raw bindings.+  let openGLtextureID = intPtrToPtr $ fromIntegral $ textureID texture+   -- Build the GUI   clicked <- withWindow "Image example" \open ->     if open then do       text "That's an image, click it"       newLine -      let texture = if flag then fst textures else snd textures--      -- Drawing images require some backend-specific code.-      -- Meanwhile, we have to deal with raw binding.-      let openGLtextureID = intPtrToPtr $ fromIntegral $ textureID texture-+      -- Using imageButton       Foreign.with (textureSize texture) \sizePtr ->         Foreign.with (ImVec2 0 0) \uv0Ptr ->           Foreign.with (ImVec2 1 1) \uv1Ptr ->@@ -154,6 +155,19 @@                 Raw.imageButton openGLtextureID sizePtr uv0Ptr uv1Ptr (-1) bgColPtr tintColPtr     else       pure False++  -- Using DrawList+  bg <- getBackgroundDrawList+  Foreign.with (ImVec2 100 100) \pMin ->+    Foreign.with (ImVec2 200 200) \pMax ->+      Foreign.with (ImVec2 0.25 0.25) \uvMin ->+        Foreign.with (ImVec2 0.75 0.75) \uvMax ->+          DrawList.addImageRounded+            bg+            openGLtextureID+            pMin pMax uvMin uvMax+            (Raw.imCol32 0 255 0 0xFF) -- Extract green channel+            32 ImDrawFlags_RoundCornersBottom    -- Render   glClear GL_COLOR_BUFFER_BIT
src/DearImGui.hs view
@@ -3,6 +3,7 @@ {-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE FlexibleInstances #-} {-# LANGUAGE LambdaCase #-}+{-# LANGUAGE MultiParamTypeClasses #-} {-# LANGUAGE NamedFieldPuns #-} {-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE PatternSynonyms #-}@@ -54,6 +55,7 @@      -- ** Utilities +  , Raw.getWindowDrawList   , Raw.getWindowPos   , Raw.getWindowSize   , Raw.getWindowWidth@@ -172,11 +174,11 @@   , inputTextMultiline   , inputTextWithHint -    -- * Color Editor/Picker+    -- ** Color Editor/Picker   , colorPicker3   , colorButton -    -- * Trees+    -- ** Trees   , treeNode   , treePush   , Raw.treePop@@ -187,7 +189,7 @@     -- ** List Boxes   , listBox -    -- * Data Plotting+    -- ** Data Plotting   , plotHistogram      -- ** Menus@@ -221,7 +223,7 @@   , tabItemButton   , setTabItemClosed -    -- * Tooltips+    -- ** Tooltips   , withTooltip   , Raw.beginTooltip   , Raw.endTooltip@@ -252,6 +254,18 @@   , Raw.buildFontAtlas   , Raw.clearFontAtlas +    -- * Utilities++    -- ** ListClipper+  , withListClipper+  , ClipItems(..)+  , ClipRange(..)++    -- ** Miscellaneous+  , Raw.getBackgroundDrawList+  , Raw.getForegroundDrawList+  , Raw.imCol32+     -- * Types   , module DearImGui.Enums   , module DearImGui.Structs@@ -290,7 +304,12 @@ import UnliftIO.Exception (bracket, bracket_)  import qualified DearImGui.Raw as Raw+import qualified DearImGui.Raw.ListClipper as Raw.ListClipper +-- vector+import qualified Data.Vector as V+import qualified Data.Vector.Storable as VS+import qualified Data.Vector.Unboxed as VU  -- | Get the compiled version string e.g. "1.80 WIP" (essentially the value for -- @IMGUI_VERSION@ from the compiled version of @imgui.cpp@).@@ -1690,3 +1709,86 @@     if castPtr ptr == nullPtr       then Nothing       else Just res++-- | Clips a large list of items+--+-- The requirements on @a@ are that they are all of the same height.+withListClipper :: (ClipItems t a, MonadUnliftIO m) => Maybe Float -> t a -> (a -> m ()) -> m ()+withListClipper itemHeight items action =+  bracket+    (liftIO $ throwIfNull "withListClipper: ListClipper allocation failed" Raw.ListClipper.new)+    Raw.ListClipper.delete+    step+  where+    itemHeight' = maybe (-1.0) CFloat itemHeight+    itemCount' = maybe maxBound fromIntegral (itemCount items)++    step clipper = do+      Raw.ListClipper.begin clipper itemCount' itemHeight'+      go clipper++    go clipper = do+      doStep <- Raw.ListClipper.step clipper+      when doStep do+        let+          startIndex = fromIntegral $ Raw.ListClipper.displayStart clipper+          endIndex   = fromIntegral $ Raw.ListClipper.displayEnd clipper+        stepItems action $+          clipItems startIndex endIndex items++        go clipper++-- | Containers usable with 'ListClipper'.+class ClipItems t a where+  itemCount :: t a -> Maybe Int+  clipItems :: Int -> Int -> t a -> t a+  stepItems :: Monad m => (a -> m ()) -> t a -> m ()++-- | Unbounded stream of items.+instance ClipItems [] a where+  itemCount = const Nothing++  clipItems displayStart displayEnd =+    take (displayEnd - displayStart) . drop displayStart++  stepItems = mapM_++instance ClipItems V.Vector a where+  itemCount = Just . V.length++  clipItems displayStart displayEnd =+    V.slice displayStart (displayEnd - displayStart)++  stepItems = V.mapM_++instance Storable a => ClipItems VS.Vector a where+  itemCount = Just . VS.length++  clipItems displayStart displayEnd =+    VS.slice displayStart (displayEnd - displayStart)++  stepItems = VS.mapM_++instance VU.Unbox a => ClipItems VU.Vector a where+  itemCount = Just . VU.length++  clipItems displayStart displayEnd =+    VU.slice displayStart (displayEnd - displayStart)++  stepItems = VU.mapM_++-- | ClipList helper for arbitrary unmaterialized ranges.+data ClipRange a = ClipRange a a+  deriving (Eq, Ord, Show)++instance (Ord a, Enum a, Num a) => ClipItems ClipRange a where+  itemCount (ClipRange _begin end) =+    Just $ fromEnum end++  clipItems clipBegin clipEnd (ClipRange oldBegin oldEnd) =+    ClipRange+      (toEnum $ max clipBegin $ fromEnum oldBegin)+      (toEnum $ min clipEnd $ fromEnum oldEnd)++  stepItems action (ClipRange start end) =+    mapM_ action [start .. end - 1]
src/DearImGui/Context.hs view
@@ -33,7 +33,10 @@       [ ( TypeName "ImVec2", [t| ImVec2 |] )       , ( TypeName "ImVec3", [t| ImVec3 |] )       , ( TypeName "ImVec4", [t| ImVec4 |] )+      , ( TypeName "ImU32", [t| ImU32 |] )+      , ( TypeName "ImDrawList", [t| ImDrawList |] )       , ( TypeName "ImGuiContext", [t| ImGuiContext |] )       , ( TypeName "ImFont", [t| ImFont |] )+      , ( TypeName "ImGuiListClipper", [t| ImGuiListClipper |] )       ]   }
src/DearImGui/Raw.hs view
@@ -49,6 +49,7 @@      -- ** Utilities +  , getWindowDrawList   , getWindowPos   , getWindowSize   , getWindowWidth@@ -89,6 +90,7 @@   , beginGroup   , endGroup   , setCursorPos+  , getCursorScreenPos   , alignTextToFramePadding      -- * Widgets@@ -217,6 +219,13 @@   , buildFontAtlas   , clearFontAtlas +    -- * Utilities++    -- ** Miscellaneous+  , getBackgroundDrawList+  , getForegroundDrawList+  , imCol32+     -- * Types   , module DearImGui.Enums   , module DearImGui.Structs@@ -228,12 +237,15 @@   ( MonadIO, liftIO ) import Foreign import Foreign.C+import System.IO.Unsafe+  ( unsafePerformIO )  -- dear-imgui import DearImGui.Context   ( imguiContext ) import DearImGui.Enums import DearImGui.Structs+import DearImGui.Raw.DrawList (DrawList(..))  -- inline-c import qualified Language.C.Inline as C@@ -1264,6 +1276,19 @@ isItemHovered = liftIO do   (0 /=) <$> [C.exp| bool { IsItemHovered() } |] ++-- | Get draw list associated to the current window.+getWindowDrawList :: (MonadIO m) => m DrawList+getWindowDrawList = liftIO do+  DrawList <$> [C.exp|+    ImDrawList* {+      GetWindowDrawList()+    }+  |]++-- | Get current window position in screen space.+--+-- Useful if you want to do your own drawing via the "DrawList" API. getWindowPos :: (MonadIO m) => m ImVec2 getWindowPos = liftIO do   C.withPtr_ \ptr ->@@ -1445,7 +1470,22 @@ setCursorPos posPtr = liftIO do   [C.exp| void { SetCursorPos(*$(ImVec2* posPtr)) } |] +-- | Cursor position in absolute coordinates.+--+-- Useful to work with 'DrawList' API.+--+-- Generally top-left == @GetMainViewport()->Pos == (0,0)@ in single viewport mode,+-- and bottom-right == @GetMainViewport()->Pos+Size == io.DisplaySize@ in single-viewport mode.+getCursorScreenPos :: (MonadIO m) => m ImVec2+getCursorScreenPos = liftIO do+  C.withPtr_ \ptr ->+    [C.block|+      void {+        *$(ImVec2 * ptr) = GetCursorScreenPos();+      }+    |] + -- | Modify a style color by pushing to the shared stack. always use this if you modify the style after `newFrame` -- -- Wraps @ImGui::PushStyleColor()@@@ -1571,5 +1611,44 @@   [C.block|     void {       GetIO().Fonts->Clear();+    }+  |]+++-- | This draw list will be the first rendering one.+--+-- Useful to quickly draw shapes/text behind dear imgui contents.+getBackgroundDrawList :: (MonadIO m) => m DrawList+getBackgroundDrawList = liftIO do+  DrawList <$> [C.exp|+    ImDrawList* {+      GetBackgroundDrawList()+    }+  |]++--  | This draw list will be the last rendered one.+--+-- Useful to quickly draw shapes/text over dear imgui contents.+getForegroundDrawList :: (MonadIO m) => m DrawList+getForegroundDrawList = liftIO do+  DrawList <$> [C.exp|+    ImDrawList* {+      GetForegroundDrawList()+    }+  |]++-- | Generate 32-bit encoded colors using DearImgui macros.+--+-- Follows @IMGUI_USE_BGRA_PACKED_COLOR@ define to put bytes in appropriate positions.+imCol32 :: CUChar -> CUChar -> CUChar -> CUChar -> ImU32+imCol32 r g b a = unsafePerformIO+  [C.exp|+    ImU32 {+      IM_COL32(+        $(unsigned char r),+        $(unsigned char g),+        $(unsigned char b),+        $(unsigned char a)+      )     }   |]
+ src/DearImGui/Raw/DrawList.hs view
@@ -0,0 +1,742 @@+{-# LANGUAGE BlockArguments #-}+{-# LANGUAGE DuplicateRecordFields #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE LambdaCase #-}+{-# LANGUAGE NamedFieldPuns #-}+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE PatternSynonyms #-}+{-# LANGUAGE QuasiQuotes #-}+{-# LANGUAGE TemplateHaskell #-}+{-# LANGUAGE ViewPatterns #-}++{-| Draw command list++This is the low-level list of polygons that ImGui functions are filling.++At the end of the frame, all command lists are passed to your @ImGuiIO::RenderDrawListFn@ function for rendering.++Each dear imgui window contains its own ImDrawList.++You can use 'getWindowDrawList' to access the current window draw list and draw custom primitives.++You can interleave normal ImGui calls and adding primitives to the current draw list.++In single viewport mode, top-left is == @GetMainViewport()->Pos@ (generally @0,0@),+bottom-right is == @GetMainViewport()->Pos+Size@ (generally io.DisplaySize).++You are totally free to apply whatever transformation matrix to want to the data+(depending on the use of the transformation you may want to apply it to ClipRect as well!).++__Important__: Primitives are always added to the list and not culled (culling is done at higher-level by ImGui functions),+if you use this API a lot consider coarse culling your drawn objects.+-}++module DearImGui.Raw.DrawList+  ( DrawList(..)+  , new+  , destroy++    -- * Primitives++    -- $primitives+  , addLine++  , addRect+  , addRectFilled+  , addRectFilledMultiColor++  , addQuad+  , addQuadFilled++  , addTriangle+  , addTriangleFilled++  , addCircle+  , addCircleFilled++  , addNgon+  , addNgonFilled++  , addText_+  , addText++  , addPolyLine+  , addConvexPolyFilled++  , addBezierCubic+  , addBezierQuadratic++    -- ** Image primitives++    -- $image+  , addImage+  , addImageQuad+  , addImageRounded++    -- * Stateful path API++    -- $stateful+  , pathClear+  , pathLineTo+  , pathLineToMergeDuplicate+  , pathFillConvex+  , pathStroke++  , pathArcTo+  , pathArcToFast++  , pathBezierCubicCurveTo+  , pathBezierQuadraticCurveTo++  , pathRect++    -- * Advanced++  -- , addCallback+  , addDrawCmd+  , cloneOutput++    -- * Internal state++  , pushClipRect+  , pushClipRectFullScreen+  , popClipRect+  , getClipRectMin+  , getClipRectMax++  , pushTextureID+  , popTextureID+  )+  where++import Control.Monad.IO.Class+  ( MonadIO, liftIO )+import Foreign hiding (new)+import Foreign.C++-- dear-imgui+import DearImGui.Context+  ( imguiContext )+import DearImGui.Enums+import DearImGui.Structs++-- inline-c+import qualified Language.C.Inline as C++-- inline-c-cpp+import qualified Language.C.Inline.Cpp as Cpp++C.context (Cpp.cppCtx <> C.bsCtx <> imguiContext)+C.include "imgui.h"+Cpp.using "namespace ImGui"++-- | A single draw command list.+-- Generally one per window, conceptually you may see this as a dynamic "mesh" builder.+newtype DrawList = DrawList (Ptr ImDrawList)++new :: MonadIO m => m DrawList+new = liftIO do+  DrawList <$> [C.block|+    ImDrawList* {+      return IM_NEW(ImDrawList(GetDrawListSharedData()));+    }+  |]++destroy :: MonadIO m => DrawList -> m ()+destroy (DrawList drawList) = liftIO do+  [C.block|+    void {+      IM_DELETE($(ImDrawList* drawList));+    }+  |]+++pushClipRect :: MonadIO m => DrawList -> Ptr ImVec2 -> Ptr ImVec2 -> CBool -> m ()+pushClipRect (DrawList drawList) clip_rect_min clip_rect_max intersect_with_current_clip_rect = liftIO do+  [C.block|+    void {+      $(ImDrawList* drawList)->PushClipRect(+        *$(ImVec2* clip_rect_min),+        *$(ImVec2* clip_rect_max),+        $(bool intersect_with_current_clip_rect)+      );+    }+  |]++pushClipRectFullScreen :: MonadIO m => DrawList -> m ()+pushClipRectFullScreen (DrawList drawList) = liftIO do+  [C.block|+    void {+      $(ImDrawList* drawList)->PushClipRectFullScreen();+    }+  |]++popClipRect :: MonadIO m => DrawList -> m ()+popClipRect (DrawList drawList) = liftIO do+  [C.block|+    void {+      $(ImDrawList* drawList)->PopClipRect();+    }+  |]+++getClipRectMin :: MonadIO m => DrawList -> m ImVec2+getClipRectMin (DrawList drawList) = liftIO do+  C.withPtr_ \ptr ->+    [C.block|+      void {+        *$(ImVec2 * ptr) = $(ImDrawList* drawList)->GetClipRectMin();+      }+    |]++getClipRectMax :: MonadIO m => DrawList -> m ImVec2+getClipRectMax (DrawList drawList) = liftIO do+  C.withPtr_ \ptr ->+    [C.block|+      void {+        *$(ImVec2 * ptr) = $(ImDrawList* drawList)->GetClipRectMax();+      }+    |]+++pushTextureID :: MonadIO m => DrawList -> Ptr () -> m ()+pushTextureID (DrawList drawList) userTextureIDPtr = liftIO do+  [C.block|+    void {+      $(ImDrawList* drawList)->PushTextureID(+        $(void* userTextureIDPtr)+      );+    }+  |]++popTextureID :: MonadIO m => DrawList -> m ()+popTextureID (DrawList drawList) = liftIO do+  [C.block|+    void {+      $(ImDrawList* drawList)->PopTextureID();+    }+  |]+++{- $primitives+- For rectangular primitives, @p_min@ and @p_max@ represent the upper-left and lower-right corners.+- For circle primitives, use @num_segments == 0@ to automatically calculate tessellation (preferred).+  In older versions (until Dear ImGui 1.77) the 'addCircle' functions defaulted to num_segments == 12.+  In future versions we will use textures to provide cheaper and higher-quality circles.+  Use 'addNgon' and 'addNgonFilled' functions if you need to guaranteed a specific number of sides.+-}++addLine :: MonadIO m => DrawList -> Ptr ImVec2 -> Ptr ImVec2 -> ImU32 -> CFloat -> m ()+addLine (DrawList drawList) p1 p2 col thickness = liftIO do+  [C.block|+    void {+      $(ImDrawList* drawList)->AddLine(+        *$(ImVec2* p1),+        *$(ImVec2* p2),+        $(ImU32 col),+        $(float thickness)+      );+    }+  |]+++addRect :: MonadIO m => DrawList -> Ptr ImVec2 -> Ptr ImVec2 -> ImU32 -> CFloat -> ImDrawFlags -> CFloat -> m ()+addRect (DrawList drawList) p_min p_max col rounding flags thickness = liftIO do+  [C.block|+    void {+      $(ImDrawList* drawList)->AddRect(+        *$(ImVec2* p_min),+        *$(ImVec2* p_max),+        $(ImU32 col),+        $(float rounding),+        $(ImDrawFlags flags),+        $(float thickness)+      );+    }+  |]++addRectFilled :: MonadIO m => DrawList -> Ptr ImVec2 -> Ptr ImVec2 -> ImU32 -> CFloat -> ImDrawFlags -> m ()+addRectFilled (DrawList drawList) p_min p_max col rounding flags = liftIO do+  [C.block|+    void {+      $(ImDrawList* drawList)->AddRectFilled(+        *$(ImVec2* p_min),+        *$(ImVec2* p_max),+        $(ImU32 col),+        $(float rounding),+        $(ImDrawFlags flags)+      );+    }+  |]++addRectFilledMultiColor :: MonadIO m => DrawList -> Ptr ImVec2 -> Ptr ImVec2 -> ImU32 -> ImU32 -> ImU32 -> ImU32 -> m ()+addRectFilledMultiColor (DrawList drawList) p_min p_max col_upr_left col_upr_right col_bot_right col_bot_left = liftIO do+  [C.block|+    void {+      $(ImDrawList* drawList)->AddRectFilledMultiColor(+        *$(ImVec2* p_min),+        *$(ImVec2* p_max),+        $(ImU32 col_upr_left),+        $(ImU32 col_upr_right),+        $(ImU32 col_bot_right),+        $(ImU32 col_bot_left)+      );+    }+  |]+++addQuad :: MonadIO m => DrawList -> Ptr ImVec2 -> Ptr ImVec2 -> Ptr ImVec2 -> Ptr ImVec2 -> ImU32 -> CFloat -> m ()+addQuad (DrawList drawList) p1 p2 p3 p4 col thickness = liftIO do+  [C.block|+    void {+      $(ImDrawList* drawList)->AddQuad(+        *$(ImVec2* p1),+        *$(ImVec2* p2),+        *$(ImVec2* p3),+        *$(ImVec2* p4),+        $(ImU32 col),+        $(float thickness)+      );+    }+  |]++addQuadFilled :: MonadIO m => DrawList -> Ptr ImVec2 -> Ptr ImVec2 -> Ptr ImVec2 -> Ptr ImVec2 -> ImU32 -> m ()+addQuadFilled (DrawList drawList) p1 p2 p3 p4 col = liftIO do+  [C.block|+    void {+      $(ImDrawList* drawList)->AddQuadFilled(+        *$(ImVec2* p1),+        *$(ImVec2* p2),+        *$(ImVec2* p3),+        *$(ImVec2* p4),+        $(ImU32 col)+      );+    }+  |]+++addTriangle :: MonadIO m => DrawList -> Ptr ImVec2 -> Ptr ImVec2 -> Ptr ImVec2 -> ImU32 -> CFloat -> m ()+addTriangle (DrawList drawList) p1 p2 p3 col thickness = liftIO do+  [C.block|+    void {+      $(ImDrawList* drawList)->AddTriangle(+        *$(ImVec2* p1),+        *$(ImVec2* p2),+        *$(ImVec2* p3),+        $(ImU32 col),+        $(float thickness)+      );+    }+  |]++addTriangleFilled :: MonadIO m => DrawList -> Ptr ImVec2 -> Ptr ImVec2 -> Ptr ImVec2 -> ImU32 -> m ()+addTriangleFilled (DrawList drawList) p1 p2 p3 col = liftIO do+  [C.block|+    void {+      $(ImDrawList* drawList)->AddTriangleFilled(+        *$(ImVec2* p1),+        *$(ImVec2* p2),+        *$(ImVec2* p3),+        $(ImU32 col)+      );+    }+  |]+++addCircle :: MonadIO m => DrawList -> Ptr ImVec2 -> CFloat -> ImU32 -> CInt -> CFloat -> m ()+addCircle (DrawList drawList) center radius col num_segments thickness = liftIO do+  [C.block|+    void {+      $(ImDrawList* drawList)->AddCircle(+        *$(ImVec2* center),+        $(float radius),+        $(ImU32 col),+        $(int num_segments),+        $(float thickness)+      );+    }+  |]++addCircleFilled :: MonadIO m => DrawList -> Ptr ImVec2 -> CFloat -> ImU32 -> CInt -> m ()+addCircleFilled (DrawList drawList) center radius col num_segments = liftIO do+  [C.block|+    void {+      $(ImDrawList* drawList)->AddCircleFilled(+        *$(ImVec2* center),+        $(float radius),+        $(ImU32 col),+        $(int num_segments)+      );+    }+  |]+++addNgon :: MonadIO m => DrawList -> Ptr ImVec2 -> CFloat -> ImU32 -> CInt -> CFloat -> m ()+addNgon (DrawList drawList) center radius col num_segments thickness = liftIO do+  [C.block|+    void {+      $(ImDrawList* drawList)->AddNgon(+        *$(ImVec2* center),+        $(float radius),+        $(ImU32 col),+        $(int num_segments),+        $(float thickness)+      );+    }+  |]++addNgonFilled :: MonadIO m => DrawList -> Ptr ImVec2 -> CFloat -> ImU32 -> CInt -> m ()+addNgonFilled (DrawList drawList) center radius col num_segments = liftIO do+  [C.block|+    void {+      $(ImDrawList* drawList)->AddNgonFilled(+        *$(ImVec2* center),+        $(float radius),+        $(ImU32 col),+        $(int num_segments)+      );+    }+  |]+++addText_ :: MonadIO m => DrawList -> Ptr ImVec2 -> ImU32 -> CString -> CString -> m ()+addText_ (DrawList drawList) pos col text_begin text_end = liftIO do+  [C.block|+    void {+      $(ImDrawList* drawList)->AddText(+        *$(ImVec2* pos),+        $(ImU32 col),+        $(char* text_begin),+        $(char* text_end)+      );+    }+  |]++addText :: MonadIO m => DrawList -> Ptr ImFont -> CFloat -> Ptr ImVec2 -> ImU32 -> CString -> CString -> CFloat -> Ptr ImVec4 -> m ()+addText (DrawList drawList) fontPtr font_size pos col text_begin text_end wrap_width cpu_fine_clip_rect = liftIO do+  [C.block|+    void {+      $(ImDrawList* drawList)->AddText(+        $(ImFont* fontPtr),+        $(float font_size),+        *$(ImVec2* pos),+        $(ImU32 col),+        $(char* text_begin),+        $(char* text_end),+        $(float wrap_width),+        $(ImVec4* cpu_fine_clip_rect)+      );+    }+  |]+++addPolyLine :: MonadIO m => DrawList -> Ptr ImVec2 -> CInt -> ImU32 -> ImDrawFlags -> CFloat -> m ()+addPolyLine (DrawList drawList) points num_points col flags thickness = liftIO do+  [C.block|+    void {+      $(ImDrawList* drawList)->AddPolyline(+        $(ImVec2* points),+        $(int num_points),+        $(ImU32 col),+        $(ImDrawFlags flags),+        $(float thickness)+      );+    }+  |]++addConvexPolyFilled :: MonadIO m => DrawList -> Ptr ImVec2 -> CInt -> ImU32 -> m ()+addConvexPolyFilled (DrawList drawList) points num_points col = liftIO do+  [C.block|+    void {+      $(ImDrawList* drawList)->AddConvexPolyFilled(+        $(ImVec2* points),+        $(int num_points),+        $(ImU32 col)+      );+    }+  |]+++addBezierCubic+  :: MonadIO m+  => DrawList+  -> Ptr ImVec2 -> Ptr ImVec2 -> Ptr ImVec2 -> Ptr ImVec2 -- Positions (control points)+  -> ImU32+  -> CFloat+  -> CInt+  -> m ()+addBezierCubic (DrawList drawList) p1 p2 p3 p4 col thickness numSegments = liftIO do+  [C.block|+    void {+      $(ImDrawList* drawList)->AddBezierCubic(+        *$(ImVec2* p1),+        *$(ImVec2* p2),+        *$(ImVec2* p3),+        *$(ImVec2* p4),+        $(ImU32 col),+        $(float thickness),+        $(int numSegments)+      );+    }+  |]++addBezierQuadratic+  :: MonadIO m+  => DrawList+  -> Ptr ImVec2 -> Ptr ImVec2 -> Ptr ImVec2 -- Positions (control points)+  -> ImU32+  -> CFloat+  -> CInt+  -> m ()+addBezierQuadratic (DrawList drawList) p1 p2 p3 col thickness numSegments = liftIO do+  [C.block|+    void {+      $(ImDrawList* drawList)->AddBezierQuadratic(+        *$(ImVec2* p1),+        *$(ImVec2* p2),+        *$(ImVec2* p3),+        $(ImU32 col),+        $(float thickness),+        $(int numSegments)+      );+    }+  |]+++{- $image+* Read FAQ to understand what @ImTextureID@ is.+* @p_min@ and @p_max@ represent the upper-left and lower-right corners of the rectangle.+* @uv_min@ and @uv_max@ represent the normalized texture coordinates to use for those corners.+  Using @(0,0)->(1,1)@ texture coordinates will generally display the entire texture.+-}++addImage+  :: MonadIO m+  => DrawList+  -> Ptr ()+  -> Ptr ImVec2 -> Ptr ImVec2 -- Positions+  -> Ptr ImVec2 -> Ptr ImVec2 -- UVs+  -> ImU32+  -> m ()+addImage (DrawList drawList) userTextureIDPtr p_min p_max uv_min uv_max col = liftIO do+  [C.block|+    void {+      $(ImDrawList* drawList)->AddImage(+        $(void* userTextureIDPtr),+        *$(ImVec2* p_min),+        *$(ImVec2* p_max),+        *$(ImVec2* uv_min),+        *$(ImVec2* uv_max),+        $(ImU32 col)+      );+    }+  |]++addImageQuad+  :: MonadIO m+  => DrawList+  -> Ptr ()+  -> Ptr ImVec2 -> Ptr ImVec2 -> Ptr ImVec2 -> Ptr ImVec2 -- Positions+  -> Ptr ImVec2 -> Ptr ImVec2 -> Ptr ImVec2 -> Ptr ImVec2 -- UVs+  -> ImU32+  -> m ()+addImageQuad (DrawList drawList) userTextureIDPtr p1 p2 p3 p4 uv1 uv2 uv3 uv4 col = liftIO do+  [C.block|+    void {+      $(ImDrawList* drawList)->AddImageQuad(+        $(void* userTextureIDPtr),+        *$(ImVec2* p1),+        *$(ImVec2* p2),+        *$(ImVec2* p3),+        *$(ImVec2* p4),+        *$(ImVec2* uv1),+        *$(ImVec2* uv2),+        *$(ImVec2* uv3),+        *$(ImVec2* uv4),+        $(ImU32 col)+      );+    }+  |]++addImageRounded+  :: MonadIO m+  => DrawList+  -> Ptr ()+  -> Ptr ImVec2 -> Ptr ImVec2 -- Positions+  -> Ptr ImVec2 -> Ptr ImVec2 -- UVs+  -> ImU32+  -> CFloat+  -> ImDrawFlags+  -> m ()+addImageRounded (DrawList drawList) userTextureIDPtr p_min p_max uv_min uv_max col rounding flags = liftIO do+  [C.block|+    void {+      $(ImDrawList* drawList)->AddImageRounded(+        $(void* userTextureIDPtr),+        *$(ImVec2* p_min),+        *$(ImVec2* p_max),+        *$(ImVec2* uv_min),+        *$(ImVec2* uv_max),+        $(ImU32 col),+        $(float rounding),+        $(ImDrawFlags flags)+      );+    }+  |]++{- $stateful+Add points then finish with 'pathFillConvex' or 'pathStroke'.+-}++pathClear :: MonadIO m => DrawList -> m ()+pathClear (DrawList drawList) = liftIO do+  [C.block|+    void {+      $(ImDrawList* drawList)->PathClear();+    }+  |]++pathLineTo :: MonadIO m => DrawList -> Ptr ImVec2 -> m ()+pathLineTo (DrawList drawList) pos = liftIO do+  [C.block|+    void {+      $(ImDrawList* drawList)->PathLineTo(+        *$(ImVec2* pos)+      );+    }+  |]++pathLineToMergeDuplicate :: MonadIO m => DrawList -> Ptr ImVec2 -> m ()+pathLineToMergeDuplicate (DrawList drawList) pos = liftIO do+  [C.block|+    void {+      $(ImDrawList* drawList)->PathLineToMergeDuplicate(+        *$(ImVec2* pos)+      );+    }+  |]++-- | Note: Anti-aliased filling requires points to be in clockwise order.+pathFillConvex :: MonadIO m => DrawList -> ImU32 -> m ()+pathFillConvex (DrawList drawList) col = liftIO do+  [C.block|+    void {+      $(ImDrawList* drawList)->PathFillConvex(+        $(ImU32 col)+      );+    }+  |]++pathStroke :: MonadIO m => DrawList -> ImU32 -> ImDrawFlags -> CFloat -> m ()+pathStroke (DrawList drawList) col flags thickness = liftIO do+  [C.block|+    void {+      $(ImDrawList* drawList)->PathStroke(+        $(ImU32 col),+        $(ImDrawFlags flags),+        $(float thickness)+      );+    }+  |]+++pathArcTo :: MonadIO m => DrawList -> Ptr ImVec2 -> CFloat -> CFloat -> CFloat -> CInt -> m ()+pathArcTo (DrawList drawList) center radius a_min a_max num_segments = liftIO do+  [C.block|+    void {+      $(ImDrawList* drawList)->PathArcTo(+        *$(ImVec2* center),+        $(float radius),+        $(float a_min),+        $(float a_max),+        $(int num_segments)+      );+    }+  |]++-- | Use precomputed angles for a 12 steps circle.+pathArcToFast :: MonadIO m => DrawList -> Ptr ImVec2 -> CFloat -> CInt -> CInt -> m ()+pathArcToFast (DrawList drawList) center radius a_min_of_12 a_max_of_12 = liftIO do+  [C.block|+    void {+      $(ImDrawList* drawList)->PathArcToFast(+        *$(ImVec2* center),+        $(float radius),+        $(int a_min_of_12),+        $(int a_max_of_12)+      );+    }+  |]+++pathBezierCubicCurveTo+  :: MonadIO m+  => DrawList+  -> Ptr ImVec2+  -> Ptr ImVec2+  -> Ptr ImVec2+  -> CInt+  -> m ()+pathBezierCubicCurveTo (DrawList drawList) p1 p2 p3 num_segments = liftIO do+  [C.block|+    void {+      $(ImDrawList* drawList)->PathBezierCubicCurveTo(+        *$(ImVec2* p1),+        *$(ImVec2* p2),+        *$(ImVec2* p3),+        $(int num_segments)+      );+    }+  |]++pathBezierQuadraticCurveTo+  :: MonadIO m+  => DrawList+  -> Ptr ImVec2+  -> Ptr ImVec2+  -> CInt+  -> m ()+pathBezierQuadraticCurveTo (DrawList drawList) p1 p2 num_segments = liftIO do+  [C.block|+    void {+      $(ImDrawList* drawList)->PathBezierQuadraticCurveTo(+        *$(ImVec2* p1),+        *$(ImVec2* p2),+        $(int num_segments)+      );+    }+  |]+++pathRect :: MonadIO m => DrawList -> Ptr ImVec2 -> Ptr ImVec2 -> CFloat -> ImDrawFlags -> m ()+pathRect (DrawList drawList) rect_min rect_max rounding flags = liftIO do+  [C.block|+    void {+      $(ImDrawList* drawList)->PathRect(+        *$(ImVec2* rect_min),+        *$(ImVec2* rect_max),+        $(float rounding),+        $(ImDrawFlags flags)+      );+    }+  |]+++-- | This is useful if you need to forcefully create a new draw call (to allow for dependent rendering / blending).+-- Otherwise primitives are merged into the same draw-call as much as possible.+addDrawCmd :: MonadIO m => DrawList -> m ()+addDrawCmd (DrawList drawList) = liftIO do+  [C.block|+    void {+      $(ImDrawList* drawList)->AddDrawCmd();+    }+  |]++-- | Create a clone of the CmdBuffer/IdxBuffer/VtxBuffer.+cloneOutput :: MonadIO m => DrawList -> m DrawList+cloneOutput (DrawList drawList) = liftIO do+  DrawList <$> [C.block|+    ImDrawList* {+      return $(ImDrawList* drawList)->CloneOutput();+    }+  |]
+ src/DearImGui/Raw/IO.hs view
@@ -0,0 +1,137 @@+{-# LANGUAGE BlockArguments #-}+{-# LANGUAGE DuplicateRecordFields #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE LambdaCase #-}+{-# LANGUAGE NamedFieldPuns #-}+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE PatternSynonyms #-}+{-# LANGUAGE QuasiQuotes #-}+{-# LANGUAGE TemplateHaskell #-}+{-# LANGUAGE ViewPatterns #-}++{-| Main configuration and I/O between your application and ImGui++-}++module DearImGui.Raw.IO+  ( setIniFilename+  , setLogFilename++  , setMouseDoubleClickMaxDist+  , setMouseDoubleClickTime+  , setMouseDragThreshold++  , setKeyRepeatDelay+  , setKeyRepeatRate++  , setUserData+  ) where++-- TODO: add exports++import Control.Monad.IO.Class+  ( MonadIO, liftIO )+import Foreign+  ( Ptr )+import Foreign.C+  ( CFloat(..)+  , CString+  )++-- dear-imgui+import DearImGui.Context+  ( imguiContext )+-- import DearImGui.Enums+-- import DearImGui.Structs++-- inline-c+import qualified Language.C.Inline as C++-- inline-c-cpp+import qualified Language.C.Inline.Cpp as Cpp++C.context (Cpp.cppCtx <> C.bsCtx <> imguiContext)+C.include "imgui.h"+Cpp.using "namespace ImGui"++setIniFilename :: MonadIO m => CString -> m ()+setIniFilename ptr = liftIO do+  [C.block|+    void {+      GetIO().IniFilename = $(char * ptr);+    }+  |]++setLogFilename :: MonadIO m => CString -> m ()+setLogFilename ptr = liftIO do+  [C.block|+    void {+      GetIO().LogFilename = $(char * ptr);+    }+  |]++setMouseDoubleClickTime :: MonadIO m => CFloat -> m ()+setMouseDoubleClickTime seconds = liftIO do+  [C.block|+    void {+      GetIO().MouseDoubleClickTime = $(float seconds);+    }+  |]++setMouseDoubleClickMaxDist :: MonadIO m => CFloat -> m ()+setMouseDoubleClickMaxDist pixels = liftIO do+  [C.block|+    void {+      GetIO().MouseDoubleClickMaxDist = $(float pixels);+    }+  |]++setMouseDragThreshold :: MonadIO m => CFloat -> m ()+setMouseDragThreshold pixels = liftIO do+  [C.block|+    void {+      GetIO().MouseDragThreshold = $(float pixels);+    }+  |]++setKeyRepeatDelay :: MonadIO m => CFloat -> m ()+setKeyRepeatDelay seconds = liftIO do+  [C.block|+    void {+      GetIO().KeyRepeatDelay = $(float seconds);+    }+  |]++setKeyRepeatRate :: MonadIO m => CFloat -> m ()+setKeyRepeatRate pixels = liftIO do+  [C.block|+    void {+      GetIO().KeyRepeatRate = $(float pixels);+    }+  |]++setUserData :: MonadIO m => Ptr () -> m ()+setUserData ptr = liftIO do+  [C.block|+    void {+      GetIO().UserData = $(void* ptr);+    }+  |]++{- TODO:++bool   WantCaptureMouse;         // Set when Dear ImGui will use mouse inputs, in this case do not dispatch them to your main game/application (either way, always pass on mouse inputs to imgui). (e.g. unclicked mouse is hovering over an imgui window, widget is active, mouse was clicked over an imgui window, etc.).+bool   WantCaptureKeyboard;      // Set when Dear ImGui will use keyboard inputs, in this case do not dispatch them to your main game/application (either way, always pass keyboard inputs to imgui). (e.g. InputText active, or an imgui window is focused and navigation is enabled, etc.).+bool   WantTextInput;            // Mobile/console: when set, you may display an on-screen keyboard. This is set by Dear ImGui when it wants textual keyboard input to happen (e.g. when a InputText widget is active).+bool   WantSetMousePos;          // MousePos has been altered, backend should reposition mouse on next frame. Rarely used! Set only when ImGuiConfigFlags_NavEnableSetMousePos flag is enabled.+bool   WantSaveIniSettings;      // When manual .ini load/save is active (io.IniFilename == NULL), this will be set to notify your application that you can call SaveIniSettingsToMemory() and save yourself. Important: clear io.WantSaveIniSettings yourself after saving!+bool   NavActive;                // Keyboard/Gamepad navigation is currently allowed (will handle ImGuiKey_NavXXX events) = a window is focused and it doesn't use the ImGuiWindowFlags_NoNavInputs flag.+bool   NavVisible;               // Keyboard/Gamepad navigation is visible and allowed (will handle ImGuiKey_NavXXX events).+float  Framerate;                // Rough estimate of application framerate, in frame per second. Solely for convenience. Rolling average estimation based on io.DeltaTime over 120 frames.+int    MetricsRenderVertices;    // Vertices output during last call to Render()+int    MetricsRenderIndices;     // Indices output during last call to Render() = number of triangles * 3+int    MetricsRenderWindows;     // Number of visible windows+int    MetricsActiveWindows;     // Number of active windows+int    MetricsActiveAllocations; // Number of active allocations, updated by MemAlloc/MemFree based on current context. May be off if you have multiple imgui contexts.+ImVec2 MouseDelta;+-}
+ src/DearImGui/Raw/ListClipper.hs view
@@ -0,0 +1,149 @@+{-# LANGUAGE BlockArguments #-}+{-# LANGUAGE DuplicateRecordFields #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE LambdaCase #-}+{-# LANGUAGE NamedFieldPuns #-}+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE PatternSynonyms #-}+{-# LANGUAGE QuasiQuotes #-}+{-# LANGUAGE TemplateHaskell #-}+{-# LANGUAGE ViewPatterns #-}++{-| Helper: Manually clip large list of items.++If you are submitting lots of evenly spaced items and you have a random access to the list,+you can perform coarse clipping based on visibility to save yourself from processing those items at all.++The clipper calculates the range of visible items and advance the cursor to compensate for the non-visible items we have skipped.++Dear ImGui already clips items based on their bounds but it needs to measure text size to do so,+whereas manual coarse clipping before submission makes this cost and your own data fetching/submission cost almost null.++Usage:++@+clipper <- ListClipper.new+ListClipper.begin clipper 1000 -- We have 1000 elements, evenly spaced.+whileTrue (ListClipper.step clipper) $+  start <- ListClipper.displayStart clipper+  end <- ListClipper.displayEnd clipper+  for_ [start .. end] \ix ->+    ImGui.text $ "line number " <> show ix+@++Generally what happens is:++* Clipper lets you process the first element (DisplayStart = 0, DisplayEnd = 1) regardless of it being visible or not.+* User code submit one element.+* Clipper can measure the height of the first element+* Clipper calculate the actual range of elements to display based on the current clipping rectangle,+  position the cursor before the first visible element.+* User code submit visible elements.+-}++module DearImGui.Raw.ListClipper+  ( ListClipper+  , new+  , delete+  , begin+  , displayStart+  , displayEnd+  , step+  )+  where++import Control.Monad.IO.Class+  ( MonadIO, liftIO )+import Foreign hiding (new)+import Foreign.C+import System.IO.Unsafe (unsafePerformIO)++-- dear-imgui+import DearImGui.Context+  ( imguiContext )+import DearImGui.Structs+  ( ImGuiListClipper )++-- inline-c+import qualified Language.C.Inline as C++-- inline-c-cpp+import qualified Language.C.Inline.Cpp as Cpp++C.context (Cpp.cppCtx <> C.bsCtx <> imguiContext)+C.include "imgui.h"+Cpp.using "namespace ImGui"+++-- | @ImGuiListClipper@ object handle.+type ListClipper = Ptr ImGuiListClipper+++-- | Create a new 'ListClipper' instance.+new :: (MonadIO m) => m ListClipper+new = liftIO do+  [C.block|+    ImGuiListClipper* {+      return IM_NEW(ImGuiListClipper);+    }+  |]++-- | Destroy 'ListClipper' instance.+delete :: (MonadIO m) => ListClipper -> m ()+delete clipper = liftIO do+  [C.block|+    void {+      IM_DELETE($(ImGuiListClipper* clipper));+    }+  |]+++-- | ListClipper setup+--+-- @items_count@: Use 'maxBound' if you don't know how many items you have+-- (in which case the cursor won't be advanced in the final step).+--+-- @items_height@: Use -1.0f to be calculated automatically on first step.+-- Otherwise pass in the distance between your items, typically+-- 'getTextLineHeightWithSpacing' or 'getFrameHeightWithSpacing'.+--+-- Wraps @ListClipper::Begin()@.+begin :: (MonadIO m) => ListClipper -> CInt -> CFloat -> m ()+begin clipper items_count items_height = liftIO do+  [C.block|+    void {+      $(ImGuiListClipper* clipper)->Begin($(int items_count), $(float items_height));+    }+  |]++-- | An accessor for @ListClipper::Begin@+displayStart :: ListClipper -> CInt+displayStart clipper = unsafePerformIO do+  [C.exp|+    int {+      $(ImGuiListClipper* clipper)->DisplayStart+    }+  |]++-- | An accessor for @ListClipper::DisplayStart@+displayEnd :: ListClipper -> CInt+displayEnd clipper = unsafePerformIO+  [C.exp|+    int {+      $(ImGuiListClipper* clipper)->DisplayEnd+    }+  |]+++-- | Call until it returns 'False'.+--+-- The 'displayStart'/'displayEnd' fields will be set and you can process/draw those items.+--+-- Wraps @ListClipper::Step()@.+step :: (MonadIO m) => ListClipper -> m Bool+step clipper = liftIO do+  (0 /=) <$> [C.block|+    bool {+      return $(ImGuiListClipper* clipper)->Step();+    }+  |]
src/DearImGui/Structs.hs view
@@ -4,6 +4,8 @@ module DearImGui.Structs where  -- base+import Data.Word+  ( Word32 ) import Foreign   ( Storable(..), castPtr, plusPtr ) @@ -77,3 +79,12 @@  -- | Individual font handle. data ImFont++-- | Opaque DrawList handle.+data ImDrawList++-- | 'DearImGui.Raw.ListClipper.ListClipper' pointer tag.+data ImGuiListClipper++-- | 32-bit unsigned integer (often used to store packed colors).+type ImU32 = Word32