haskell-game / dear-imgui.hs

Haskell bindings to Dear ImGui, an immediate mode GUI toolkit
BSD 3-Clause "New" or "Revised" License
142 stars 31 forks source link

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

Closed SturdyPose closed 2 years ago

SturdyPose commented 2 years ago

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.

SturdyPose commented 2 years ago

Ok, never mind. I didn't invoke the IO from the input parameters.

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 (\i -> do 
        liftIO i -- I missed invoking IO at the beginning of the arrow
        t <- get >>= \x -> return $ view (intermediateState . blueishTexture) x
        liftIO $ buttonWindow t
    )

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

            DearImGui.render
            DearImGui.getDrawData >>= openGL3RenderDrawData

            SDL.glSwapWindow window

        return isClicked
    )

Should I add in the future example on how to integrate Yampa (with potentially strict state monad) into Imgui?

dpwiz commented 2 years ago

I'm definitely interested in seeing how dear-imgui ties with different FRP libraries.

Is it possible to use dunai instead and have BearRiver integration for free?

dpwiz commented 2 years ago

I'll close this for now. Will be waiting for your FRP PR :smile: