Skip to content

Commit 8b0025a

Browse files
committed
now have dockable panels
1 parent adac16d commit 8b0025a

File tree

4 files changed

+181
-77
lines changed

4 files changed

+181
-77
lines changed

src/imgui/Imgui.cpp

Lines changed: 165 additions & 76 deletions
Original file line numberDiff line numberDiff line change
@@ -5,98 +5,187 @@
55
#include "Imgui.hpp"
66

77
#include <imgui.h>
8+
#include <imgui_internal.h>
89
#include <imgui_impl_glfw.h>
910
#include <imgui_impl_vulkan.h>
1011

1112
namespace reactor {
1213

13-
Imgui::Imgui(VulkanContext &vulkanContext, Window &window)
14-
: m_device(vulkanContext.device())
15-
{
16-
IMGUI_CHECKVERSION();
17-
ImGui::CreateContext();
18-
ImGuiIO &io = ImGui::GetIO(); (void)io;
19-
ImGui::StyleColorsDark();
20-
21-
// --- Initialize descriptor pool for ImGui ---
22-
VkDescriptorPoolSize pool_sizes[] =
23-
{
24-
{ VK_DESCRIPTOR_TYPE_SAMPLER, 1000 },
25-
{ VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1000 },
26-
{ VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, 1000 },
27-
{ VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, 1000 },
28-
{ VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER, 1000 },
29-
{ VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER, 1000 },
30-
{ VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 1000 },
31-
{ VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1000 },
32-
{ VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC, 1000 },
33-
{ VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC, 1000 },
34-
{ VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT, 1000 }
35-
};
36-
VkDescriptorPoolCreateInfo pool_info = {};
37-
pool_info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO;
38-
pool_info.flags = VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT;
39-
pool_info.maxSets = 1000 * IM_ARRAYSIZE(pool_sizes);
40-
pool_info.poolSizeCount = (uint32_t)IM_ARRAYSIZE(pool_sizes);
41-
pool_info.pPoolSizes = pool_sizes;
42-
43-
// create the pool
44-
m_descriptorPool = vulkanContext.device().createDescriptorPool(pool_info);
45-
46-
// GLFW backend init
47-
ImGui_ImplGlfw_InitForVulkan(window.getNativeWindow(), true);
48-
49-
auto colorAttachmentFormat = vk::Format::eB8G8R8A8Srgb;
50-
51-
vk::PipelineRenderingCreateInfo renderingInfo{};
52-
renderingInfo.colorAttachmentCount = 1;
53-
renderingInfo.pColorAttachmentFormats = &colorAttachmentFormat;
54-
renderingInfo.viewMask = 0;
55-
renderingInfo.depthAttachmentFormat = vk::Format::eUndefined;
56-
renderingInfo.stencilAttachmentFormat = vk::Format::eUndefined;
57-
58-
ImGui_ImplVulkan_InitInfo initInfo{};
59-
initInfo.Instance = vulkanContext.instance();
60-
initInfo.PhysicalDevice = vulkanContext.physicalDevice();
61-
initInfo.Device = vulkanContext.device();
62-
initInfo.QueueFamily = vulkanContext.queueFamilies().graphicsFamily.value();
63-
initInfo.Queue = vulkanContext.graphicsQueue();
64-
initInfo.PipelineCache = nullptr;
65-
initInfo.DescriptorPool = m_descriptorPool;
66-
initInfo.MinImageCount = 3;
67-
initInfo.ImageCount = 3;
68-
initInfo.UseDynamicRendering = true;
69-
initInfo.PipelineRenderingCreateInfo = renderingInfo;
70-
71-
ImGui_ImplVulkan_Init(&initInfo);
72-
}
73-
14+
Imgui::Imgui(VulkanContext &vulkanContext, Window &window) : m_device(vulkanContext.device()) {
15+
IMGUI_CHECKVERSION();
16+
ImGui::CreateContext();
17+
ImGuiIO &io = ImGui::GetIO();
18+
(void)io;
19+
io.ConfigFlags |= ImGuiConfigFlags_DockingEnable;
20+
ImGui::StyleColorsDark();
21+
22+
// --- Initialize descriptor pool for ImGui ---
23+
VkDescriptorPoolSize pool_sizes[] = {{VK_DESCRIPTOR_TYPE_SAMPLER, 1000},
24+
{VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1000},
25+
{VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, 1000},
26+
{VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, 1000},
27+
{VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER, 1000},
28+
{VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER, 1000},
29+
{VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 1000},
30+
{VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1000},
31+
{VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC, 1000},
32+
{VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC, 1000},
33+
{VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT, 1000}};
34+
VkDescriptorPoolCreateInfo pool_info = {};
35+
pool_info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO;
36+
pool_info.flags = VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT;
37+
pool_info.maxSets = 1000 * IM_ARRAYSIZE(pool_sizes);
38+
pool_info.poolSizeCount = (uint32_t)IM_ARRAYSIZE(pool_sizes);
39+
pool_info.pPoolSizes = pool_sizes;
40+
41+
// create the pool
42+
m_descriptorPool = vulkanContext.device().createDescriptorPool(pool_info);
43+
44+
// GLFW backend init
45+
ImGui_ImplGlfw_InitForVulkan(window.getNativeWindow(), true);
46+
47+
auto colorAttachmentFormat = vk::Format::eB8G8R8A8Srgb;
48+
49+
vk::PipelineRenderingCreateInfo renderingInfo{};
50+
renderingInfo.colorAttachmentCount = 1;
51+
renderingInfo.pColorAttachmentFormats = &colorAttachmentFormat;
52+
renderingInfo.viewMask = 0;
53+
renderingInfo.depthAttachmentFormat = vk::Format::eUndefined;
54+
renderingInfo.stencilAttachmentFormat = vk::Format::eUndefined;
55+
56+
ImGui_ImplVulkan_InitInfo initInfo{};
57+
initInfo.Instance = vulkanContext.instance();
58+
initInfo.PhysicalDevice = vulkanContext.physicalDevice();
59+
initInfo.Device = vulkanContext.device();
60+
initInfo.QueueFamily = vulkanContext.queueFamilies().graphicsFamily.value();
61+
initInfo.Queue = vulkanContext.graphicsQueue();
62+
initInfo.PipelineCache = nullptr;
63+
initInfo.DescriptorPool = m_descriptorPool;
64+
initInfo.MinImageCount = 3;
65+
initInfo.ImageCount = 3;
66+
initInfo.UseDynamicRendering = true;
67+
initInfo.PipelineRenderingCreateInfo = renderingInfo;
68+
69+
ImGui_ImplVulkan_Init(&initInfo);
70+
}
7471

75-
Imgui::~Imgui() {
72+
Imgui::~Imgui() {
7673

77-
ImGui_ImplGlfw_Shutdown();
78-
ImGui_ImplVulkan_Shutdown();
79-
m_device.destroyDescriptorPool(m_descriptorPool);
80-
}
74+
ImGui_ImplGlfw_Shutdown();
75+
ImGui_ImplVulkan_Shutdown();
76+
m_device.destroyDescriptorPool(m_descriptorPool);
77+
}
8178

8279
void Imgui::createFrame() {
8380
ImGui_ImplVulkan_NewFrame();
8481
ImGui_ImplGlfw_NewFrame();
8582
ImGui::NewFrame();
86-
//ImGui::ShowDemoWindow();
87-
ImGui::Begin("Composite");
88-
ImGui::SliderFloat("Exposure", &m_exposure, 0.0, 2.0);
89-
ImGui::SliderFloat("Contrast", &m_contrast, 0.0, 2.0);
90-
ImGui::SliderFloat("Saturation", &m_saturation, 0.0, 2.0);
9183

92-
ImGui::End();
84+
ShowDockspace();
85+
ShowSceneView();
86+
ShowInspector();
87+
ShowConsole();
88+
}
89+
90+
void Imgui::drawFrame(vk::CommandBuffer commandBuffer) {
91+
ImGui::Render();
92+
ImGui_ImplVulkan_RenderDrawData(ImGui::GetDrawData(), commandBuffer);
93+
}
94+
95+
void Imgui::ShowDockspace() {
96+
static ImGuiDockNodeFlags dockspace_flags = ImGuiDockNodeFlags_PassthruCentralNode;
97+
98+
ImGuiWindowFlags window_flags = ImGuiWindowFlags_MenuBar | ImGuiWindowFlags_NoDocking;
99+
const ImGuiViewport *viewport = ImGui::GetMainViewport();
100+
101+
ImGui::SetNextWindowPos(viewport->Pos);
102+
ImGui::SetNextWindowSize(viewport->Size);
103+
ImGui::SetNextWindowViewport(viewport->ID);
104+
ImGui::PushStyleVar(ImGuiStyleVar_WindowRounding, 0.0f);
105+
ImGui::PushStyleVar(ImGuiStyleVar_WindowBorderSize, 0.0f);
106+
window_flags |= ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoCollapse |
107+
ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoMove;
108+
window_flags |= ImGuiWindowFlags_NoBringToFrontOnFocus | ImGuiWindowFlags_NoNavFocus;
109+
110+
ImGui::Begin("DockSpace Window", nullptr, window_flags);
111+
ImGui::PopStyleVar(2);
112+
113+
// Create dockspace ID
114+
ImGuiID dockspace_id = ImGui::GetID("MyDockSpace");
115+
ImGui::DockSpace(dockspace_id, ImVec2(0.0f, 0.0f), dockspace_flags);
116+
117+
static bool first_time = true;
118+
if (first_time) {
119+
SetupInitialDockLayout(dockspace_id);
120+
first_time = false;
121+
}
122+
123+
ImGui::End();
93124
}
94125

95-
void Imgui::drawFrame(vk::CommandBuffer commandBuffer) {
96-
ImGui::Render();
97-
ImGui_ImplVulkan_RenderDrawData(ImGui::GetDrawData(), commandBuffer);
126+
void Imgui::ShowSceneView() {
127+
ImGui::Begin("Scene View");
128+
ImGui::Text("Scene View");
129+
ImVec2 size = ImGui::GetContentRegionAvail();
130+
131+
if (m_sceneImguiId) {
132+
ImTextureID id;
133+
id = reinterpret_cast<ImTextureID>(static_cast<VkDescriptorSet>(m_sceneImguiId));
134+
135+
ImGui::Image(
136+
id,
137+
size,
138+
ImVec2(0, 1),
139+
ImVec2(1, 0));
140+
} else {
141+
ImGui::Text("No scene image");
98142
}
99143

144+
ImGui::End();
145+
}
146+
147+
void Imgui::ShowInspector() {
148+
ImGui::Begin("Inspector");
149+
ImGui::SliderFloat("Exposure", &m_exposure, 0.0, 2.0);
150+
ImGui::SliderFloat("Contrast", &m_contrast, 0.0, 2.0);
151+
ImGui::SliderFloat("Saturation", &m_saturation, 0.0, 2.0);
152+
ImGui::End();
153+
}
154+
155+
void Imgui::ShowConsole() {
156+
ImGui::Begin("Console");
157+
ImGui::Text("Console");
158+
ImGui::End();
159+
}
160+
161+
void Imgui::SetupInitialDockLayout(ImGuiID dockspace_id) {
162+
ImGui::DockBuilderRemoveNode(dockspace_id); // Clear existing layout
163+
ImGui::DockBuilderAddNode(dockspace_id, ImGuiDockNodeFlags_DockSpace);
164+
ImGui::DockBuilderSetNodeSize(dockspace_id, ImGui::GetMainViewport()->Size);
165+
166+
// Split main dockspace into left (main), right (inspector), and bottom (console)
167+
ImGuiID dock_main = dockspace_id;
168+
ImGuiID dock_right = ImGui::DockBuilderSplitNode(dock_main, ImGuiDir_Right, 0.25f, nullptr, &dock_main);
169+
ImGuiID dock_bottom = ImGui::DockBuilderSplitNode(dock_main, ImGuiDir_Down, 0.25f, nullptr, &dock_main);
170+
171+
// Assign windows to dock nodes
172+
ImGui::DockBuilderDockWindow("Scene View", dock_main);
173+
ImGui::DockBuilderDockWindow("Inspector", dock_right);
174+
ImGui::DockBuilderDockWindow("Console", dock_bottom);
175+
ImGui::DockBuilderDockWindow("Composite", dock_main); // or move to its own panel
100176

177+
ImGui::DockBuilderFinish(dockspace_id);
178+
}
179+
180+
181+
void Imgui::SetSceneImage(vk::ImageView imageView, vk::Sampler sampler) {
182+
183+
if (m_sceneImguiId) {
184+
ImGui_ImplVulkan_RemoveTexture(m_sceneImguiId);
185+
}
186+
187+
m_sceneImguiId = ImGui_ImplVulkan_AddTexture(sampler, imageView, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
188+
189+
}
101190

102-
} // reactor
191+
} // namespace reactor

src/imgui/Imgui.hpp

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@
77
#include "../core/Window.hpp"
88
#include "../vulkan/VulkanContext.hpp"
99

10+
#include <imgui.h>
11+
1012
namespace reactor {
1113

1214
class Imgui {
@@ -21,15 +23,25 @@ class Imgui {
2123
float getContrast() const { return m_contrast; }
2224
float getSaturation() const { return m_saturation; }
2325

26+
void SetSceneImage(vk::ImageView imageView, vk::Sampler sampler);
27+
2428
private:
2529

2630
vk::Device m_device;
2731
vk::DescriptorPool m_descriptorPool;
2832

33+
vk::DescriptorSet m_sceneImguiId;
34+
2935
float m_exposure = 1.0f;
3036
float m_contrast = 1.0f;
3137
float m_saturation = 1.0f;
3238

39+
void ShowDockspace();
40+
void ShowSceneView();
41+
void ShowInspector();
42+
void ShowConsole();
43+
void SetupInitialDockLayout(ImGuiID dockspace_id);
44+
3345
};
3446

3547
} // reactor

src/vulkan/VulkanRenderer.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -345,6 +345,8 @@ void VulkanRenderer::drawFrame() {
345345
// The UI is rendered on top of the composited scene.
346346
// The swapchain image is already in COLOR_ATTACHMENT_OPTIMAL, so no transition is needed.
347347
beginDynamicRendering(cmd, m_swapchain->getImageViews()[imageIndex], extent, false);
348+
349+
m_imgui->SetSceneImage(m_resolveViews[frameIdx], m_sampler->get());
348350
renderUI(cmd);
349351
endDynamicRendering(cmd);
350352

vcpkg.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,8 @@
1212
"name": "imgui",
1313
"features": [
1414
"glfw-binding",
15-
"vulkan-binding"
15+
"vulkan-binding",
16+
"docking-experimental"
1617
]
1718
}
1819
]

0 commit comments

Comments
 (0)