cimgui-go icon indicating copy to clipboard operation
cimgui-go copied to clipboard

Initial docking example?

Open maxsupermanhd opened this issue 2 years ago • 6 comments

I would really like to know how to create window within previous window, example seem to not have such functionality

maxsupermanhd avatar Sep 16 '23 20:09 maxsupermanhd

Any updates on that?

maxsupermanhd avatar Dec 02 '23 22:12 maxsupermanhd

I think you could check the Imgui for a demo, and use almost the same API here.

AllenDang avatar Dec 04 '23 02:12 AllenDang

@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). image

CC @ocornut

gucio321 avatar Dec 17 '23 17:12 gucio321

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
}

damntourists avatar Jan 19 '24 17:01 damntourists

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 avatar Jan 20 '24 11:01 ocornut

@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)

damntourists avatar Jan 21 '24 04:01 damntourists