Open maxsupermanhd opened 1 year ago
Any updates on that?
I think you could check the Imgui for a demo, and use almost the same API here.
@AllenDang problem is that even imgui doesn't have such an example. They only have a document about it but with no example. So we don't know how to create two windows initially being in the same dockspace (in the demo below I've merged these windows after running an app).
CC @ocornut
Perhaps I can help? I've been spending quite a bit of time recently working on getting docking working using cimgui-go with success.
First thing to do is enable it:
imgui.CurrentIO().SetConfigFlags(imgui.ConfigFlagsDockingEnable)
My setup docking function looks like this, and it only executes the portion in the if !u.initialized
on the first iteration of the event loop
func setupDocking(u *UI) {
viewport := imgui.MainViewport()
dockspaceID := imgui.DockSpaceOverViewport()
if !u.initialized {
imgui.InternalDockBuilderRemoveNode(dockspaceID)
imgui.InternalDockBuilderAddNodeV(dockspaceID, imgui.DockNodeFlagsNone)
imgui.InternalDockBuilderSetNodeSize(dockspaceID, viewport.Size())
/*
Step 1)
Split root dockspace
╔══════════════╗ ╔═══════╤═══════╗
║ ║ ║ │ ║
║ root ║ → ║ L ↔ R ║
║ ║ ║ │ ║
╚══════════════╝ ╚═══════╧═══════╝
*/
dockspaceIDMainRight := imgui.DockSpace(10)
dockspaceIDMainLeft := imgui.DockSpace(20)
imgui.InternalDockBuilderSplitNode(dockspaceID, imgui.DirRight, .2,
&dockspaceIDMainRight, &dockspaceIDMainLeft)
/*
Step 2)
Split right dockspace
╔═══════╦═══════╗ ╔═══════╦═════════╗
║ ║ ║ ║ ║ RT ║
║ L ║ R ║ → ║ L ╟────↕────╢
║ ║ ║ ║ ║ RB ║
╚═══════╩═══════╝ ╚═══════╩═════════╝
*/
dockspaceIDMainRightTop := imgui.DockSpace(30)
dockspaceIDMainRightBottom := imgui.DockSpace(40)
imgui.InternalDockBuilderSplitNode(dockspaceIDMainRight, imgui.DirUp, .35,
&dockspaceIDMainRightTop, &dockspaceIDMainRightBottom)
/*
Step 3)
Dock windows into RT & RB by name
╔═══════╦════════╗ ╔════════╦══════════╗
║ ║ ║ ║ ║ ╒══════╕ ║
║ ║ RT ║ ║ ║ │ wRT │ ║
║ ║ ║ ║ ║ └──────┘ ║
║ L ╠════════╣ → ║ L ╠══════════╣
║ ║ ║ ║ ║ ╒══════╕ ║
║ ║ RB ║ ║ ║ │ wRB │ ║
║ ║ ║ ║ ║ └──────┘ ║
╚═══════╩════════╝ ╚════════╩══════════╝
*/
imgui.InternalDockBuilderDockWindow("context", dockspaceIDMainRightTop)
imgui.InternalDockBuilderDockWindow("status", dockspaceIDMainRightBottom)
/*
Step 4)
Split left dockspace
╔════════╦══════════╗ ╔═════════╦══════════╗
║ ║ ╒══════╕ ║ ║ ║ ╒══════╕ ║
║ ║ │ wRT │ ║ ║ LT ║ │ wRT │ ║
║ ║ └──────┘ ║ ║ ║ └──────┘ ║
║ L ╠══════════╣ → ╟────↕────╠══════════╣
║ ║ ╒══════╕ ║ ║ ║ ╒══════╕ ║
║ ║ │ wRB │ ║ ║ LB ║ │ wRB │ ║
║ ║ └──────┘ ║ ║ ║ └──────┘ ║
╚════════╩══════════╝ ╚═════════╩══════════╝
*/
dockspaceIDMainLeftTop, dockspaceIDMainLeftBottom := imgui.DockSpace(50), imgui.DockSpace(60)
imgui.InternalDockBuilderSplitNode(dockspaceIDMainLeft, imgui.DirDown, .3,
&dockspaceIDMainLeftBottom, &dockspaceIDMainLeftTop)
/*
Dock 2 windows into LT by name
Before: After:
╔════════╦══════════╗ ╔═════════════╦══════════╗
║ ║ ╒══════╕ ║ ║ ╒════════╕ ║ ╒══════╕ ║
║ ║ │ │ ║ ║ ╒╧═══════╕│ ║ │ │ ║
║ LT ║ │ wRT │ ║ ║ │ wLT1 & ││ ║ │ wRT │ ║
║ ║ │ │ ║ ║ │ wLT2 ├┘ ║ │ │ ║
║ ║ └──────┘ ║ ║ └────────┘ ║ └──────┘ ║
╠════════╬══════════╣ → ╠═════════════╬══════════╣
║ ║ ╒══════╕ ║ ║ ║ ╒══════╕ ║
║ ║ │ │ ║ ║ ║ │ │ ║
║ LB ║ │ wRB │ ║ ║ LB ║ │ wRB │ ║
║ ║ │ │ ║ ║ ║ │ │ ║
║ ║ └──────┘ ║ ║ ║ └──────┘ ║
╚════════╩══════════╝ ╚═════════════╩══════════╝
*/
imgui.InternalDockBuilderDockWindow("content", dockspaceIDMainLeftTop)
imgui.InternalDockBuilderDockWindow("editor", dockspaceIDMainLeftTop)
imgui.InternalDockBuilderDockWindow("settings", dockspaceIDMainLeftTop)
/*
Split LB
╔═════════════╦══════════╗ ╔══════════════════╦══════════╗
║ ╒════════╕ ║ ╒══════╕ ║ ║ ╒═══════════╕ ║ ╒══════╕ ║
║ ╒╧═══════╕│ ║ │ │ ║ ║ ╒═╧═════════╕ │ ║ │ │ ║
║ │ wLT1 & ││ ║ │ wRT │ ║ ║ │ wLT1 & │ │ ║ │ wRT │ ║
║ │ wLT2 │┘ ║ │ │ ║ ║ │ wLT2 ├─┘ ║ │ │ ║
║ └────────┘ ║ └──────┘ ║ ║ └───────────┘ ║ └──────┘ ║
╠═════════════╬══════════╣ → ╠═════════╤════════╬══════════╣
║ ║ ╒══════╕ ║ ║ │ ║ ╒══════╕ ║
║ ║ │ │ ║ ║ │ ║ │ │ ║
║ LB ║ │ wRB │ ║ ║ LBL ↔ LBR ║ │ wRB │ ║
║ ║ │ │ ║ ║ │ ║ │ │ ║
║ ║ └──────┘ ║ ║ │ ║ └──────┘ ║
╚═════════════╩══════════╝ ╚═════════╧════════╩══════════╝
*/
dockspaceIDMainLeftBottomLeft, dockspaceIDMainLeftBottomRight := imgui.DockSpace(70), imgui.DockSpace(80)
imgui.InternalDockBuilderSplitNode(dockspaceIDMainLeftBottom, imgui.DirLeft, .25,
&dockspaceIDMainLeftBottomLeft, &dockspaceIDMainLeftBottomRight)
/*
Dock 2 windows into LBR by name and one into LBL
╔══════════════════╦══════════╗ ╔════════════════════════════╦══════════╗
║ ╒═══════════╕ ║ ╒══════╕ ║ ║ ╒══════════════════════╕ ║ ╒══════╕ ║
║ ╒═╧═════════╕ │ ║ │ │ ║ ║ ╒═╧════════════════════╕ │ ║ │ │ ║
║ │ wLT1 & │ │ ║ │ wRT │ ║ ║ │ wLT1 & │ │ ║ │ wRT │ ║
║ │ wLT2 ├─┘ ║ │ │ ║ ║ │ wLT2 ├─┘ ║ │ │ ║
║ └───────────┘ ║ └──────┘ ║ ║ └──────────────────────┘ ║ └──────┘ ║
╠═════════╦════════╬══════════╣ → ╠═════════════╦══════════════╬══════════╣
║ ║ ║ ╒══════╕ ║ ║ ╒═════════╕ ║ ╒═════════╕ ║ ╒══════╕ ║
║ ║ ║ │ │ ║ ║ │ │ ║ ╒╧════════╕│ ║ │ │ ║
║ LBL ║ LBR ║ │ wRB │ ║ ║ │ wLBL │ ║ │ wLBR1 & ││ ║ │ wRB │ ║
║ ║ ║ │ │ ║ ║ │ │ ║ │ wLBR2 ├┘ ║ │ │ ║
║ ║ ║ └──────┘ ║ ║ └─────────┘ ║ └─────────┘ ║ └──────┘ ║
╚═════════╩════════╩══════════╝ ╚═════════════╩══════════════╩══════════╝
*/
imgui.InternalDockBuilderDockWindow("properties", dockspaceIDMainLeftBottomLeft)
imgui.InternalDockBuilderDockWindow("docker", dockspaceIDMainLeftBottomLeft)
imgui.InternalDockBuilderDockWindow("console", dockspaceIDMainLeftBottomRight)
imgui.InternalDockBuilderFinish(dockspaceID)
u.initialized = true
}
}
I'm not 100% on the ID assignments, as I ran into panics while putting this together. my guess is that i tried to use an ID that was already in use, but not sure what it belonged to. Maybe wouldn't be an issue if you're using larger more arbitrary numbers?
The windows that get docked are by name, so if you wanted to populate the "console" window for instance, you would create this window after docking had been set up:
type windowFlags struct {
noTitlebar bool
noScrollbar bool
noMenu bool
noMove bool
noResize bool
noCollapse bool
noNav bool
noBackground bool
noBringToFront bool
noHorizontalScrollbar bool
noDocking bool
}
type Window struct {
flags windowFlags
noClose bool
collapsed *bool
open *bool
}
func (w windowFlags) combined() imgui.WindowFlags {
flags := 0
if w.noTitlebar {
flags |= imgui.WindowFlagsNoTitleBar
}
if w.noScrollbar {
flags |= imgui.WindowFlagsNoScrollbar
}
if !w.noMenu {
flags |= imgui.WindowFlagsMenuBar
}
if w.noMove {
flags |= imgui.WindowFlagsNoMove
}
if w.noResize {
flags |= imgui.WindowFlagsNoResize
}
if w.noCollapse {
flags |= imgui.WindowFlagsNoCollapse
}
if w.noNav {
flags |= imgui.WindowFlagsNoNav
}
if w.noBackground {
flags |= imgui.WindowFlagsNoBackground
}
if w.noBringToFront {
flags |= imgui.WindowFlagsNoBringToFrontOnFocus
}
if !w.noHorizontalScrollbar {
flags |= imgui.WindowFlagsHorizontalScrollbar
}
if w.noDocking {
flags |= imgui.WindowFlagsNoDocking
}
return imgui.WindowFlags(flags)
}
func MakeConsoleWindow() *Window {
w := &Window{
flags: windowFlags{
noTitlebar: false,
noScrollbar: false,
noMenu: true,
noMove: false,
noResize: false,
noCollapse: false,
noNav: false,
noBackground: false,
noBringToFront: false,
noHorizontalScrollbar: false,
noDocking: false,
},
noClose: false,
collapsed: &consoleWindowCollapsed,
open: &consoleWindowOpen,
}
imgui.BeginV("console", w.open, w.flags.combined())
imgui.Text("I'm the console area.")
imgui.End()
return w
}
I'm not 100% on the ID assignments, as I ran into panics while putting this together. my guess is that i tried to use an ID that was already in use, but not sure what it belonged to.
You should use GetID("something") to generate a valid ID. Random integers will technically work but quite not recommended.
@ocornut Thank you! I was not aware that I could use it that way. That will make things way less confusing.
Edit: just to clarify for those using cimgui-go, this means to use imgui.IDStr("something")
instead of imgui.DockSpace(N)
I would really like to know how to create window within previous window, example seem to not have such functionality