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

[Feature Request] support integration with go-sdl2 binding? #923

Open
shellohunter opened this issue Nov 30, 2024 · 8 comments
Open

[Feature Request] support integration with go-sdl2 binding? #923

shellohunter opened this issue Nov 30, 2024 · 8 comments
Labels
enhancement New feature or request

Comments

@shellohunter
Copy link

Related problem

No response

Your request

I know that giu can work with sdl2 backend, but it goes with sdl2 cgo, right?
Is it possible to integrate giu with go-sdl2 ((https://github.com/veandco/go-sdl2) ? I mean, seamlessly.
yesterday I gave it a try and it seems they two have their owen deps, and work independently.

Alternative solution

No response

Additional context

No response

@shellohunter shellohunter added the enhancement New feature or request label Nov 30, 2024
@gucio321
Copy link
Collaborator

you can deffinitly integrate cimgui-go with go-sdl if you want (however idk why would you need this as ther is an sdl backend already - I'm not a big fan of it but iirc @AllenDang had some reasons to do this with CGO for glfw and I did similar thing for sdl).

In case of giu - Technically its 100% possible to make giu use sdl instead of glfw, but it wan't tested yet 😄. You can be the first one who tries.

(I think laud here):
Technically you need to override giu.Context.backend with sdlbackend from cimgui-go. The problem is that backdne.Backend is a generic type so this might be difficult to write this variable in giu 🤔
if you change

// before
type GIUContext struct {
        backend backend.Backend[glfwbackend.GLFWWindowFlags]
// after
type GIUContext[FLAGST ~int] struct {
        backend backend.Backend[FLAGST]

Now it will be difficutl to define giu.Context variable's type

This might require some cimgui-go refactor as well

@shellohunter
Copy link
Author

Here's my scenario: I've been working on a go-sdl2 project for a couple of days, it goes well, then I want to add a gui toolset for it, so I found giu. the demo was pretty cute, exactly what I'm looking for. I think there should be more gl-sdl2 users thinking about the same thing.

unfortunately, once I introduce giu into the project, my go-sdl2 program keeps throwing unknown errors. I mean, some of the go-sdl2 api stop working and give me an empty error. those errors are all gone if I eliminate giu code.

After some debugging, I realized that the two projects were not working the way I expected.

Thanks for you suggestion. giu is quite a new thing to me, I'll dig for a while see if I can make it~

@gucio321
Copy link
Collaborator

@shellohunter as far as I see, the thing you're looking for is rather cimgui-go, not giu.
We try to keep giu as simple as possible. Especially we want users don't need to care about so called backend (opengl/glfw/sdl things) so giu is really top-level. We can ofc consider adding some features to change backend (as long as it is fully optional)

Generally first of all you need to implement your use-case with cimgui-go

@shellohunter
Copy link
Author

yes, you would be right.
I thought cimgui-go was a auto-generated binding, so i post it here since giu is more active, :-)
actually I also tried cimgui-go with go-sdl2, and I got the same errors. so, the situation is pretty much the same. hopefully replacing the backend could be the way out.

@gucio321
Copy link
Collaborator

yes, you need to implement backend almost from scratch as contexts and other things must match your sdl and opengl instnce.

I thought cimgui-go was a auto-generated binding

cimgui-go/backend is 100% manually-writen 😄

btw, if you like discord we've started a server:

Discord Shield

@shellohunter
Copy link
Author

Yesterday, I gave another try.
Taking ebiten backend as a reference I made some progress on go-sdl2 backend, and here's what i got:

cimgui-bug1

i think something went wrong with the color conversion. but the most obvious issue is the texture ....
I tracked the calls from imgui, it's quite weird that it created only 1 texture, and all following draw cmd uses the only 1 texture. haven't figured it out yet. any advice?

CreateWindow(Hello from cimgui-go,1200x900)
CreateTextureRgba(256,256) -> 1
draw cmd: textureID=1, clipRect={0 0 1200 900}
draw cmd: textureID=1, clipRect={0 0 1200 900}
draw cmd: textureID=1, clipRect={61 79 359 359}
draw cmd: textureID=1, clipRect={0 0 1200 900}
draw cmd: textureID=1, clipRect={401 79 899 359}
draw cmd: textureID=1, clipRect={444 115 881 323}
draw cmd: textureID=1, clipRect={408 87 891 351}
draw cmd: textureID=1, clipRect={454 125 505 161}
draw cmd: textureID=1, clipRect={401 79 899 359}
draw cmd: textureID=1, clipRect={0 0 1200 900}
draw cmd: textureID=1, clipRect={801 279 1049 659}
draw cmd: textureID=1, clipRect={808 287 1042 652}
draw cmd: textureID=1, clipRect={0 0 1200 900}
draw cmd: textureID=1, clipRect={0 0 1200 900}
draw cmd: textureID=1, clipRect={61 79 359 359}

here's my backend.Run code:

func (backend *MyBackend) Run(loop func()) {
	running := true
	for running {
		for event := sdl.PollEvent(); event != nil; event = sdl.PollEvent() {
			switch e := event.(type) {
			case *sdl.QuitEvent:
				running = false
			case *sdl.KeyboardEvent:
				if e.Keysym.Sym == sdl.K_ESCAPE {
					running = false
				}
			}

		}
		if backend.beforeRender != nil {
			backend.beforeRender()
		}

		io := imgui.CurrentIO()
		w, h := backend.window.GetSize()
		io.SetDisplaySize(imgui.Vec2{X: float32(w), Y: float32(h)})

		backend.renderer.SetDrawColor(backend.clearColor.R, backend.clearColor.G, backend.clearColor.B, backend.clearColor.A)
		backend.renderer.Clear()
		imgui.NewFrame()
		loop()
		imgui.EndFrame()

		imgui.Render()
		drawdata := imgui.CurrentDrawData()
		for _, drawList := range drawdata.CommandLists() {
			for _, cmd := range drawList.Commands() {
				clipRect := cmd.ClipRect()
				textureID := cmd.TextureId()
				println(fmt.Sprintf("draw cmd: textureID=%d, clipRect=%v", textureID, clipRect))
				w, h := backend.window.GetSize()
				if clipRect.X == 0 &&
					clipRect.Y == 0 &&
					clipRect.Z == float32(w) &&
					clipRect.W == float32(h) {
					// TODO: draw triangle?
				} else {
					if tx, ok := backend.textureCache.Load(textureID); ok {
						backend.renderer.Copy(tx.(*sdl.Texture), nil, &sdl.Rect{
							X: int32(clipRect.X),
							Y: int32(clipRect.Y),
							W: int32(clipRect.Z - clipRect.X),
							H: int32(clipRect.W - clipRect.Y),
						})
					}
				}
			}

		}

		backend.renderer.Present()
		if backend.afterRender != nil {
			backend.afterRender()
		}
	}
}

@shellohunter
Copy link
Author

well, it turns out the ebiten backend received the same draw cmds and texture ids just as my backend got. but it displays various of widgets as expected.

ok, I'm confused.

according to my understanding, imgui takes in charge of widget logics, like creation and organization of widgets, figures out where to draw them, etc. and my backend is responsible for actual rendering. so the imgui lib should create a bunch of textures using the API provided by my backend, then in every loop it should tell my backend to draw each texture at its specific position. that's how they two work together, am i right?

@gucio321 hoping for some advice, if it's not bothering.

@gucio321
Copy link
Collaborator

according to my understanding, imgui takes in charge of widget logics, like creation and organization of widgets, figures out where to draw them, etc. and my backend is responsible for actual rendering. so the imgui lib should create a bunch of textures using the API provided by my backend, then in every loop it should tell my backend to draw each texture at its specific position. that's how they two work together, am i right?

As far as I understand that - yes.

Generally I think I'm not the right person to ask about that sa I've actually never worked with this low-level logic to be honest. Maybe @damntourists has any idea bout that?

Also, let me note that what you're doing is actually already done inside of Dear ImGui in backends/ directory so it might be worth checking if modifying cimgui-go so that it generates wrappers for that stuff wouldn't be the better idea in fact. (by better I mean easier to do 😄)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

2 participants