diff --git a/.gitmodules b/.gitmodules index 028a4fb..e19bc9e 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,3 +1,6 @@ [submodule "imgui"] path = imgui url = https://github.com/ocornut/imgui +[submodule "implot"] + path = implot + url = https://github.com/epezent/implot.git diff --git a/dear-imgui.cabal b/dear-imgui.cabal index 27032dc..a816a9c 100644 --- a/dear-imgui.cabal +++ b/dear-imgui.cabal @@ -22,7 +22,9 @@ extra-source-files: imgui/backends/*.h, imgui/backends/*.mm, imgui/imconfig.h, - imgui/LICENSE.txt + imgui/LICENSE.txt, + implot/*.h, + implot/LICENSE common exe-flags if flag(debug) @@ -140,6 +142,7 @@ library exposed-modules: DearImGui DearImGui.FontAtlas + DearImGui.Plot DearImGui.Raw DearImGui.Raw.DrawList DearImGui.Raw.Font @@ -147,6 +150,7 @@ library DearImGui.Raw.Font.GlyphRanges DearImGui.Raw.ListClipper DearImGui.Raw.IO + DearImGui.Raw.Plot other-modules: DearImGui.Context DearImGui.Enums @@ -158,10 +162,14 @@ library imgui/imgui_draw.cpp imgui/imgui_tables.cpp imgui/imgui_widgets.cpp + implot/implot.cpp + implot/implot_demo.cpp + implot/implot_items.cpp extra-libraries: stdc++ include-dirs: imgui + implot build-depends: dear-imgui-generator , containers diff --git a/generator/DearImGui/Generator.hs b/generator/DearImGui/Generator.hs index b9657dd..b3d5083 100644 --- a/generator/DearImGui/Generator.hs +++ b/generator/DearImGui/Generator.hs @@ -74,9 +74,15 @@ headers = $( do basicHeaders <- TH.runIO do headersPath <- canonicalizePath ( takeDirectory currentPath <> "/../../imgui/imgui.h" ) headersSource <- Text.readFile headersPath - tokens <- case tokenise headersSource of + tokensImGui <- case tokenise headersSource of Left err -> error ( "Couldn't tokenise Dear ImGui headers:\n\n" <> show err ) Right toks -> pure toks + headersPath <- canonicalizePath ( takeDirectory currentPath <> "/../../implot/implot.h" ) + headersSource <- Text.readFile headersPath + tokensImPlot <- case tokenise headersSource of + Left err -> error ( "Couldn't tokenise Dear ImPlot headers:\n\n" <> show err ) + Right toks -> pure toks + let tokens = tokensImGui<>tokensImPlot case Megaparsec.parse Parser.headers "" tokens of Left err -> do let diff --git a/implot b/implot new file mode 160000 index 0000000..b47c8ba --- /dev/null +++ b/implot @@ -0,0 +1 @@ +Subproject commit b47c8bacdbc78bc521691f70666f13924bb522ab diff --git a/src/DearImGui.hs b/src/DearImGui.hs index e4e15cc..71991cf 100644 --- a/src/DearImGui.hs +++ b/src/DearImGui.hs @@ -294,6 +294,9 @@ module DearImGui , Raw.getForegroundDrawList , Raw.imCol32 + -- * Plotting + , module DearImGui.Plot + -- * Types , module DearImGui.Enums , module DearImGui.Structs @@ -315,6 +318,7 @@ import System.IO -- dear-imgui import DearImGui.Enums import DearImGui.Structs +import DearImGui.Plot import qualified DearImGui.Raw as Raw import qualified DearImGui.Raw.Font as Raw.Font import qualified DearImGui.Raw.ListClipper as Raw.ListClipper diff --git a/src/DearImGui/Context.hs b/src/DearImGui/Context.hs index 1c91a60..cbb7c2e 100644 --- a/src/DearImGui/Context.hs +++ b/src/DearImGui/Context.hs @@ -43,3 +43,11 @@ imguiContext = mempty , ( TypeName "ImGuiListClipper", [t| ImGuiListClipper |] ) ] } + +implotContext :: Context +implotContext = mempty + { ctxTypesTable = + Map.fromList + [ ( TypeName "ImPlotContext", [t| ImPlotContext |] ) + ] + } diff --git a/src/DearImGui/Plot.hs b/src/DearImGui/Plot.hs new file mode 100644 index 0000000..3a4315b --- /dev/null +++ b/src/DearImGui/Plot.hs @@ -0,0 +1,71 @@ +{-# LANGUAGE BlockArguments #-} +{-# LANGUAGE DuplicateRecordFields #-} +{-# LANGUAGE FlexibleContexts #-} +{-# LANGUAGE FlexibleInstances #-} +{-# LANGUAGE LambdaCase #-} +{-# LANGUAGE MultiParamTypeClasses #-} +{-# LANGUAGE NamedFieldPuns #-} +{-# LANGUAGE OverloadedStrings #-} +{-# LANGUAGE PatternSynonyms #-} +{-# LANGUAGE QuasiQuotes #-} +{-# LANGUAGE TemplateHaskell #-} + +{-| +Module: DearImGui.Plot + +Main ImPlot module, exporting the functions to make plots happen in Gui. +-} + +module DearImGui.Plot + ( -- * Context Creation and Access + Raw.Plot.PlotContext(..) + , Raw.Plot.createPlotContext + , Raw.Plot.destroyPlotContext + , Raw.Plot.getCurrentPlotContext + , Raw.Plot.setCurrentPlotContext + + -- * Demo so you can play with all features + , Raw.Plot.showPlotDemoWindow + ) + where + +-- base +import Control.Monad + ( when ) +import Data.Bool +import Data.Foldable + ( foldl' ) +import Foreign +import Foreign.C +import qualified GHC.Foreign as Foreign +import System.IO + ( utf8 ) + +-- dear-imgui +import DearImGui.Enums +import DearImGui.Structs +import qualified DearImGui.Raw as Raw +import qualified DearImGui.Raw.Plot as Raw.Plot +import qualified DearImGui.Raw.Font as Raw.Font +import qualified DearImGui.Raw.ListClipper as Raw.ListClipper + +-- managed +import qualified Control.Monad.Managed as Managed + +-- StateVar +import Data.StateVar + ( HasGetter(get), HasSetter, ($=!) ) + +-- transformers +import Control.Monad.IO.Class + ( MonadIO, liftIO ) + +-- unliftio +import UnliftIO (MonadUnliftIO) +import UnliftIO.Exception (bracket, bracket_) + +-- vector +import qualified Data.Vector as V +import qualified Data.Vector.Storable as VS +import qualified Data.Vector.Unboxed as VU + diff --git a/src/DearImGui/Raw/Plot.hs b/src/DearImGui/Raw/Plot.hs new file mode 100644 index 0000000..ebdd5a4 --- /dev/null +++ b/src/DearImGui/Raw/Plot.hs @@ -0,0 +1,83 @@ +{-# LANGUAGE BlockArguments #-} +{-# LANGUAGE DuplicateRecordFields #-} +{-# LANGUAGE FlexibleContexts #-} +{-# LANGUAGE LambdaCase #-} +{-# LANGUAGE NamedFieldPuns #-} +{-# LANGUAGE OverloadedStrings #-} +{-# LANGUAGE PatternSynonyms #-} +{-# LANGUAGE QuasiQuotes #-} +{-# LANGUAGE TemplateHaskell #-} +{-# LANGUAGE ViewPatterns #-} + +{-| +Module: DearImGui.Raw.Plot + +Main ImPlot Raw module. +-} +module DearImGui.Raw.Plot + ( PlotContext(..) + , createPlotContext + , destroyPlotContext + , getCurrentPlotContext + , setCurrentPlotContext + + , showPlotDemoWindow + ) where + +-- base +import Control.Monad.IO.Class + ( MonadIO, liftIO ) +import Foreign +import Foreign.C +import System.IO.Unsafe + ( unsafePerformIO ) + +-- dear-imgui +import DearImGui.Context + ( imguiContext, implotContext ) +import DearImGui.Enums +import DearImGui.Structs +import DearImGui.Raw.DrawList (DrawList(..)) + +-- 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 <> implotContext) +C.include "imgui.h" +C.include "implot.h" +Cpp.using "namespace ImPlot" + + +-- | Wraps @ImPlotContext*@. +newtype PlotContext = PlotContext (Ptr ImPlotContext) + + +-- | Wraps @ImPlot::CreateContext()@. +createPlotContext :: (MonadIO m) => m PlotContext +createPlotContext = liftIO do + PlotContext <$> [C.exp| ImPlotContext* { CreateContext() } |] + +-- | Wraps @ImPlot::DestroyPlotContext()@. +destroyPlotContext :: (MonadIO m) => PlotContext -> m () +destroyPlotContext (PlotContext contextPtr) = liftIO do + [C.exp| void { DestroyContext($(ImPlotContext* contextPtr)); } |] + +-- | Wraps @ImPlot::GetCurrentPlotContext()@. +getCurrentPlotContext :: MonadIO m => m PlotContext +getCurrentPlotContext = liftIO do + PlotContext <$> [C.exp| ImPlotContext* { GetCurrentContext() } |] + + +-- | Wraps @ImPlot::SetCurrentPlotContext()@. +setCurrentPlotContext :: MonadIO m => PlotContext -> m () +setCurrentPlotContext (PlotContext contextPtr) = liftIO do + [C.exp| void { SetCurrentContext($(ImPlotContext* contextPtr)) } |] + +-- | Create demo window. Demonstrate most ImGui features. Call this to learn +-- about the library! Try to make it always available in your application! +showPlotDemoWindow :: (MonadIO m) => m () +showPlotDemoWindow = liftIO do + [C.exp| void { ShowDemoWindow(); } |] diff --git a/src/DearImGui/Structs.hs b/src/DearImGui/Structs.hs index f4acfe7..72071f0 100644 --- a/src/DearImGui/Structs.hs +++ b/src/DearImGui/Structs.hs @@ -107,3 +107,23 @@ type ImWchar = Word32 #else type ImWchar = Word16 #endif + +-------------------------------------------------------------------------------- + +-- | DearImPlot context handle +data ImPlotContext + +-- | Double precision version of ImVec2 used by ImPlot. Extensible by end users +data ImPlotPoint + +-- | Range defined by a min/max value. +data ImPlotRange + +-- | Combination of two range limits for X and Y axes. Also an AABB defined by Min()/Max(). +data ImPlotRect + +-- | Plot style structure +data ImPlotStyle + +-- | Input mapping structure. Default values listed. See also MapInputDefault, MapInputReverse. +data ImPlotInputMap