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
1112namespace 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
8279void 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
0 commit comments