GithubHelp home page GithubHelp logo

haskell-game / dear-imgui.hs Goto Github PK

View Code? Open in Web Editor NEW
133.0 11.0 31.0 4.1 MB

Haskell bindings to Dear ImGui, an immediate mode GUI toolkit

License: BSD 3-Clause "New" or "Revised" License

Haskell 96.52% Nix 3.48%

dear-imgui.hs's Introduction

Dear ImGui.hs

Dear ImGui is a bloat-free graphical user interface library for C++. It outputs optimized vertex buffers that you can render anytime in your 3D-pipeline enabled application. It is fast, portable, renderer agnostic and self-contained (no external dependencies).

This project contains Haskell bindings to the ImGui project. This allows you to rapidly put together graphical user interfaces in Haskell, with a particular focus to games and graphics intensive applications.

Getting Started

To get started, we'll build the following:

dear-imgui.hs can be used like a normal Haskell library. If you use Cabal, simply add dear-imgui to your build-depends. ImGui supports a variety of backends, and you will need to choose your backend at configuration time. Backends can be enabled using Cabal flags, and these can be set through the cabal.project file. For example, if you want to use a combination of SDL and OpenGL:

package dear-imgui
  flags: +sdl +opengl3

With this done, the following module is the "Hello, World!" of ImGui:

{-# language OverloadedStrings #-}

module Main ( main ) where

import DearImGui
import DearImGui.OpenGL3
import DearImGui.SDL
import DearImGui.SDL.OpenGL

import Graphics.GL
import SDL

import Control.Monad.Managed
import Control.Monad.IO.Class ()
import Control.Monad (when, unless)
import Control.Exception (bracket, bracket_)

main :: IO ()
main = do
  -- Initialize SDL
  initializeAll

  runManaged $ do
    -- Create a window using SDL; as we're using OpenGL, we enable OpenGL too
    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 window) glDeleteContext
    -- Create an ImGui context
    _ <- managed $ bracket createContext destroyContext

    -- Initialize ImGui's SDL2 backend
    managed_ $ bracket_ (sdl2InitForOpenGL window glContext) sdl2Shutdown
    -- Initialize ImGui's OpenGL backend
    managed_ $ bracket_ openGL3Init openGL3Shutdown

    liftIO $ mainLoop window

mainLoop :: Window -> IO ()
mainLoop window = unlessQuit $ do
  -- Tell ImGui we're starting a new frame
  openGL3NewFrame
  sdl2NewFrame
  newFrame

  -- Build the GUI
  withWindowOpen "Hello, ImGui!" $ do
    -- Add a text widget
    text "Hello, ImGui!"

    -- Add a button widget, and call 'putStrLn' when it's clicked
    button "Clickety Click" >>= \clicked ->
      when clicked $ putStrLn "Ow!"

  -- Show the ImGui demo window
  showDemoWindow

  -- Render
  glClear GL_COLOR_BUFFER_BIT
  render
  openGL3RenderDrawData =<< getDrawData

  glSwapWindow window
  mainLoop window
  where
  -- Process the event loop
  unlessQuit action = do
    shouldQuit <- gotQuitEvent
    unless shouldQuit action

  gotQuitEvent = do
    ev <- pollEventWithImGui

    case ev of
      Nothing ->
        return False
      Just event ->
        (isQuit event ||) <$> gotQuitEvent

  isQuit event =
    eventPayload event == QuitEvent

Hacking

If you would like to help dear-imgui, here's how you can get started.

The best path to development is using Nix. Once you have Nix installed (either in your operating system, or by running NixOS), you can enter a development shell:

$ nix-shell

You should now be in a bash shell where you can run cabal build all, cabal run readme, etc.

If you experience any difficulties, please don't hesistate to raise an issue.

Getting Help

Feel free to raise bugs, questions and feature requests on the GitHub issue tracker.

We have a Matrix room at #dear-imgui.hs:ocharles.org.uk.

dear-imgui.hs's People

Contributors

alt-romes avatar asivitz avatar bflyblue avatar cab404 avatar cartazio avatar chekoopa avatar dpwiz avatar drezil avatar jpwidera avatar jship avatar jtnuttall avatar o1lo01ol1o avatar ocharles avatar sheaf avatar swarthe avatar techmindful avatar tristancacqueray avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

dear-imgui.hs's Issues

Splitting rendering new frames for FRP - Future yampa example for imgui

I've been playing with Yampa and this lib lately. I'm facing the issue where I need to split code for rendering new frames into different yampa's signal functions. After splitting code for rendering frames I get this error:
Assertion failed: g.WithinFrameScope && "Forgot to call ImGui::NewFrame()?"

This is just minimal example:

mainSF:: SDL.Window -> SF (Event SDL.EventPayload) (IOProgramRWSType Bool)
mainSF window = beginRender >>> middleRender >>> (endRender window)

