7 Commits
v1.0.1 ... args

15 changed files with 902 additions and 2541 deletions

View File

@ -1,12 +0,0 @@
# Changelog for dear-imgui
## [1.0.1] Initial Hackage release
- Fixed missing headers in source dist.
## [1.0.0]
Initial Hackage release based on 1.83.
[1.0.0]: https://github.com/haskell-game/dear-imgui.hs/tree/v1.0.0
[1.0.0]: https://github.com/haskell-game/dear-imgui.hs/tree/v1.0.1

View File

@ -1,4 +1,5 @@
{-# LANGUAGE BlockArguments #-} {-# LANGUAGE BlockArguments #-}
{-# LANGUAGE DuplicateRecordFields #-}
{-# LANGUAGE LambdaCase #-} {-# LANGUAGE LambdaCase #-}
{-# LANGUAGE NamedFieldPuns #-} {-# LANGUAGE NamedFieldPuns #-}
{-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE OverloadedStrings #-}
@ -74,7 +75,7 @@ loop w checked color slider r pos size' selected tab1Ref tab2Ref = do
setNextWindowBgAlpha 0.42 setNextWindowBgAlpha 0.42
begin "My Window" begin Begin{ name = "My Window", isOpen = Nothing }
text "Hello!" text "Hello!"
@ -112,7 +113,7 @@ loop w checked color slider r pos size' selected tab1Ref tab2Ref = do
sameLine >> arrowButton "Arrow" ImGuiDir_Up sameLine >> arrowButton "Arrow" ImGuiDir_Up
sameLine >> checkbox "Check!" checked >>= \case sameLine >> checkbox Checkbox{ label = "Check!", checked = toStateVar checked } >>= \case
True -> readIORef checked >>= print True -> readIORef checked >>= print
False -> return () False -> return ()

View File

@ -25,7 +25,7 @@ OpenGL:
``` ```
package dear-imgui package dear-imgui
flags: +sdl +opengl3 flags: +sdl +opengl
``` ```
With this done, the following module is the "Hello, World!" of ImGui: With this done, the following module is the "Hello, World!" of ImGui:

View File

@ -1,3 +1,3 @@
packages: *.cabal packages: *.cabal
package dear-imgui package dear-imgui
flags: +sdl2 +glfw +opengl2 +opengl3 +vulkan +examples flags: +sdl2 +glfw +opengl2 +opengl3 +vulkan

View File

@ -1,32 +1,9 @@
cabal-version: 3.0 cabal-version: 3.0
name: dear-imgui name: dear-imgui
version: 1.0.1 version: 1.0.0
author: Oliver Charles
maintainer: ollie@ocharles.org.uk, aenor.realm@gmail.com
license: BSD-3-Clause
category: Graphics
synopsis: Haskell bindings for Dear ImGui.
description:
The package supports multiple rendering backends.
Set package flags according to your needs.
build-type: Simple build-type: Simple
extra-source-files: data-files:
README.md, imgui/imgui.h
ChangeLog.md
extra-source-files:
imgui/*.h,
imgui/backends/*.h,
imgui/backends/*.mm,
imgui/imconfig.h,
imgui/LICENSE.txt
source-repository head
type: git
location: https://github.com/haskell-game/dear-imgui.hs
flag opengl2 flag opengl2
description: description:
@ -34,7 +11,7 @@ flag opengl2
default: default:
False False
manual: manual:
True False
flag opengl3 flag opengl3
description: description:
@ -42,7 +19,7 @@ flag opengl3
default: default:
True True
manual: manual:
True False
flag vulkan flag vulkan
description: description:
@ -58,7 +35,7 @@ flag sdl
default: default:
True True
manual: manual:
True False
flag glfw flag glfw
description: description:
@ -68,14 +45,6 @@ flag glfw
manual: manual:
True True
flag examples
description:
Build executable examples.
default:
False
manual:
True
common common common common
build-depends: build-depends:
base base
@ -91,7 +60,6 @@ library
src src
exposed-modules: exposed-modules:
DearImGui DearImGui
DearImGui.Raw
other-modules: other-modules:
DearImGui.Context DearImGui.Context
DearImGui.Enums DearImGui.Enums
@ -115,7 +83,6 @@ library
, inline-c , inline-c
, inline-c-cpp , inline-c-cpp
, StateVar , StateVar
, unliftio
if flag(opengl2) if flag(opengl2)
exposed-modules: exposed-modules:
@ -130,8 +97,16 @@ library
DearImGui.OpenGL3 DearImGui.OpenGL3
cxx-sources: cxx-sources:
imgui/backends/imgui_impl_opengl3.cpp imgui/backends/imgui_impl_opengl3.cpp
pkgconfig-depends: if os(windows)
glew buildable:
False
else
if os(darwin)
buildable:
False
else
pkgconfig-depends:
glew
if flag(vulkan) if flag(vulkan)
exposed-modules: exposed-modules:
@ -208,20 +183,16 @@ library dear-imgui-generator
build-depends: build-depends:
template-haskell template-haskell
>= 2.15 && < 2.19 >= 2.15 && < 2.19
, containers
^>= 0.6.2.1
, directory , directory
>= 1.3 && < 1.4 >= 1.3 && < 1.4
, filepath , filepath
>= 1.4 && < 1.5 >= 1.4 && < 1.5
, inline-c
>= 0.9.0.0 && < 0.10
, megaparsec , megaparsec
>= 9.0 && < 9.1 >= 9.0 && < 9.1
, parser-combinators , parser-combinators
>= 1.2.0 && < 1.3 >= 1.2.0 && < 1.3
, scientific , scientific
>= 0.3.6.2 && < 0.3.8 >= 0.3.6.2 && < 0.3.7
, text , text
>= 1.2.4 && < 1.3 >= 1.2.4 && < 1.3
, th-lift , th-lift
@ -229,35 +200,27 @@ library dear-imgui-generator
, transformers , transformers
>= 0.5.6 && < 0.6 >= 0.5.6 && < 0.6
, unordered-containers , unordered-containers
>= 0.2.11 && < 0.2.15 >= 0.2.11 && < 0.2.14
executable test executable test
import: common import: common
main-is: Main.hs main-is: Main.hs
default-language: Haskell2010 default-language: Haskell2010
build-depends: base, sdl2, gl, dear-imgui
ghc-options: -Wall ghc-options: -Wall
if (!flag(examples) || !flag(sdl) || !flag(opengl2))
buildable: False
else
build-depends: base, sdl2, gl, dear-imgui
executable glfw executable glfw
main-is: Main.hs main-is: Main.hs
hs-source-dirs: examples/glfw hs-source-dirs: examples/glfw
default-language: Haskell2010 default-language: Haskell2010
build-depends: base, GLFW-b, gl, dear-imgui, managed
ghc-options: -Wall ghc-options: -Wall
if (!flag(examples) || !flag(glfw) || !flag(opengl2))
buildable: False
else
build-depends: base, GLFW-b, gl, dear-imgui, managed
executable readme executable readme
import: common import: common
main-is: Readme.hs main-is: Readme.hs
hs-source-dirs: examples hs-source-dirs: examples
build-depends: sdl2, gl, dear-imgui, managed build-depends: sdl2, gl, dear-imgui, managed
if (!flag(examples) || !flag(sdl) || !flag(opengl2))
buildable: False
executable vulkan executable vulkan
import: common import: common
@ -265,33 +228,30 @@ executable vulkan
other-modules: Attachments, Backend, Input, Util other-modules: Attachments, Backend, Input, Util
hs-source-dirs: examples/vulkan hs-source-dirs: examples/vulkan
default-language: Haskell2010 default-language: Haskell2010
build-depends:
dear-imgui
, bytestring
>= 0.10.10.0 && < 0.12
, containers
^>= 0.6.2.1
, logging-effect
^>= 1.3.12
, resourcet
^>= 1.2.4.2
, sdl2
^>= 2.5.3.0
, text-short
^>= 0.1.3
, transformers
^>= 0.5.6.2
, unliftio
>= 0.2.13 && < 0.2.15
, unliftio-core
^>= 0.2.0.1
, vector
^>= 0.12.1.2
, vulkan
^>= 3.9
, vulkan-utils
^>= 0.4.1
ghc-options: -Wall ghc-options: -Wall
if (!flag(examples) || !flag(sdl) || !flag(vulkan))
buildable: False
else
build-depends:
dear-imgui
, bytestring
>= 0.10.10.0 && < 0.12
, containers
^>= 0.6.2.1
, logging-effect
^>= 1.3.12
, resourcet
^>= 1.2.4.2
, sdl2
^>= 2.5.3.0
, text-short
^>= 0.1.3
, transformers
^>= 0.5.6.2
, unliftio
>= 0.2.13 && < 0.2.19
, unliftio-core
^>= 0.2.0.1
, vector
^>= 0.12.1.2
, vulkan
^>= 3.9
, vulkan-utils
^>= 0.4.1

View File

@ -55,7 +55,7 @@ mainLoop w = do
newFrame newFrame
-- Build the GUI -- Build the GUI
withWindowOpen "Hello, ImGui!" do bracket_ (begin Begin{ name = "Hello, ImGui!", isOpen = Nothing }) end do
-- Add a text widget -- Add a text widget
text "Hello, ImGui!" text "Hello, ImGui!"

View File

@ -59,7 +59,7 @@ mainLoop win = do
newFrame newFrame
-- Build the GUI -- Build the GUI
bracket_ (begin "Hello, ImGui!") end do bracket_ (begin Begin{ name = "Hello, ImGui!", isOpen = Nothing }) end do
-- Add a text widget -- Add a text widget
text "Hello, ImGui!" text "Hello, ImGui!"

View File

@ -6,33 +6,21 @@
{-# LANGUAGE TemplateHaskell #-} {-# LANGUAGE TemplateHaskell #-}
module DearImGui.Generator module DearImGui.Generator
( declareEnumerations, enumerationsTypesTable ) ( declareEnumerations )
where where
-- base -- base
import Control.Arrow
( second )
import Data.Coerce import Data.Coerce
( coerce ) ( coerce )
import Data.Bits import Data.Bits
( Bits ) ( Bits )
import Data.Foldable import Data.Foldable
( toList ) ( toList )
import qualified Data.List.NonEmpty as NonEmpty
( head )
import Data.String
( fromString )
import Data.Traversable import Data.Traversable
( for ) ( for )
import Foreign.Storable import Foreign.Storable
( Storable ) ( Storable )
-- containers
import Data.Map.Strict
( Map )
import qualified Data.Map.Strict as Map
( fromList )
-- directory -- directory
import System.Directory import System.Directory
( canonicalizePath ) ( canonicalizePath )
@ -41,12 +29,9 @@ import System.Directory
import System.FilePath import System.FilePath
( takeDirectory ) ( takeDirectory )
-- inline-c
import qualified Language.C.Types as InlineC
( TypeSpecifier(TypeName) )
-- megaparsec -- megaparsec
import qualified Text.Megaparsec as Megaparsec import qualified Text.Megaparsec as Megaparsec
( ParseErrorBundle(bundleErrors), parse, parseErrorPretty )
-- template-haskell -- template-haskell
import qualified Language.Haskell.TH as TH import qualified Language.Haskell.TH as TH
@ -62,68 +47,53 @@ import qualified Data.Text.IO as Text
import qualified DearImGui.Generator.Parser as Parser import qualified DearImGui.Generator.Parser as Parser
( headers ) ( headers )
import DearImGui.Generator.Tokeniser import DearImGui.Generator.Tokeniser
( Tok, tokenise ) ( tokenise )
import DearImGui.Generator.Types import DearImGui.Generator.Types
( Comment(..), Enumeration(..), Headers(..) ( Comment(..), Enumeration(..), Headers(..) )
, generateNames
)
-------------------------------------------------------------------------------- --------------------------------------------------------------------------------
-- Obtaining parsed header data. -- Obtaining parsed header data.
headers :: Headers ( TH.Name, TH.Name ) headers :: Headers
headers = $( do headers = $( do
currentPath <- TH.loc_filename <$> TH.location currentPath <- TH.loc_filename <$> TH.location
basicHeaders <- TH.runIO do TH.lift =<< TH.runIO do
headersPath <- canonicalizePath ( takeDirectory currentPath <> "/../../imgui/imgui.h" ) headersPath <- canonicalizePath ( takeDirectory currentPath <> "/../../imgui/imgui.h" )
headersSource <- Text.readFile headersPath headersSource <- Text.readFile headersPath
tokens <- case tokenise headersSource of tokens <- case tokenise headersSource of
Left err -> error ( "Couldn't tokenise Dear ImGui headers:\n\n" <> show err ) Left err -> error ( "Couldn't tokenise Dear ImGui headers:\n\n" <> show err )
Right toks -> pure toks Right toks -> pure toks
case Megaparsec.parse Parser.headers "" tokens of case Megaparsec.parse Parser.headers "" tokens of
Left err -> do Left err -> error $
let "Couldn't parse Dear ImGui headers:\n\n" <>
errorPos :: Int ( unlines ( map Megaparsec.parseErrorPretty . toList $ Megaparsec.bundleErrors err ) )
errorPos = Megaparsec.errorOffset . NonEmpty.head $ Megaparsec.bundleErrors err
prev, rest :: [ Tok ]
( prev, rest ) = second ( take 15 ) . splitAt 5 . drop ( errorPos - 5 ) $ tokens
error $
"Couldn't parse Dear ImGui headers:\n\n" <>
( unlines ( map Megaparsec.parseErrorPretty . toList $ Megaparsec.bundleErrors err ) ) <> "\n" <>
( unlines ( map show prev ) <> "\n\n" <> unlines ( map show rest ) )
Right res -> pure res Right res -> pure res
TH.lift $ generateNames basicHeaders
) )
-------------------------------------------------------------------------------- --------------------------------------------------------------------------------
-- Generating TH splices. -- Generating TH splices.
enumerationsTypesTable :: Map InlineC.TypeSpecifier ( TH.Q TH.Type )
enumerationsTypesTable = Map.fromList . map mkTypePair $ enums headers
where
mkTypePair :: Enumeration ( TH.Name, TH.Name ) -> ( InlineC.TypeSpecifier, TH.Q TH.Type )
mkTypePair ( Enumeration { enumName, enumTypeName } ) =
( InlineC.TypeName $ fromString ( Text.unpack enumName )
, TH.conT ( fst $ enumTypeName )
)
declareEnumerations :: TH.Name -> TH.Name -> TH.Q [ TH.Dec ] declareEnumerations :: TH.Name -> TH.Name -> TH.Q [ TH.Dec ]
declareEnumerations finiteEnumName countName = do declareEnumerations finiteEnumName countName = do
concat <$> mapM ( declareEnumeration finiteEnumName countName ) ( enums headers ) concat <$> mapM ( declareEnumeration finiteEnumName countName ) ( enums headers )
declareEnumeration :: TH.Name -> TH.Name -> Enumeration ( TH.Name, TH.Name ) -> TH.Q [ TH.Dec ] declareEnumeration :: TH.Name -> TH.Name -> Enumeration -> TH.Q [ TH.Dec ]
declareEnumeration finiteEnumName countName ( Enumeration {..} ) = do declareEnumeration finiteEnumName countName ( Enumeration {..} ) = do
let let
tyName, conName :: TH.Name enumNameStr :: String
( tyName, conName ) = enumTypeName enumNameStr = Text.unpack enumName
isFlagEnum :: Bool isFlagEnum :: Bool
isFlagEnum = "Flags" `Text.isInfixOf` enumName isFlagEnum = "Flags" `Text.isInfixOf` enumName
tyName <- TH.newName enumNameStr
conName <- TH.newName enumNameStr
let
newtypeCon :: TH.Q TH.Con newtypeCon :: TH.Q TH.Con
newtypeCon = newtypeCon =
TH.normalC conName TH.normalC conName
[ TH.bangType [ TH.bangType
( TH.bang TH.noSourceUnpackedness TH.noSourceStrictness ) ( TH.bang TH.noSourceUnpackedness TH.noSourceStrictness )
( TH.conT underlyingType ) ( TH.conT enumType )
] ]
classes :: [ TH.Q TH.Type ] classes :: [ TH.Q TH.Type ]
classes classes
@ -133,15 +103,14 @@ declareEnumeration finiteEnumName countName ( Enumeration {..} ) = do
= map TH.conT [ ''Eq, ''Ord, ''Storable ] = map TH.conT [ ''Eq, ''Ord, ''Storable ]
derivClause :: TH.Q TH.DerivClause derivClause :: TH.Q TH.DerivClause
derivClause = TH.derivClause ( Just TH.NewtypeStrategy ) classes derivClause = TH.derivClause ( Just TH.NewtypeStrategy ) classes
newtypeDecl <- newtypeDecl <-
#if MIN_VERSION_template_haskell(2,18,0) #if MIN_VERSION_base(4,16,0)
( if null docs ( if null docs
then TH.newtypeD then TH.newtypeD
else else
\ ctx name bndrs kd con derivs -> \ ctx name bndrs kd con derivs ->
TH.newtypeD_doc ctx name ( fmap pure bndrs ) ( fmap pure kd ) ( con, Nothing, [] ) derivs TH.newtypeD_doc ctx name ( fmap pure bndrs ) ( fmap pure kd ) ( con, "", [] ) derivs
( Just . Text.unpack . Text.unlines . coerce $ docs ) ( Text.unpack . Text.unlines . coerce $ docs )
) )
#else #else
TH.newtypeD TH.newtypeD
@ -168,13 +137,13 @@ declareEnumeration finiteEnumName countName ( Enumeration {..} ) = do
patName <- TH.newName patNameStr patName <- TH.newName patNameStr
patSynSig <- TH.patSynSigD patName ( TH.conT tyName ) patSynSig <- TH.patSynSigD patName ( TH.conT tyName )
pat <- pat <-
#if MIN_VERSION_template_haskell(2,18,0) #if MIN_VERSION_base(4,16,0)
( if Text.null patDoc ( if Text.null patDoc
then TH.patSynD then TH.patSynD
else else
\ nm args dir pat -> \ nm args dir pat ->
TH.patSynD_doc nm args dir pat TH.patSynD_doc nm args dir pat
( Just $ Text.unpack patDoc ) [] ( Text.unpack patDoc ) []
) )
#else #else
TH.patSynD TH.patSynD

View File

@ -111,46 +111,27 @@ instance ShowErrorComponent CustomParseError where
-------------------------------------------------------------------------------- --------------------------------------------------------------------------------
-- Parsing headers. -- Parsing headers.
headers :: MonadParsec CustomParseError [Tok] m => m ( Headers () ) headers :: MonadParsec CustomParseError [Tok] m => m Headers
headers = do headers = do
_ <- skipManyTill anySingle ( namedSection "Header mess" ) _ <- skipManyTill anySingle ( namedSection "Header mess" )
_ <- skipManyTill anySingle ( namedSection "Forward declarations" ) _ <- skipManyTill anySingle ( namedSection "Forward declarations" )
( _structNames, enumNamesAndTypes ) <- forwardDeclarations ( _structNames, enumNamesAndTypes ) <- forwardDeclarations
_ <- skipManyTill anySingle ( namedSection "Dear ImGui end-user API functions" ) _ <- skipManyTill anySingle ( namedSection "Dear ImGui end-user API functions" )
_ <- skipManyTill anySingle ( namedSection "Flags & Enumerations" ) _ <- skipManyTill anySingle ( namedSection "Flags & Enumerations" )
( _defines, basicEnums ) <- partitionEithers <$> ( _defines, enums ) <- partitionEithers <$>
manyTill manyTill
( ( Left <$> try ignoreDefine ) ( ( Left <$> try ignoreDefine )
<|> ( Right <$> enumeration enumNamesAndTypes ) <|> ( Right <$> enumeration enumNamesAndTypes )
) )
( namedSection "Helpers: Memory allocations macros, ImVector<>" ) ( namedSection "Helpers: Memory allocations macros, ImVector<>" )
_ <- skipManyTill anySingle ( namedSection "ImGuiStyle" ) _ <- skipManyTill anySingle ( namedSection "ImGuiStyle" )
_ <- skipManyTill anySingle ( namedSection "ImGuiIO" ) _ <- skipManyTill anySingle ( namedSection "ImGuiIO" )
_ <- skipManyTill anySingle ( namedSection "Misc data structures" ) _ <- skipManyTill anySingle ( namedSection "Misc data structures" )
_ <- skipManyTill anySingle ( namedSection "Obsolete functions" )
_ <- skipManyTill anySingle ( namedSection "Helpers" )
_ <- skipManyTill anySingle ( namedSection "Drawing API" )
_ <- skipManyTill anySingle ( namedSection "Font API" )
_ <- skipManyTill anySingle ( namedSection "Helpers (ImGuiOnceUponAFrame, ImGuiTextFilter, ImGuiTextBuffer, ImGuiStorage, ImGuiListClipper, ImColor)" )
_ <- skipManyTill anySingle ( namedSection "Drawing API (ImDrawCmd, ImDrawIdx, ImDrawVert, ImDrawChannel, ImDrawListSplitter, ImDrawListFlags, ImDrawList, ImDrawData)" )
skipManyTill anySingle ( try . lookAhead $ many comment *> keyword "enum" )
drawingEnums <- many ( enumeration enumNamesAndTypes )
_ <- skipManyTill anySingle ( namedSection "Font API (ImFontConfig, ImFontGlyph, ImFontAtlasFlags, ImFontAtlas, ImFontGlyphRangesBuilder, ImFont)" )
skipManyTill anySingle ( try . lookAhead $ many comment *> keyword "enum" )
fontEnums <- many ( enumeration enumNamesAndTypes )
_ <- skipManyTill anySingle ( namedSection "Viewports" )
_ <- skipManyTill anySingle ( namedSection "Obsolete functions and types" )
let
enums :: [ Enumeration () ]
enums = basicEnums <> drawingEnums <> fontEnums
pure ( Headers { enums } ) pure ( Headers { enums } )
-------------------------------------------------------------------------------- --------------------------------------------------------------------------------
@ -170,7 +151,7 @@ forwardDeclarations = do
_ <- many comment _ <- many comment
enums <- many do enums <- many do
keyword "typedef" keyword "typedef"
ty <- cTypeName ty <- enumTypeName
enumName <- identifier enumName <- identifier
reservedSymbol ';' reservedSymbol ';'
doc <- commentText <$> comment doc <- commentText <$> comment
@ -178,8 +159,8 @@ forwardDeclarations = do
-- Stopping after simple structs and enums for now. -- Stopping after simple structs and enums for now.
pure ( HashMap.fromList structs, HashMap.fromList enums ) pure ( HashMap.fromList structs, HashMap.fromList enums )
cTypeName :: MonadParsec e [Tok] m => m TH.Name enumTypeName :: MonadParsec e [Tok] m => m TH.Name
cTypeName = keyword "int" $> ''CInt enumTypeName = keyword "int" $> ''CInt
-------------------------------------------------------------------------------- --------------------------------------------------------------------------------
-- Parsing enumerations. -- Parsing enumerations.
@ -191,19 +172,15 @@ data EnumState = EnumState
, hasExplicitCount :: Bool , hasExplicitCount :: Bool
} }
enumeration :: MonadParsec CustomParseError [Tok] m => HashMap Text ( TH.Name, Comment ) -> m ( Enumeration () ) enumeration :: MonadParsec CustomParseError [Tok] m => HashMap Text ( TH.Name, Comment ) -> m Enumeration
enumeration enumNamesAndTypes = do enumeration enumNamesAndTypes = do
inlineDocs <- try do inlineDocs <- many comment
inlineDocs <- many comment keyword "enum"
keyword "enum"
pure inlineDocs
fullEnumName <- identifier fullEnumName <- identifier
let let
enumName :: Text enumName :: Text
enumName = Text.dropWhileEnd ( == '_' ) fullEnumName enumName = Text.dropWhileEnd ( == '_' ) fullEnumName
enumTypeName :: () ( enumType, forwardDoc ) <- case HashMap.lookup enumName enumNamesAndTypes of
enumTypeName = ()
( underlyingType, forwardDoc ) <- case HashMap.lookup enumName enumNamesAndTypes of
Just res -> pure res Just res -> pure res
Nothing -> customFailure ( MissingForwardDeclaration { enumName } ) Nothing -> customFailure ( MissingForwardDeclaration { enumName } )
let let
@ -245,11 +222,11 @@ patternNameAndValue
patternNameAndValue enumName = patternNameAndValue enumName =
try do try do
sz <- count sz <- count
modify' ( \ ( EnumState {..} ) -> EnumState { enumSize = sz, hasExplicitCount = True, .. } ) modify' ( ( \ st -> st { enumSize = sz, hasExplicitCount = True } ) :: EnumState -> EnumState )
pure Nothing pure Nothing
<|> do <|> do
pat@( _, val ) <- value pat@( _, val ) <- value
modify' ( \ ( EnumState {..} ) -> EnumState { enumSize = enumSize + 1, currEnumTag = val + 1, .. } ) modify' ( \ st -> st { enumSize = ( enumSize :: EnumState -> Integer ) st + 1, currEnumTag = val + 1} )
pure ( Just pat ) pure ( Just pat )
where where
count :: StateT EnumState m Integer count :: StateT EnumState m Integer

View File

@ -1,27 +1,19 @@
{-# LANGUAGE BangPatterns #-} {-# LANGUAGE BangPatterns #-}
{-# LANGUAGE BlockArguments #-}
{-# LANGUAGE DeriveLift #-} {-# LANGUAGE DeriveLift #-}
{-# LANGUAGE DerivingStrategies #-} {-# LANGUAGE DerivingStrategies #-}
{-# LANGUAGE GeneralizedNewtypeDeriving #-} {-# LANGUAGE GeneralizedNewtypeDeriving #-}
{-# LANGUAGE NamedFieldPuns #-}
{-# LANGUAGE RecordWildCards #-} {-# LANGUAGE RecordWildCards #-}
{-# LANGUAGE TemplateHaskellQuotes #-} {-# LANGUAGE TemplateHaskellQuotes #-}
module DearImGui.Generator.Types where module DearImGui.Generator.Types where
-- base
import Data.Functor
( (<&>) )
-- template-haskell -- template-haskell
import qualified Language.Haskell.TH as TH
import qualified Language.Haskell.TH.Syntax as TH import qualified Language.Haskell.TH.Syntax as TH
( Lift(..), Name(..) )
-- text -- text
import Data.Text import Data.Text
( Text ) ( Text )
import qualified Data.Text as Text
( unpack )
-- th-lift -- th-lift
import Language.Haskell.TH.Lift import Language.Haskell.TH.Lift
@ -33,33 +25,18 @@ newtype Comment = CommentText { commentText :: Text }
deriving stock ( Show, TH.Lift ) deriving stock ( Show, TH.Lift )
deriving newtype ( Eq, Ord ) deriving newtype ( Eq, Ord )
data Enumeration typeName data Enumeration
= Enumeration = Enumeration
{ docs :: ![Comment] { docs :: ![Comment]
, enumName :: !Text , enumName :: !Text
, enumTypeName :: !typeName
, enumSize :: !Integer , enumSize :: !Integer
, underlyingType :: !TH.Name , enumType :: !TH.Name
, hasExplicitCount :: !Bool , hasExplicitCount :: !Bool
, patterns :: [ ( Text, Integer, Comment ) ] , patterns :: [ ( Text, Integer, Comment ) ]
} }
deriving stock ( Show, TH.Lift ) deriving stock ( Show, TH.Lift )
data Headers typeName data Headers
= Headers = Headers
{ enums :: [ Enumeration typeName ] } { enums :: [ Enumeration ] }
deriving stock ( Show, TH.Lift ) deriving stock ( Show, TH.Lift )
generateNames :: Headers () -> Headers ( TH.Name, TH.Name )
generateNames ( Headers { enums = basicEnums } ) = Headers { enums = namedEnums }
where
namedEnums :: [ Enumeration ( TH.Name, TH.Name ) ]
namedEnums = basicEnums <&> \ enum@( Enumeration { enumName } ) ->
let
enumNameStr :: String
enumNameStr = Text.unpack enumName
tyName, conName :: TH.Name
tyName = TH.mkName enumNameStr
conName = TH.mkName enumNameStr
in
enum { enumTypeName = ( tyName, conName ) }

2
imgui

Submodule imgui updated: ad5d1a8429...58075c4414

File diff suppressed because it is too large Load Diff

View File

@ -18,19 +18,21 @@ import Language.C.Types
( pattern TypeName ) ( pattern TypeName )
-- dear-imgui -- dear-imgui
import DearImGui.Enums
import DearImGui.Structs import DearImGui.Structs
-- dear-imgui-generator
import DearImGui.Generator
( enumerationsTypesTable )
-------------------------------------------------------------------------------- --------------------------------------------------------------------------------
imguiContext :: Context imguiContext :: Context
imguiContext = mempty imguiContext = mempty
{ ctxTypesTable = enumerationsTypesTable <> { ctxTypesTable = Map.fromList
Map.fromList [ ( TypeName "ImGuiCol" , [t| ImGuiCol |] )
[ ( TypeName "ImVec2", [t| ImVec2 |] ) , ( TypeName "ImGuiCond", [t| ImGuiCond |] )
, ( TypeName "ImGuiDir" , [t| ImGuiDir |] )
, ( TypeName "ImGuiStyleVar" , [t| ImGuiStyleVar |] )
, ( TypeName "ImGuiTabBarFlags" , [t| ImGuiTabBarFlags |] )
, ( TypeName "ImGuiTabItemFlags", [t| ImGuiTabItemFlags |] )
, ( TypeName "ImVec2", [t| ImVec2 |] )
, ( TypeName "ImVec3", [t| ImVec3 |] ) , ( TypeName "ImVec3", [t| ImVec3 |] )
, ( TypeName "ImVec4", [t| ImVec4 |] ) , ( TypeName "ImVec4", [t| ImVec4 |] )
] ]

File diff suppressed because it is too large Load Diff

View File

@ -12,8 +12,6 @@ Vulkan backend for Dear ImGui.
module DearImGui.Vulkan module DearImGui.Vulkan
( InitInfo(..) ( InitInfo(..)
, withVulkan , withVulkan
, vulkanInit
, vulkanShutdown
, vulkanNewFrame , vulkanNewFrame
, vulkanRenderDrawData , vulkanRenderDrawData
, vulkanCreateFontsTexture , vulkanCreateFontsTexture
@ -30,7 +28,7 @@ import Data.Word
import Foreign.Marshal.Alloc import Foreign.Marshal.Alloc
( alloca ) ( alloca )
import Foreign.Ptr import Foreign.Ptr
( FunPtr, Ptr, freeHaskellFunPtr, nullPtr ) ( Ptr, freeHaskellFunPtr, nullPtr )
import Foreign.Storable import Foreign.Storable
( Storable(poke) ) ( Storable(poke) )
@ -85,18 +83,7 @@ data InitInfo =
-- | Wraps @ImGui_ImplVulkan_Init@ and @ImGui_ImplVulkan_Shutdown@. -- | Wraps @ImGui_ImplVulkan_Init@ and @ImGui_ImplVulkan_Shutdown@.
withVulkan :: MonadUnliftIO m => InitInfo -> Vulkan.RenderPass -> ( Bool -> m a ) -> m a withVulkan :: MonadUnliftIO m => InitInfo -> Vulkan.RenderPass -> ( Bool -> m a ) -> m a
withVulkan initInfo renderPass action = withVulkan ( InitInfo {..} ) renderPass action = do
bracket
( vulkanInit initInfo renderPass )
vulkanShutdown
( \ ( _, initResult ) -> action initResult )
-- | Wraps @ImGui_ImplVulkan_Init@.
--
-- Use 'vulkanShutdown' to clean up on shutdown.
-- Prefer using 'withVulkan' when possible, as it automatically handles cleanup.
vulkanInit :: MonadIO m => InitInfo -> Vulkan.RenderPass -> m (FunPtr (Vulkan.Result -> IO ()), Bool)
vulkanInit ( InitInfo {..} ) renderPass = do
let let
instancePtr :: Ptr Vulkan.Instance_T instancePtr :: Ptr Vulkan.Instance_T
instancePtr = Vulkan.instanceHandle instance' instancePtr = Vulkan.instanceHandle instance'
@ -110,39 +97,38 @@ vulkanInit ( InitInfo {..} ) renderPass = do
withCallbacks f = case mbAllocator of withCallbacks f = case mbAllocator of
Nothing -> f nullPtr Nothing -> f nullPtr
Just callbacks -> alloca ( \ ptr -> poke ptr callbacks *> f ptr ) Just callbacks -> alloca ( \ ptr -> poke ptr callbacks *> f ptr )
liftIO do bracket
checkResultFunPtr <- $( C.mkFunPtr [t| Vulkan.Result -> IO () |] ) checkResult ( liftIO do
initResult <- withCallbacks \ callbacksPtr -> checkResultFunPtr <- $( C.mkFunPtr [t| Vulkan.Result -> IO () |] ) checkResult
[C.block| bool { initResult <- withCallbacks \ callbacksPtr ->
ImGui_ImplVulkan_InitInfo initInfo; [C.block| bool {
VkInstance instance = { $( VkInstance_T* instancePtr ) }; ImGui_ImplVulkan_InitInfo initInfo;
initInfo.Instance = instance; VkInstance instance = { $( VkInstance_T* instancePtr ) };
VkPhysicalDevice physicalDevice = { $( VkPhysicalDevice_T* physicalDevicePtr ) }; initInfo.Instance = instance;
initInfo.PhysicalDevice = physicalDevice; VkPhysicalDevice physicalDevice = { $( VkPhysicalDevice_T* physicalDevicePtr ) };
VkDevice device = { $( VkDevice_T* devicePtr ) }; initInfo.PhysicalDevice = physicalDevice;
initInfo.Device = device; VkDevice device = { $( VkDevice_T* devicePtr ) };
initInfo.QueueFamily = $(uint32_t queueFamily); initInfo.Device = device;
VkQueue queue = { $( VkQueue_T* queuePtr ) }; initInfo.QueueFamily = $(uint32_t queueFamily);
initInfo.Queue = queue; VkQueue queue = { $( VkQueue_T* queuePtr ) };
initInfo.PipelineCache = $(VkPipelineCache pipelineCache); initInfo.Queue = queue;
initInfo.DescriptorPool = $(VkDescriptorPool descriptorPool); initInfo.PipelineCache = $(VkPipelineCache pipelineCache);
initInfo.Subpass = $(uint32_t subpass); initInfo.DescriptorPool = $(VkDescriptorPool descriptorPool);
initInfo.MinImageCount = $(uint32_t minImageCount); initInfo.Subpass = $(uint32_t subpass);
initInfo.ImageCount = $(uint32_t imageCount); initInfo.MinImageCount = $(uint32_t minImageCount);
initInfo.MSAASamples = $(VkSampleCountFlagBits msaaSamples); initInfo.ImageCount = $(uint32_t imageCount);
initInfo.Allocator = $(VkAllocationCallbacks* callbacksPtr); initInfo.MSAASamples = $(VkSampleCountFlagBits msaaSamples);
initInfo.CheckVkResultFn = $( void (*checkResultFunPtr)(VkResult) ); initInfo.Allocator = $(VkAllocationCallbacks* callbacksPtr);
return ImGui_ImplVulkan_Init(&initInfo, $(VkRenderPass renderPass) ); initInfo.CheckVkResultFn = $( void (*checkResultFunPtr)(VkResult) );
}|] return ImGui_ImplVulkan_Init(&initInfo, $(VkRenderPass renderPass) );
pure ( checkResultFunPtr, initResult /= 0 ) }|]
pure ( checkResultFunPtr, initResult /= 0 )
-- | Wraps @ImGui_ImplVulkan_Shutdown@. )
-- ( \ ( checkResultFunPtr, _ ) -> liftIO do
-- Counterpart to 'vulkanInit', for clean-up. [C.exp| void { ImGui_ImplVulkan_Shutdown(); } |]
vulkanShutdown :: MonadIO m => (FunPtr a, b) -> m () freeHaskellFunPtr checkResultFunPtr
vulkanShutdown ( checkResultFunPtr, _ ) = liftIO do )
[C.exp| void { ImGui_ImplVulkan_Shutdown(); } |] ( \ ( _, initResult ) -> action initResult )
freeHaskellFunPtr checkResultFunPtr
-- | Wraps @ImGui_ImplVulkan_NewFrame@. -- | Wraps @ImGui_ImplVulkan_NewFrame@.
vulkanNewFrame :: MonadIO m => m () vulkanNewFrame :: MonadIO m => m ()