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 +4/−0
- Main.hs +16/−0
- README.md +22/−12
- dear-imgui.cabal +47/−13
- examples/Readme.hs +15/−5
- examples/sdl/Image.hs +20/−6
- src/DearImGui.hs +106/−4
- src/DearImGui/Context.hs +3/−0
- src/DearImGui/Raw.hs +79/−0
- src/DearImGui/Raw/DrawList.hs +742/−0
- src/DearImGui/Raw/IO.hs +137/−0
- src/DearImGui/Raw/ListClipper.hs +149/−0
- src/DearImGui/Structs.hs +11/−0
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