beginRender:: SF (Event SDL.EventPayload) (IOProgramRWSType (Event SDL.EventPayload))
beginRender = arr (\i -> do 
        openGL3NewFrame
        sdl2NewFrame
        newFrame
        return i
    )

middleRender:: SF (IOProgramRWSType (Event SDL.EventPayload)) (IOProgramRWSType Bool)
middleRender= arr (\_ -> do 
        t <- get >>= \x -> return $ view (intermediateState . blueishTexture) x
        liftIO $ buttonWindow t
    )

endRender:: SDL.Window -> SF (IOProgramRWSType Bool) (IOProgramRWSType Bool)
endRender window = arr (\i -> do 
    
        liftIO $ do
            glClear GL_COLOR_BUFFER_BIT

            DearImGui.render
            DearImGui.getDrawData >>= openGL3RenderDrawData

            SDL.glSwapWindow window

        i
    )

MainSF is signal function for Yampa's reactimate.
IOProgramRWSType is RWST monad with IO.
ButtonWindow is just button which returns IO bool (isClicked).

Is there a way on how I can split rendering new frames? I don't want to lose the yampa's functionality where I can detect the signals from different windows and do fancy stuff with them.

Auto-generation of bindings

I started looking at imgui.h. It's large. I don't think it's reasonable to achieve feature completeness, even less maintainability, without auto-generating at least some portion of the bindings. We could rely on cimgui, or generate directly from the headers. This would also allow easier access to different branches of ImGui, such as the docking branch which supports multi-viewport.

I haven't looked too much into it, but for cimgui here are some possible steps:

  • parse structs_and_enums and define corresponding Haskell types
    • a newtype around CInt for each enum type, with the corresponding pattern synonyms
    • ADTs for structs
  • parse typedefs_dicts and define Haskell type synonyms
  • (the hard part) parse definitions and use them to generate bindings like the ones that currently exist in the main DearImGui.hs file.

Running the glfw example in ghci shows a blank window

When running:

$ cabal repl exe:glfw
[1 of 1] Compiling Main             ( examples/glfw/Main.hs, interpreted )
Ok, one module loaded.
ghci> Main.main
[blank window appears]

Note that this work with exe:vulkan: the dear-imgui window is displayed.

What could be the issue?

Don’t hardcode imgui location

When I try to build a project with dear-imgui.hs, I get the following error:

