Skip to content

Instantly share code, notes, and snippets.

@marpe
Last active December 14, 2022 18:47
Show Gist options
  • Save marpe/49404475a3c326af43952f8cd3c60645 to your computer and use it in GitHub Desktop.
Save marpe/49404475a3c326af43952f8cd3c60645 to your computer and use it in GitHub Desktop.
ImGui window with splitter using docking
using System;
public abstract class SplitWindow
{
private string _leftTitle;
private string _rightTitle;
private string _dockSpaceId;
private Action _drawLeft;
private Action _drawRight;
public string Title;
private readonly Action<uint> _initializeDockSpace;
protected SplitWindow(string title)
{
_leftTitle = $"{title}_Left";
_rightTitle = $"{title}_Right";
_dockSpaceId = $"{title}_DockSpace";
_drawLeft = DrawLeft;
_drawRight = DrawRight;
_initializeDockSpace = InitializeDockSpace(_leftTitle, _rightTitle);
}
public void Draw(ref bool isOpen)
{
if (!isOpen)
return;
CreateDockSpace(Title, _dockSpaceId, ref isOpen, _initializeDockSpace);
DrawSplit(_leftTitle, _drawLeft);
DrawSplit(_rightTitle, _drawRight);
}
private static void CreateDockSpace(string windowTitle, string dockspaceId, ref bool isOpen, Action<uint> initializeLayout,
ImGuiWindowFlags flags = ImGuiWindowFlags.NoCollapse)
{
ImGui.SetNextWindowSize(new Vector2(800, 850), ImGuiCond.Appearing);
ImGui.SetNextWindowSizeConstraints(new Vector2(200, 200), new Vector2(800, 850));
var result = ImGui.Begin(windowTitle, ImGuiExt.RefPtr(ref isOpen), flags);
SetupDockSpace(dockspaceId, initializeLayout, !result);
ImGui.End();
}
private static Action<uint> InitializeDockSpace(string leftWindowTitle, string rightWindowTitle)
{
return dockspaceID =>
{
var rightDockID = 0u;
var leftDockID = 0u;
ImGuiInternal.DockBuilderSplitNode(dockspaceID, ImGuiDir.Left, 0.5f, &leftDockID, &rightDockID);
ImGuiInternal.DockBuilderDockWindow(leftWindowTitle, leftDockID);
ImGuiInternal.DockBuilderDockWindow(rightWindowTitle, rightDockID);
};
}
private static void DrawSplit(string title, Action drawContent)
{
if (ImGui.Begin(title))
{
drawContent();
}
SetDockSpaceFlags();
ImGui.End();
}
private static void SetDockSpaceFlags()
{
var dockNode = ImGuiInternal.GetWindowDockNode();
if (dockNode != null)
{
dockNode->LocalFlags = 0;
dockNode->LocalFlags |= (ImGuiDockNodeFlags)(ImGuiDockNodeFlagsPrivate_.ImGuiDockNodeFlags_NoDockingSplitMe);
dockNode->LocalFlags |= (ImGuiDockNodeFlags)(ImGuiDockNodeFlagsPrivate_.ImGuiDockNodeFlags_NoDockingOverMe);
dockNode->LocalFlags |= (ImGuiDockNodeFlags)(ImGuiDockNodeFlagsPrivate_.ImGuiDockNodeFlags_NoTabBar);
}
}
protected abstract void DrawLeft();
protected abstract void DrawRight();
private static void SetupDockSpace(string dockspaceId, Action<uint> setupCallback, bool keepAlive = false)
{
var dockspaceID = ImGui.GetID(dockspaceId);
ImGuiWindowClass workspaceWindowClass;
workspaceWindowClass.ClassId = dockspaceID;
workspaceWindowClass.DockingAllowUnclassed = false;
if (ImGuiInternal.DockBuilderGetNode(dockspaceID) == null)
{
var dockFlags = ImGuiDockNodeFlagsPrivate_.ImGuiDockNodeFlags_DockSpace |
ImGuiDockNodeFlagsPrivate_.ImGuiDockNodeFlags_NoWindowMenuButton |
ImGuiDockNodeFlagsPrivate_.ImGuiDockNodeFlags_NoCloseButton;
ImGuiInternal.DockBuilderAddNode(dockspaceID, (ImGuiDockNodeFlags)dockFlags);
var contentAvail = ImGui.GetContentRegionAvail();
var size = new Num.Vector2(MathF.Max(4.0f, contentAvail.X), MathF.Max(4.0f, contentAvail.Y));
ImGuiInternal.DockBuilderSetNodeSize(dockspaceID, size);
//
setupCallback.Invoke(dockspaceID);
//
ImGuiInternal.DockBuilderFinish(dockspaceID);
}
var flags = keepAlive ? ImGuiDockNodeFlags.KeepAliveOnly : ImGuiDockNodeFlags.None | ImGuiDockNodeFlags.NoSplit;
ImGui.DockSpace(dockspaceID, new Num.Vector2(0.0f, 0.0f), flags, &workspaceWindowClass);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment