Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

dear-imgui bindings #250

Open
turion opened this issue Sep 18, 2023 · 3 comments
Open

dear-imgui bindings #250

turion opened this issue Sep 18, 2023 · 3 comments
Labels

Comments

@turion
Copy link
Owner

turion commented Sep 18, 2023

It would be great to have bindings for https://hackage.haskell.org/package/dear-imgui, which is a GUI library.

@Cajunvoodoo
Copy link

I've actually been working on something like this for Dunai! It's in a very rough condition, but I haven't had tons of time (or motivation) to work on it recently (I really wanted it to compile to the browser, but I think the JS backend needs to mature). The biggest issue with it is sampling rate (my laptop manages to limit the framerate, but on my desktop it burns a core running at max fps). I managed to get user input, graphs, windows, and buttons working in what I think is a decently ergonomic way, but I'm very open to suggestions! The current version of the Dunai library can be found here (everything about it, including the name, is/was WIP and is mostly due to a change in project goals/scope).

I'd happily switch to Rhine, especially with the cleaner user experience, but I'm not entirely confident with the various Rhine datatypes (I get the concept, but I don't know how much the API has changed in terms of UX).

@ners
Copy link
Contributor

ners commented Oct 22, 2023

@Cajunvoodoo I'd love to collaborate with you on this!

@turion
Copy link
Owner Author

turion commented Oct 23, 2023

That sounds great! Since rhine currently depends on dunai, a dunai-dear-imgui library could actually be reused in rhine. For example, FRP.Rhine.ClSF.Except is to a large portion a re-export of the corresponding dunai module, and the other half is just simple lifting functions applied to the dunai primitives.

If you have a conceptual idea, feel free to open a PR, I'll guide you along. If not, here are some ideas how to design this. I think the central questions have to be "what is the monad" and "what are the clocks".

Monads

For the monads, I could imagine something like abstracting the brackets into reader monads that, when run, take care of the brackets. Something like this pseudocode:

{-# LANGUAGE DataKinds #-}
data Backend = OpenGL | SDL
class BackendBracket (b :: Backend) where
  type Context b
  type Config b
  create :: Config b -> IO (Context b)
  destroy :: Context b -> IO ()

instance BackendBracket 'OpenGL where
  type Context 'OpenGL = OpenGLContext
  type Config b = OpenGLConfig
  create = createWindow
  destroy = destroyWindow

-- Using e.g. vinyl heterogeneous lists
newtype ManagedT (backends :: [Backend]) a = ManagedT (ReaderT (Rec Context backends) IO a)

-- It should be possible to implement such a context like Forall using type families
type family Forall (backends :: [Backend]) (Backend -> Constraint) :: Constraint where
  Forall '[] _ = ()
  Forall (backend ': backends) f = (f backend, Forall backends f)

runManagedT :: Forall backends BackendBracked => ManagedT backends a -> IO a
runManagedT = ... -- create all contexts and destroy them at the end

This is just a suggestion, possibly heterogeneous lists are overkill and it's better to have e.g. data Backend = OpenGL | SDL | OpenGLAndSDL | ... to have more fine grained initialisations. Or one does away with the BackendBracket type class completely and burdens initialisation on the user.

Clocks

I'm not sure what's the best idea for clocks.

  1. The obvious way to go forward would be to use an event clock for every widget. But the downside would be that adding, changing or removing a widget then changes the type signature. That would create some friction while developing.
  2. Another way would be to have a single event clock for all widgets. But then one needs to add routing for all events again, which is annoying.
  3. Or one could have no clocks for widget events, and instead wire the widgets the same way one does in dear-imgui. Only the renderings are ticks then.

I guess it's easiest to start with 3. and once this is done, experiment with 2. or 1. when a few example applications are ready.

@turion turion added the backend label Dec 7, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

3 participants