dear-imgui> generator\DearImGui\Generator.hs:75:11: error:
dear-imgui>     * Exception when trying to run compile-time code:
dear-imgui>         C:\Users\bradn\AppData\Local\Programs\stack\x86_64-windows\msys2-20150512\tmp\stack-2831df5137059ac1\dear-imgui-1.0.0\imgui\imgui.h: openFile: does not exist (N
dear-imgui>       Code: do currentPath <- TH.loc_filename <$> TH.location
dear-imgui>                basicHeaders <- TH.runIO
dear-imgui>                                  do headersPath <- canonicalizePath
dear-imgui>                                                      (takeDirectory currentPath
dear-imgui>                                                         <> "/../../imgui/imgui.h")
dear-imgui>                                     ....
dear-imgui>                TH.lift $ generateNames basicHeaders
dear-imgui>     * In the untyped splice:
dear-imgui>         $(do currentPath <- TH.loc_filename <$> TH.location
dear-imgui>              basicHeaders <- TH.runIO
dear-imgui>                                do headersPath <- canonicalizePath
dear-imgui>                                                    (takeDirectory currentPath
dear-imgui>                                                       <> "/../../imgui/imgui.h")
dear-imgui>                                   headersSource <- Text.readFile headersPath
dear-imgui>                                   ....
dear-imgui>              TH.lift $ generateNames basicHeaders)
dear-imgui>    |
dear-imgui> 75 | headers = $( do
dear-imgui>    |           ^^^^^...
dear-imgui>

The cause of this error is obvious: dear-imgui.hs looks for imgui at ./../../imgui/imgui.h. However, I am using Stack, which changes the working directory to a temporary one while building; it is thus infeasible to place imgui at this location. For this reason, would it be possible to avoid hardcoding the location of imgui? Preferably it would be possible for the user to specify the location of their imgui installation in some fasion. (Cabal flags would be perfect for this, if only they supported string values…)

Matrix room appears to be private

As title. When attempting to join, I receive an error:

#dear-imgui.hs:ocharles.org.uk is not accessible at this time.

Try again later, or ask a room or space admin to check if you have access.

Cheers :)

Wrong flags type for *TabItem

It is ImGuiTabBarFlags.
Should be ImGuiTabItemFlags instead.

IMGUI_API bool          BeginTabItem(const char* label, bool* p_open = NULL, ImGuiTabItemFlags flags = 0);
// create a Tab. Returns true if the Tab is selected.

Adding debug mode to build

To debug the C/C++-calls and run in gdb a debug mode would be very handsome.
Something like:

if flag(debug)
  if os(linux)
     ghc-options: -Wall -g -rtsopts -dcore-lint -debug -O0
     cc-options: -g -O0 -fsanitize=address -fno-omit-frame-pointer
  if os(darwin)
    ....
  if os(windows)
   ...

Provide wrapped functions with all the options exposed

A follow-up to #52, but can be done concurrently.

The current functions can remain intact and a new set of functions can be added as a cheap wrapper for raw procedures.

-- current
withWindowOpen :: MonadUnliftIO m => String -> m () -> m ()

-- proposed
withWindowOpen' :: (MonadUnliftIO m, StateVar Bool isOpen) => ImGuiWindowFlags -> isOpen -> String -> m () -> m ()

Fancy wrappers (labels, lenses, etc.) can be provided as alternatives in their own packages.

Cons: this will double the amount of functions published. The previous implementation, however, can be rebased upon those new expanded.

Alternative 1: Add all the arguments to existing functions. A breaking change, a bit noisier to write but lighter on maintenance.

Alternative 2: Rename current shortcuts to underscored, add expanded versions like in A1. Also a breaking change and may require breakage again when "expandable defaults" are to be implemented.

Trying to build with stack as a dependency packages fails

stack.yaml:

packages:
- .
- /.../dear-imgui.hs

package.yaml:

dependencies:
- base >= 4.7 && < 5
- dear-imgui
$ stack build
cabal file path /home/sino/github/dear-imgui.hs/hs-dear-imgui.cabal does not match the package name it defines.
Please rename the file to: dear-imgui.cabal
For more information, see: https://github.com/commercialhaskell/stack/issues/317

Handling GetIO, GetStyle and GetStyleColorVec4

These 3 functions return a reference.

GetStyleColorVec4 seems to just be used to pass a reference to PushStyleColor, so I don't think we need to do anything special.

On the other hand, GetIO and GetStyle allow the user to change internal ImGui settings by mutating the state. So I think we might want a slightly different API. For instance, we could have:

data ImGuiIO = ImGuiIOHandle ( Ptr ImGuiIO )
data ImGuiStyle = ImGuiStyleHandle ( Ptr ImGuiStyle )

getIO :: MonadIO m => m ImGuiIO
getStyle :: MonadIO m => m ImGuiStyle

and then an interface for getting/setting fields:

data ImGuiIOFieldName
  = ConfigFlags
  | BackendFlags
  | DisplaySize
  | DeltaTime
  ...

data ImGuiStyleFieldName
  = Alpha
  | WindowPadding
  | WindowRounding
  ...


class HasImGuiIOField ( name :: ImGuiIOFieldName ) ( a :: Type ) | name -> a where
  getIOField :: ImGuiIO -> m a
  setIOField :: ImGuiIO -> a -> m ()

class ImGuiStyleField ( name :: ImGuiStyleFieldName ) ( a :: Type ) | name -> a where
  getStyleField :: ImGuiStyle -> m a
  setStyleField :: ImGuiStyle -> a -> m ()


instance HasImGuiIOField 'ConfigFlags  ImGuiConfigFlags
instance HasImGuiIOField 'BackendFlags ImGuiBackendFlags
instance HasImGuiIOField 'DisplaySize ImVec4
instance HasImGuiIOField 'DeltaTime Float

instance HasImGuiStyleField 'Alpha Float
instance HasImGuiStyleField 'WindowPadding ImVec2
instance HasImGuiStyleField 'WindowRounding Float

This would definitely be an improvement in usability over manually mutating fields through the reference.
Another upside is that it avoids us having to actually define the ImGuiIO and ImGuiStyle structs proper: we can just implement whatever get/set operations we want. I think this is particularly relevant with the function pointers in the ImGuiIO struct like GetClipboardTextFn, SetClipboardTextFn, where it seems much more appropriate to have a HasImGuiIOField instance for 'ClipboardTextFn as opposed to requiring the user to manage two different function pointers.

How can you help?

Hi, thanks for coming to see how you can help! We need help in a variety of places:

Add More Bindings

A good starting point is to add bindings to more functions. We're trying to implement all of imgui.h. If you head down the line namespace ImGui, you should find the majority of ImGui's functions. Go through this list and see if you can spot anything that's not in DearImGui.hs. If there's something missing, please help us add it!

Add More Backends

ImGui ships with a variety of different backends, and we currently only support a handful. Implementing a backend is similar to wrapping functions - open up the relevant .h file and create a corresponding .hs module and then wrap each function. Check the other implemented backends for reference, and if you get stuck raise an issue and we'll help

Add Bindings to Contributed Libraries

Dear ImGui has a rich and active community with lots of contributed extensions. We'd love to have wrappers for these, too! The list is constantly growing, but the "Useful Widgets" wiki page shows a lot of projects.

Use The Library

A great way to help us find out if this library is useful is to just use it! Try making some cool stuff and see what you think. Any feedback is appreciated.

It's Dangerous to Go Alone!

There is a Matrix room set up - if you have any questions or just want to come hang out, come join!

strange error when trying to do Compatibility 4 1 profile vs Core 4 1 profile

Hey! So after some futzing, i got the readme example to work wiht >= opengl3 flavor stuff. as below.

i did hit a strange crash i'm not sure how to understand when i tried a compatiblity profile (not that i expect to need it, but was just trying things)

carterschonwald@CarterHydra ~/W/p/a/genicad (main) [1]> cabal run exe:trash_demo
Build profile: -w ghc-9.4.7 -O1
In order, the following will be built (use -v for more details):
 - genicad-0.1.0.0 (exe:trash_demo) (file app/Trash.hs changed)
Preprocessing executable 'trash_demo' for genicad-0.1.0.0..
Building executable 'trash_demo' for genicad-0.1.0.0..
trash_demo: SDLCallFailed {sdlExceptionCaller = "SDL.Video.glCreateContext", sdlFunction = "SDL_GL_CreateContext", sdlExceptionError = "Failed creating OpenGL context at version requested"}

the full code with working core profile is as below

{-# LANGUAGE OverloadedStrings,GHC2021 #-}

module Main ( main ) where

import Control.Exception
import Control.Monad.IO.Class
import Control.Monad.Managed
import DearImGui
import DearImGui.OpenGL3
import DearImGui.SDL
import DearImGui.SDL.OpenGL
import Graphics.GL
import SDL
import SDL.Video 

main :: IO ()
main = do
  -- Initialize SDL
  initializeAll

  runManaged $ do
    -- Create a window using SDL. As we're using OpenGL, we need to enable OpenGL too.
    window <- do
      let title = "Hello, Dear ImGui!"
      let config = defaultWindow { windowGraphicsContext = OpenGLContext defaultOpenGL{glProfile=Core Normal 4 1} , windowResizable       = True }
      managed $ bracket (createWindow title config) destroyWindow

    -- Create an OpenGL context
    glContext <- managed $ bracket (glCreateContext window) glDeleteContext

    -- Create an ImGui context
    _ <- managed $ bracket createContext destroyContext

    -- Initialize ImGui's SDL2 backend
    _ <- managed_ $ bracket_ (sdl2InitForOpenGL window glContext) sdl2Shutdown

    -- Initialize ImGui's OpenGL backend
    _ <- managed_ $ bracket_ openGL3Init openGL3Shutdown

    liftIO $ mainLoop window


mainLoop :: Window -> IO ()
mainLoop window = unlessQuit $ do
  -- Tell ImGui we're starting a new frame
  openGL3NewFrame
  sdl2NewFrame
  newFrame

  -- Build the GUI
  withWindowOpen "Hello, ImGui!" $ do
    -- Add a text widget
    text "Hello, ImGui!"

    -- Add a button widget, and call 'putStrLn' when it's clicked
    button "Clickety Click" >>= \x -> case x of 
      False -> return ()
      True  -> putStrLn "Ow!"

  -- Show the ImGui demo window
  showDemoWindow

  -- Render
  glClear GL_COLOR_BUFFER_BIT

  render
  openGL3RenderDrawData =<< getDrawData

  glSwapWindow window

  mainLoop window

  where
    -- Process the event loop
    unlessQuit action = do
      shouldQuit <- checkEvents
      if shouldQuit then pure () else action

    checkEvents = do
      pollEventWithImGui >>= \x -> case x of 
        Nothing ->
          return False
        Just event ->
          (isQuit event ||) <$> checkEvents

    isQuit event =
      SDL.eventPayload event == SDL.QuitEvent

Handling of Begin/End pairs

Is there any situation in which users might need to use beginXXX/endXXX in an atypical way? As far as I understand:

  • begin/end, beginChild/endChild, beginGroup/endGroup, beginTooltip/endTooltip, beginChildFrame/endChildFrame must always occur in matching pairs, so we can replace them with simple with-style functions,
  • beginCombo/endCombo, beginListBox/endListBox, beginMenuBar/endMenuBar, beginMainMenuBar/endMainMenuBar, beginPopup/endPopup, beginTable/endTable, beginTabBar/endTabBar, beginDragDropSource/endDragDropSource, beginDragDropTarget/endDragDropTarget all require a matching end function precisely when the begin function returned True. Is there any other way to use them than with the whenTrue idiom we are currently using in the example?

If there is literally no other valid usage pattern, I would recommend entirely replacing the beginXXX/endXXX functions with bracketed functions. Then users aren't confused about which one to use, and can't get it wrong.
If there are valid usage patterns, then of course we should keep the individual beginXXX/endXXX functions, and provide additional helpers.

On using withCString

I was looking through C++ code and found that it assumes its text data is in UTF-8.

This may not be necessarily the case, since Foreign.withCString is locale-dependent and some users may have ASCII/C or some other national locales. This regularly trips up Windows users with symptoms like "invalid argument (invalid character)".

Besides, using withCString will waste CPU on the same [Char] -> CString conversion for every call on every frame. While the raw bindings are exempt from this churn, the library can provide smart constructors that will take in something like Text, encode to UTF8 ByteString once and then use its pointer for raw calls. Anyway, even with Text-to-BS encoding happening every frame at least it will be correct for any environment.

More popup bindings

  • OpenPopupOnItemClick
  • BeginPopupContextItem
  • BeginPopupContextWindow
  • BeginPopupContextVoid
  • IsPopupOpen

Add sdist releases to CI

A small-effort stepping stone towards #50, the CI can be tasked with preparing source tarballs to be published as GitHub releases.

It is of little direct benefit but sets up an obvious iteration point.

Expose flags to widgets

Hey all,
I'm trying to make an inputText that returns true when an enter is hit, which requires the ImGuiInputTextFlags_EnterReturnsTrue flag. I notice all flags are already there, but most widgets are set with a default value instead of exposing it to the public interface, I find it is a bit limiting. Is there a reason for this? e.g for this piece:

dear-imgui.hs/src/DearImGui.hs

Lines 1216 to 1224 in 7795b3d

-- | Wraps @ImGui::InputText()@.
inputText :: (MonadIO m, HasSetter ref Text, HasGetter ref Text) => Text -> ref -> Int -> m Bool
inputText label ref bufSize =
withInputString ref bufSize \bufPtrLen ->
Text.withCString label \labelPtr ->
Raw.inputText
labelPtr
bufPtrLen
ImGuiInputTextFlags_None

Can we expose the flag as an option to the user like this?

 inputText :: (MonadIO m, HasSetter ref Text, HasGetter ref Text) => Text -> ref -> Int -> ImGuiInputTextFlags -> m Bool 

Bump imgui to 1.84.2

However, ....

https://github.com/ocornut/imgui/releases/tag/v1.84

Backends: GLFW: backend uses glfwSetCursorEnterCallback() + glfwSetWindowFocusCallback() (#3751, #4377, #2445, #4388)

  • If calling ImGui_ImplGlfw_InitXXX with install_callbacks=true: this is already done for you.
  • If calling ImGui_ImplGlfw_InitXXX with install_callbacks=false: you WILL NEED to register the GLFW callbacks and forward them to the backend:
    • Register glfwSetCursorEnterCallback, forward events to ImGui_ImplGlfw_CursorEnterCallback().
    • Register glfwSetWindowFocusCallback, forward events to ImGui_ImplGlfw_WindowFocusCallback().

Build 'Hello World' example on Windows with Stack

This is not an issue as such, but to record for the benefit of other users that I was able to build the 'Hello World' example on Windows 11 with EDIT: a modified version of Stack 2.15.1 the master branch version of Stack (post-Stack 2.15.1), as follows:

A Stack configuration:

snapshot: lts-22.11 # GHC 9.6.4
extra-deps:
# Release v2.2.0
- git: https://github.com/haskell-game/dear-imgui.hs.git
  commit: bab4d769eaacba2de5da342e853f18746db0e12c
- megaparsec-9.2.2@sha256:c306a135ec25d91d252032c6128f03598a00e87ea12fcf5fc4878fdffc75c768,3219
flags:
  dear-imgui:
    sdl: true
    opengl3: true

A package.yaml:

name: imGuiHelloWorld
version: 0.1.0.0
dependencies:
- base >= 4.7 && < 5
- dear-imgui
- gl
- managed
- sdl2
executables:
  imguiHelloWorld:
    main: Main.hs
    source-dirs: app
    ghc-options:
    - -threaded
    - -rtsopts
    - -with-rtsopts=-N

I needed also needed to install with stack exec -- pacman (SDL versions after 2.24.1-1 do not work):

-S mingw-w64-x86_64-pkgconf
-U mingw-w64-x86_64-SDL2-2.24.1-1-any.pkg.tar.zst # From archive at https://repo.msys2.org/mingw/mingw64/
-S mingw-w64-x86_64-glew

EDIT: Stack 2.15.1/pantry-9.3.2 does not appear to handle an extra-dep with submodules. That is being investigated at commercialhaskell/stack#5536. That has been fixed in the master branch version of Stack (if you are not using GHCup to manage versions of Stack, stack upgrade --source-only --git).

Update to 1.87

https://github.com/ocornut/imgui/releases/tag/v1.87

There are some breaking changes and the generator is failing:

generator/DearImGui/Generator.hs:72:11: error:
    • Exception when trying to run compile-time code:
        Couldn't parse Dear ImGui headers:

offset=9459:
Couldn't lookup the following values in enum ImGuiKey_:
 - ImGuiKey_COUNT



Number 512.0 ""
ReservedSymbol ','
Identifier "ImGuiKey_NamedKey_END"
ReservedSymbol '='
Identifier "ImGuiKey_COUNT"


ReservedSymbol ','
Identifier "ImGuiKey_NamedKey_COUNT"
ReservedSymbol '='
Identifier "ImGuiKey_NamedKey_END"
Symbolic "-"
Identifier "ImGuiKey_NamedKey_BEGIN"
ReservedSymbol ','
BeginCPP "ifdef"
Identifier "IMGUI_DISABLE_OBSOLETE_KEYIO"
EndCPPLine
Identifier "ImGuiKey_KeysData_SIZE"
ReservedSymbol '='
Identifier "ImGuiKey_NamedKey_COUNT"
ReservedSymbol ','
Comment "Size of KeysData[]: only hold named keys"

CallStack (from HasCallStack):
  error, called at generator/DearImGui/Generator.hs:87:9 in dear-imgui-1.3.1-inplace-dear-imgui-generator:DearImGui.Generator
      Code: do currentPath <- TH.loc_filename <$> TH.location
               basicHeaders <- TH.runIO
                                 do headersPath <- canonicalizePath
                                                     (takeDirectory currentPath
                                                        <> "/../../imgui/imgui.h")
                                    ....
               TH.lift $ generateNames basicHeaders
    • In the untyped splice:
        $(do currentPath <- TH.loc_filename <$> TH.location
             basicHeaders <- TH.runIO
                               do headersPath <- canonicalizePath
                                                   (takeDirectory currentPath
                                                      <> "/../../imgui/imgui.h")
                                  headersSource <- Text.readFile headersPath
                                  ....
             TH.lift $ generateNames basicHeaders)
   |
72 | headers = $( do
   |           ^^^^^...

Failed to compile shader

I was building a minimal example based on the code in the readme: https://github.com/ad-si/dear-imgui-test (Only changes: using OpenGL3).

However, it just opens a blank black screen and I'm getting following error:

$ stack run
ERROR: ImGui_ImplOpenGL3_CreateDeviceObjects: failed to compile vertex shader! With GLSL: #version 150

ERROR: 0:1: '' :  version '150' is not supported

ERROR: ImGui_ImplOpenGL3_CreateDeviceObjects: failed to compile fragment shader! With GLSL: #version 150

ERROR: 0:1: '' :  version '150' is not supported

ERROR: ImGui_ImplOpenGL3_CreateDeviceObjects: failed to link shader program! With GLSL #version 150

ERROR: One or more attached shaders not successfully compiled

My system:

OS: macOS 13.6.2 22G320 arm64
Host: MacBookPro18,3
Kernel: 22.6.0
CPU: Apple M1 Pro
GPU: Apple M1 Pro
Memory: 3127MiB / 16384MiB

Add GLFW callbacks

// GLFW callbacks
// - When calling Init with 'install_callbacks=true': GLFW callbacks will be installed for you. They will call user's previously installed callbacks, if any.
// - When calling Init with 'install_callbacks=false': GLFW callbacks won't be installed. You will need to call those function yourself from your own GLFW callbacks.
IMGUI_IMPL_API void     ImGui_ImplGlfw_WindowFocusCallback(GLFWwindow* window, int focused);
IMGUI_IMPL_API void     ImGui_ImplGlfw_CursorEnterCallback(GLFWwindow* window, int entered);
IMGUI_IMPL_API void     ImGui_ImplGlfw_MouseButtonCallback(GLFWwindow* window, int button, int action, int mods);
IMGUI_IMPL_API void     ImGui_ImplGlfw_ScrollCallback(GLFWwindow* window, double xoffset, double yoffset);
IMGUI_IMPL_API void     ImGui_ImplGlfw_KeyCallback(GLFWwindow* window, int key, int scancode, int action, int mods);
IMGUI_IMPL_API void     ImGui_ImplGlfw_CharCallback(GLFWwindow* window, unsigned int c);
IMGUI_IMPL_API void     ImGui_ImplGlfw_MonitorCallback(GLFWmonitor* monitor, int event);

The code is not a big deal by itself, but require a window pointer that isn't published in GLFW-b.

Hackage release

Hi all,

thanks for your work! Is there any chance to have the package relased on Hackage? Any blockers?

Thanks,
Andrea

Font glyph ranges support

Stumbled upon the library on this week and pleased that it fits nicely for NixOS-based development and deploy. The problem is our intended end-users are Russian-speaking, and ImGui supposedly supports Unicode fonts. However, we should explicitly set needed character ranges, otherwise they would be replaced with ?'s.

So, I propose expanding font binds and adding glyph_ranges option, if not also ImFontConfig. Though, it seems that the issue is actually linked with #61.

text (ImGui::Text) is not formatted

The original uses variable args, but the bindings pass text as a single argument.

[C.exp| void { Text("%s", $(char* textPtr)) } |]

Either some type trickery is in order, or documentation tweak.

Marked as broken on nixpkgs

Currently, dear-imgui.hs is marked as broken on nixpkgs. Temporarily allowing broken packages gives the following error:

@nix { "action": "setPhase", "phase": "configurePhase" }
configuring
configureFlags: --verbose --prefix=/nix/store/r0z0xjm7p1cdsz1am22rswl97y6fg5vq-dear-imgui-2.1.3 --libdir=$prefix/lib/$compiler --libsubdir=$abi/$libname --with-gcc=gcc --package-db=/build/tmp.qo7rfeAam4/packa>Using Parsec parser
Configuring dear-imgui-2.1.3...

Setup: Encountered missing or private dependencies:
megaparsec >=9.0 && <9.3

Ignoring dependency bounds with haskell-flake produces a different error:

error: builder for '/nix/store/5mr7mfnacvzynjizdr3xqkq488mk7ayh-source-dear-imgui-sdist.tar.gz.drv' failed with exit code 1;
       last 8 log lines:
       > unpacking source archive /nix/store/gfanl0krmlsgv2ij5x3nfslh2dfk1c7c-source-dear-imgui
       > source root is source-dear-imgui
       > Config file path source is default config file.
       > Config file not found: /build/source-dear-imgui/.config/cabal/config
       > Writing default configuration to /build/source-dear-imgui/.config/cabal/config
       > Error: cabal: sdist of dear-imgui-2.1.3: filepath wildcard 'imgui/*.h' does
       > not match any files.
       >
       For full logs, run 'nix log /nix/store/5mr7mfnacvzynjizdr3xqkq488mk7ayh-source-dear-imgui-sdist.tar.gz.drv'.
error: 1 dependencies of derivation '/nix/store/pjll751gmfh225wxiadrd94b90s7zc9q-dear-imgui-2.1.3.drv' failed to build

I am using pkgs.haskell.packages.ghc92 (ghc 9.2.8) for my project.

[SDL] Add ImGui functions that use the SDL2 Renderer

I am trying to add ImGui to a small project I had using SDL but it didn't seem compatible with what this package offered. I looked at the original C++ project and they seem to have functions that allow rendering using the SDL renderer. I tried adding these binding on my own as in these functions:

sdl2InitForRenderer :: MonadIO m => Window -> Renderer -> m Bool
sdl2InitForRenderer (Window windowPtr) (Renderer rendererPtr) = liftIO do
  (0 /=) <$> [C.exp| bool { ImGui_ImplSDL2_InitForSDLRenderer((SDL_Window*)$(void* windowPtr), (SDL_Renderer*)$(void* rendererPtr)) } |]

sdl2RendererInit :: MonadIO m => Renderer -> m Bool
sdl2RendererInit (Renderer rendererPtr) = liftIO do
  (0 /=) <$> [C.exp| bool { ImGui_ImplSDLRenderer2_Init((SDL_Renderer*)$(void* rendererPtr)) } |]

sdl2RendererNewFrame :: MonadIO m => m ()
sdl2RendererNewFrame = liftIO do
  [C.exp| void { ImGui_ImplSDLRenderer2_NewFrame(); } |]

sdl2RendererShutdown :: MonadIO m => m ()
sdl2RendererShutdown = liftIO do
  [C.exp| void { ImGui_ImplSDLRenderer2_Shutdown(); } |]

sdl2RendererRenderDrawData :: MonadIO m => DrawData -> m ()
sdl2RendererRenderDrawData (DrawData drawDataPtr) = liftIO do
  [C.exp| void { ImGui_ImplSDLRenderer2_RenderDrawData((ImDrawData*) $( void* drawDataPtr )); } |]

by i cant seem to get the ImGui window to show properly, the blue bars bug out and the text doesn't show. Since I'm not that savvy in neither cpp, haskell or either library, I though it would be best to ask for their implementation here.

Update to imgui 1.88

Last time i accidentally had checked out the wrong branch on imgui locally (using master instead of v1.87) it compiled flawlessly.

However there is at least one "breaking" change i am aware of when the new implot-version broke my generator:
https://github.com/epezent/implot/blob/master/implot.h#L545-L552

#if (IMGUI_VERSION_NUM < 18716) // Renamed in 1.88
#define ImGuiModFlags       ImGuiKeyModFlags
#define ImGuiModFlags_None  ImGuiKeyModFlags_None
#define ImGuiModFlags_Ctrl  ImGuiKeyModFlags_Ctrl
#define ImGuiModFlags_Shift ImGuiKeyModFlags_Shift
#define ImGuiModFlags_Alt   ImGuiKeyModFlags_Alt
#define ImGuiModFlags_Super ImGuiKeyModFlags_Super
#endif

according to imgui:
https://github.com/ocornut/imgui/blob/v1.88/imgui.cpp#L390-L392

 - 2022/04/05 (1.88) - inputs: renamed ImGuiKeyModFlags to ImGuiModFlags. Kept inline redirection enums (will obsolete). This was never used in public API functions but technically present in imgui.h and ImGuiIO.

but i think the dear-imgui-generator we use for the enums generated & exposed them.

So i'm hesitant to just open a PR with "just checkout v1.88 - what could possible go wrong"-mentality :D

Compile failure on MacOS w/ GLFW

The current version does not build for me on MacOS (m1, GHC 8.10.7). I'm using the GLFW flag, but I suspect I might get other failures even with different flags.

022-08-23 13:59:47.286836: [info] dear-imgui  > [ 2 of 17] Compiling DearImGui.GLFW
2022-08-23 13:59:47.636796: [warn] dear-imgui  >
2022-08-23 13:59:47.637035: [warn] dear-imgui  > /private/var/folders/f6/yyydf8_149gg2pc9pm3wvgcw0000gn/T/stack-5c40579330f2d8c1/dear-imgui-2.1.0/In file included from /var/folders/f
6/yyydf8_149gg2pc9pm3wvgcw0000gn/T/ghc7845_0/ghc_16.cpp:2:0: error:
2022-08-23 13:59:47.637096: [warn] dear-imgui  >
2022-08-23 13:59:47.637128: [warn] dear-imgui  >
2022-08-23 13:59:47.637319: [warn] dear-imgui  > /private/var/folders/f6/yyydf8_149gg2pc9pm3wvgcw0000gn/T/stack-5c40579330f2d8c1/dear-imgui-2.1.0/imgui/imgui.h:252:5: error:
2022-08-23 13:59:47.637363: [warn] dear-imgui  >      error: unknown type name 'constexpr'
2022-08-23 13:59:47.637384: [warn] dear-imgui  >         constexpr ImVec2()                      : x(0.0f), y(0.0f) { }
2022-08-23 13:59:47.637402: [warn] dear-imgui  >         ^
2022-08-23 13:59:47.637417: [warn] dear-imgui  >     |
2022-08-23 13:59:47.637433: [warn] dear-imgui  > 252 |     constexpr ImVec2()                      : x(0.0f), y(0.0f) { }
2022-08-23 13:59:47.637450: [warn] dear-imgui  >     |     ^
2022-08-23 13:59:47.637496: [warn] dear-imgui  >

As far as I understand, DearImGui.GLFW has this inline-c call:

C.include "imgui.h" -- I think it's from this line? Not sure.

and we should be using a c++ compiler with -std=c++11. But we're not (only on MacOS I assume).

The cabal library has

  cxx-options: -std=c++11

but that doesn't seem to be enough.

I am actually able to fix the issue by adding

 ghc-options:
    -optcxx-std=c++11
    -optcxx-Wall

as I did in this commit: e6c40ff

I got this idea from https://github.com/fpco/inline-c/blob/master/inline-c-cpp/inline-c-cpp.cabal#L46

But I'm not sure exactly what the fix should look like for this package.

Would be happy to make this a PR if it seems like a reasonable solution. (Side note: do we support GHC < 8.10?)

Bracket for Push/Pop functions

It seems fairly obvious that a bracket-style scoping of ImGuiContext mutation should be supported per the dear-imgui.hs API. My intuition says to more-or-less implement a function such as:

setStyleVar :: (MonadIO m) => StyleVar -> StyleVarValue -> m a -> m a
setStyleVars :: (MonadIO m) => [(StyleVar, StyleVarValue)] -> m a -> m a

this would effectively invoke pushStyleVar with its first two parameters, invoke the provided MonadIO instance, and then invoke popStyleVar.

When will you put this in Hackage?

I wanted to use this, but could not find it in Hackage. It must be there to support my workflow. So when do you intend to place it there?

Thanks.

Separate valueRef and rangeRef for sliderScalar

The sliderScalar function takes three scalar values: the slider setting, which must be read and updated, and the low and high values of the range, which only need to be read. However, the type used for both is

(HasSetter ref a, HasGetter ref a) => ref

This means that we have to create (e.g.) IORef containers for the bounds, instead of just passing pure lo. This isn't an enormous problem -- we can just create new IORefs before calling sliderScalar and they'lll be GCed after the call -- but it's one more thing to remember, and the range references don't need the extra power.

I therefore suggest that the references work the same as in sliderScalarN, separating valueRef from rangeRef. The new signature of sliderScalar would thus be

sliderScalar
  :: (HasSetter valueRef a, HasGetter valueRef a, HasGetter rangeRef a, Storable a, MonadIO m)
  => String -> ImGuiDataType -> valueRef -> rangeRef -> rangeRef -> String -> ImGuiSliderFlags -> m Bool

In fact, I think that the signature is the only change that would have to be made.

ways to reduce superflous cpu usage?

I noticed that the demo app was using ~ 86% of a cpu core,
on the chance that its because of the default renderloop never sleeping, i added a threadDelay 10_000 to the end of the loop and my CPU usage went down to like ~ 15%. I also disabled Idle gc for now (yeolde +RTS I0 flage)

I think the "at scale" approach is probably using sleeping semantics that wakeup either after an idle period or when inputs over a large enough time interval to debounce or whatever "simultaneous keys" is done, probably using MVars or STM. But what are suggested best practices?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.