Skip to content

Commit f3920d9

Browse files
committed
WIP: fixes to editor navbar
1 parent aede6e3 commit f3920d9

5 files changed

Lines changed: 173 additions & 47 deletions

File tree

Core/Source/Lux/Core/Window.cpp

Lines changed: 20 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -423,6 +423,13 @@ namespace Lux {
423423

424424
void Window::Shutdown()
425425
{
426+
if (m_SwapChain)
427+
{
428+
m_SwapChain->Destroy();
429+
ldelete m_SwapChain;
430+
m_SwapChain = nullptr;
431+
}
432+
426433
if (m_WindowSurface)
427434
{
428435
auto vInstance = ((VulkanDeviceManager*)m_DeviceManager)->GetVulkanInstance();
@@ -431,13 +438,21 @@ namespace Lux {
431438
m_WindowSurface = nullptr;
432439
}
433440

434-
m_DeviceManager->Shutdown();
435-
ldelete m_DeviceManager;
441+
if (m_DeviceManager)
442+
{
443+
m_DeviceManager->Shutdown();
444+
ldelete m_DeviceManager;
445+
m_DeviceManager = nullptr;
446+
}
447+
448+
if (m_WindowHandle)
449+
{
450+
glfwDestroyWindow(m_WindowHandle);
451+
m_WindowHandle = nullptr;
452+
}
436453

437-
// m_SwapChain->Destroy();
438-
// hdelete m_SwapChain;
439454
// m_RendererContext.As<VulkanContext>()->GetDevice()->Destroy(); // need to destroy the device _before_ windows window destructor destroys the renderer context (because device Destroy() asks for renderer context...)
440-
// glfwTerminate();
455+
glfwTerminate();
441456
s_GLFWInitialized = false;
442457
}
443458

Core/Source/Lux/ImGui/ImGuiLayer.cpp

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -185,6 +185,15 @@ namespace Lux {
185185

186186
void ImGuiLayer::OnDetach()
187187
{
188+
if (ImGui::GetCurrentContext())
189+
{
190+
ImGuiIO& io = ImGui::GetIO();
191+
if (io.ConfigFlags & ImGuiConfigFlags_ViewportsEnable)
192+
ImGui::DestroyPlatformWindows();
193+
}
194+
195+
m_ImGuiRenderer.reset();
196+
ImGui_ImplGlfw_Shutdown();
188197
ImGui::DestroyContext();
189198
}
190199

Core/Source/Lux/Platform/Vulkan/VulkanImGuiLayer.cpp

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -199,7 +199,14 @@ namespace Lux {
199199
ImGui::DestroyContext();
200200
});
201201
#else
202-
// Device wait is now handled in Renderer::Shutdown via DeviceManager
202+
if (ImGui::GetCurrentContext())
203+
{
204+
ImGuiIO& io = ImGui::GetIO();
205+
if (io.ConfigFlags & ImGuiConfigFlags_ViewportsEnable)
206+
ImGui::DestroyPlatformWindows();
207+
}
208+
209+
// Device wait is handled in Renderer::Shutdown via DeviceManager.
203210
ImGui_ImplGlfw_Shutdown();
204211
ImGui::DestroyContext();
205212
#endif

Core/Source/Lux/Renderer/Renderer.cpp

Lines changed: 22 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -587,11 +587,13 @@ namespace Lux {
587587
s_ShaderDependencies.clear();
588588
}
589589

590-
// Wait for device to become idle before cleanup
591590
auto* deviceManager = Application::Get().GetWindow().GetDeviceManager();
592-
if (deviceManager && deviceManager->GetDevice())
591+
nvrhi::DeviceHandle graphicsDevice = deviceManager ? deviceManager->GetDevice() : nullptr;
592+
593+
// Wait for device to become idle before cleanup.
594+
if (graphicsDevice)
593595
{
594-
VkDevice device = (VkDevice)deviceManager->GetDevice()->getNativeObject(nvrhi::ObjectTypes::VK_Device);
596+
VkDevice device = (VkDevice)graphicsDevice->getNativeObject(nvrhi::ObjectTypes::VK_Device);
595597
vkDeviceWaitIdle(device);
596598
}
597599

@@ -604,13 +606,30 @@ namespace Lux {
604606

605607
delete s_Data;
606608

609+
// The render thread has already stopped during application shutdown.
610+
// Drain any resource-free commands queued by destructors on the main thread
611+
// before running the per-frame release queues.
612+
for (uint32_t i = 0; i < s_RenderCommandQueueCount; i++)
613+
{
614+
if (s_CommandQueue[i])
615+
s_CommandQueue[i]->Execute();
616+
}
617+
607618
// Resource release queue
608619
for (uint32_t i = 0; i < s_Config.FramesInFlight; i++)
609620
{
610621
auto& queue = Renderer::GetRenderResourceReleaseQueue(i);
611622
queue.Execute();
612623
}
613624

625+
if (graphicsDevice)
626+
{
627+
graphicsDevice->waitForIdle();
628+
graphicsDevice->runGarbageCollection();
629+
graphicsDevice->waitForIdle();
630+
graphicsDevice->runGarbageCollection();
631+
}
632+
614633
delete s_CommandQueue[0];
615634
delete s_CommandQueue[1];
616635
}

Editor/Source/EditorLayer.cpp

Lines changed: 114 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -1180,7 +1180,10 @@ namespace Lux {
11801180

11811181
ImGui::Separator();
11821182
if (ImGui::MenuItem("Exit"))
1183-
Application::Get().DispatchEvent<WindowCloseEvent, true>();
1183+
Application::Get().QueueEvent([]()
1184+
{
1185+
Application::Get().DispatchEvent<WindowCloseEvent, true>();
1186+
});
11841187

11851188
ImGui::EndMenu();
11861189
}
@@ -1230,28 +1233,32 @@ namespace Lux {
12301233
const ImVec2 windowPos = window->Pos;
12311234
const ImVec2 windowMax = ImVec2(window->Pos.x + window->Size.x, window->Pos.y + m_TitlebarHeight);
12321235

1233-
ImU32 targetTitlebarColor = Colors::Theme::titlebar;
1236+
ImU32 stateAccentColor = Colors::Theme::titlebar;
12341237
if (m_SceneState == SceneState::Play)
1235-
targetTitlebarColor = Colors::Theme::titlebarOrange;
1238+
stateAccentColor = Colors::Theme::titlebarGreen;
12361239
else if (m_SceneState == SceneState::Simulate)
1237-
targetTitlebarColor = Colors::Theme::titlebarGreen;
1240+
stateAccentColor = Colors::Theme::titlebarOrange;
12381241

1239-
const ImVec4 targetColor = ImGui::ColorConvertU32ToFloat4(targetTitlebarColor);
1242+
const ImVec4 targetColor = ImGui::ColorConvertU32ToFloat4(stateAccentColor);
12401243
const float dt = ImGui::GetIO().DeltaTime;
12411244
m_AnimatedTitlebarColor = ImLerp(m_AnimatedTitlebarColor, targetColor, std::clamp(dt * 8.0f, 0.0f, 1.0f));
1242-
drawList->AddRectFilled(windowPos, windowMax, ImGui::ColorConvertFloat4ToU32(m_AnimatedTitlebarColor));
1245+
const ImU32 activeTitlebarColor = ImGui::ColorConvertFloat4ToU32(m_AnimatedTitlebarColor);
1246+
drawList->AddRectFilled(windowPos, windowMax, Colors::Theme::titlebar);
1247+
drawList->AddRectFilledMultiColor(windowPos, ImVec2(windowPos.x + 380.0f, windowMax.y),
1248+
activeTitlebarColor, Colors::Theme::titlebar, Colors::Theme::titlebar, activeTitlebarColor);
12431249

12441250
drawList->AddLine(ImVec2(windowPos.x, windowPos.y + m_TitlebarHeight), ImVec2(windowPos.x + window->Size.x, windowPos.y + m_TitlebarHeight), Colors::Theme::backgroundDark);
12451251

1246-
const float logoPadding = 16.0f;
1247-
const float logoSize = 30.0f;
1248-
const float logoTop = (m_TitlebarHeight - logoSize) * 0.5f;
1249-
const ImVec2 logoMin(windowPos.x + logoPadding, windowPos.y + logoTop);
1250-
const ImVec2 logoMax(logoMin.x + logoSize, logoMin.y + logoSize);
12511252
if (EditorResources::HazelLogoTexture)
1253+
{
1254+
const float logoWidth = (float)EditorResources::HazelLogoTexture->GetWidth();
1255+
const float logoHeight = (float)EditorResources::HazelLogoTexture->GetHeight();
1256+
const ImVec2 logoMin(windowPos.x + 14.0f, windowPos.y + 6.0f);
1257+
const ImVec2 logoMax(logoMin.x + logoWidth, logoMin.y + logoHeight);
12521258
drawList->AddImage(GetImGuiTextureID(EditorResources::HazelLogoTexture), logoMin, logoMax);
1259+
}
12531260

1254-
const float menuBarX = logoPadding * 2.0f + logoSize + 8.0f;
1261+
const float menuBarX = 16.0f * 2.0f + 41.0f;
12551262
ImGui::SetCursorPos(ImVec2(menuBarX, 4.0f));
12561263
UI_DrawMenubar();
12571264

@@ -1268,15 +1275,63 @@ namespace Lux {
12681275
GLFWwindow* nativeWindow = Application::Get().GetWindow().GetNativeWindow();
12691276
const bool isMaximized = nativeWindow && glfwGetWindowAttrib(nativeWindow, GLFW_MAXIMIZED);
12701277

1271-
const float controlsWidth = 120.0f;
1278+
const float iconWidth = 14.0f;
1279+
const float iconHeight = 14.0f;
1280+
const float buttonWidth = 46.0f;
1281+
const float buttonHeight = m_TitlebarHeight;
1282+
const float buttonY = 0.0f;
1283+
const float closeButtonX = window->Size.x - buttonWidth;
1284+
const float maximizeButtonX = closeButtonX - buttonWidth;
1285+
const float minimizeButtonX = maximizeButtonX - buttonWidth;
1286+
const float titlebarGap = 12.0f;
1287+
1288+
const std::string projectName = GetProjectDisplayName();
1289+
const float projectBoxPaddingX = 10.0f;
1290+
const float projectBoxHeight = 26.0f;
1291+
const float projectBoxMinWidth = 76.0f;
1292+
const float projectBoxMaxX = minimizeButtonX - titlebarGap;
1293+
const float sceneNameRightX = ((window->Size.x - sceneNameSize.x) * 0.5f) + sceneNameSize.x;
1294+
const float projectBoxMinAllowedX = std::max(menuBarX + 280.0f, sceneNameRightX + 28.0f);
1295+
const float maxProjectBoxWidth = projectBoxMaxX - projectBoxMinAllowedX;
1296+
1297+
bool drawProjectBox = maxProjectBoxWidth >= projectBoxMinWidth;
1298+
std::string displayedProjectName = projectName;
1299+
float projectBoxWidth = 0.0f;
1300+
if (drawProjectBox)
1301+
{
1302+
const float maxProjectTextWidth = std::max(0.0f, maxProjectBoxWidth - projectBoxPaddingX * 2.0f);
1303+
if (ImGui::CalcTextSize(displayedProjectName.c_str()).x > maxProjectTextWidth)
1304+
{
1305+
const std::string ellipsis = "...";
1306+
while (!displayedProjectName.empty())
1307+
{
1308+
const std::string candidate = displayedProjectName + ellipsis;
1309+
if (ImGui::CalcTextSize(candidate.c_str()).x <= maxProjectTextWidth)
1310+
{
1311+
displayedProjectName = candidate;
1312+
break;
1313+
}
1314+
displayedProjectName.pop_back();
1315+
}
1316+
if (displayedProjectName.empty())
1317+
drawProjectBox = false;
1318+
}
1319+
1320+
if (drawProjectBox)
1321+
projectBoxWidth = std::min(ImGui::CalcTextSize(displayedProjectName.c_str()).x + projectBoxPaddingX * 2.0f, maxProjectBoxWidth);
1322+
}
1323+
1324+
const float projectBoxMinX = drawProjectBox ? projectBoxMaxX - projectBoxWidth : projectBoxMaxX;
12721325
const float dragZoneMinX = 70.0f;
1273-
const float dragZoneMaxX = window->Size.x - controlsWidth - 220.0f;
1326+
const float dragZoneMaxX = std::max(dragZoneMinX, (drawProjectBox ? projectBoxMinX : minimizeButtonX) - titlebarGap);
12741327
ImGui::SetCursorPos(ImVec2(dragZoneMinX, 0.0f));
12751328
ImGui::InvisibleButton("##titleBarDragZone", ImVec2(std::max(0.0f, dragZoneMaxX - dragZoneMinX), m_TitlebarHeight));
12761329
const ImVec2 dragMin = ImGui::GetItemRectMin();
12771330
const ImVec2 dragMax = ImGui::GetItemRectMax();
12781331
m_TitleBarDragRectMin = ImVec2(dragMin.x - windowPos.x, dragMin.y - windowPos.y);
12791332
m_TitleBarDragRectMax = ImVec2(dragMax.x - windowPos.x, dragMax.y - windowPos.y);
1333+
m_TitleBarDragRectMin = ImVec2(dragZoneMinX, 0.0f);
1334+
m_TitleBarDragRectMax = ImVec2(dragZoneMaxX, m_TitlebarHeight);
12801335

12811336
#if !defined(LUX_PLATFORM_WINDOWS)
12821337
if (nativeWindow && !isMaximized && ImGui::IsItemActive() && ImGui::IsMouseDragging(ImGuiMouseButton_Left))
@@ -1288,39 +1343,57 @@ namespace Lux {
12881343
}
12891344
#endif
12901345

1291-
const std::string projectName = GetProjectDisplayName();
1292-
const ImVec2 projectNameSize = ImGui::CalcTextSize(projectName.c_str());
1293-
const ImVec2 projectBoxMin(windowPos.x + window->Size.x - controlsWidth - projectNameSize.x - 36.0f, windowPos.y + 14.0f);
1294-
const ImVec2 projectBoxMax(projectBoxMin.x + projectNameSize.x + 20.0f, projectBoxMin.y + 26.0f);
1295-
drawList->AddRect(projectBoxMin, projectBoxMax, Colors::Theme::muted, 6.0f, 0, 1.0f);
1296-
drawList->AddText(ImVec2(projectBoxMin.x + 10.0f, projectBoxMin.y + 5.0f), Colors::Theme::text, projectName.c_str());
1297-
1298-
const float buttonSize = 34.0f;
1299-
const float buttonY = (m_TitlebarHeight - buttonSize) * 0.5f;
1300-
const float buttonsStartX = window->Size.x - controlsWidth;
1301-
const ImU32 normalTint = IM_COL32(220, 220, 220, 220);
1302-
const ImU32 hoverTint = IM_COL32(255, 255, 255, 255);
1303-
const ImU32 activeTint = IM_COL32(200, 200, 200, 255);
1346+
if (drawProjectBox)
1347+
{
1348+
const ImVec2 projectBoxMin(windowPos.x + projectBoxMinX, windowPos.y + 14.0f);
1349+
const ImVec2 projectBoxMax(projectBoxMin.x + projectBoxWidth, projectBoxMin.y + projectBoxHeight);
1350+
drawList->AddRect(projectBoxMin, projectBoxMax, Colors::Theme::muted, 6.0f, 0, 1.0f);
1351+
drawList->AddText(ImVec2(projectBoxMin.x + projectBoxPaddingX, projectBoxMin.y + 5.0f), Colors::Theme::text, displayedProjectName.c_str());
1352+
}
1353+
1354+
const ImU32 buttonColN = ImGuiEx::ColourWithMultipliedValue(Colors::Theme::text, 0.9f);
1355+
const ImU32 buttonColH = ImGuiEx::ColourWithMultipliedValue(Colors::Theme::text, 1.2f);
1356+
const ImU32 buttonColP = Colors::Theme::textDarker;
13041357

13051358
auto drawWindowControlButton = [&](const char* id, const Ref<Texture2D>& icon, float localX, auto&& onClick)
13061359
{
13071360
ImGui::SetCursorPos(ImVec2(localX, buttonY));
1308-
ImGui::InvisibleButton(id, ImVec2(buttonSize, buttonSize));
1361+
ImGui::InvisibleButton(id, ImVec2(buttonWidth, buttonHeight));
13091362
if (icon)
1310-
ImGuiEx::DrawButtonImage(icon, normalTint, hoverTint, activeTint, ImGui::GetItemRectMin(), ImGui::GetItemRectMax(), ImVec2(0.0f, 0.0f), ImVec2(1.0f, 1.0f));
1363+
{
1364+
const ImVec2 buttonMin = ImGui::GetItemRectMin();
1365+
const ImVec2 iconMin(
1366+
buttonMin.x + (buttonWidth - iconWidth) * 0.5f,
1367+
buttonMin.y + (buttonHeight - iconHeight) * 0.5f);
1368+
const ImVec2 iconMax(iconMin.x + iconWidth, iconMin.y + iconHeight);
1369+
ImGuiEx::DrawButtonImage(icon, buttonColN, buttonColH, buttonColP, iconMin, iconMax, ImVec2(0.0f, 0.0f), ImVec2(1.0f, 1.0f));
1370+
}
13111371

13121372
if (ImGui::IsItemClicked(ImGuiMouseButton_Left))
13131373
onClick();
13141374
};
13151375

1316-
drawWindowControlButton("##minimizeWindow", EditorResources::MinimizeIcon, buttonsStartX + 4.0f, [nativeWindow]()
1317-
{
1318-
if (!nativeWindow)
1319-
return;
1376+
ImGui::SetCursorPos(ImVec2(minimizeButtonX, buttonY));
1377+
ImGui::InvisibleButton("##minimizeWindow", ImVec2(buttonWidth, buttonHeight));
1378+
if (EditorResources::MinimizeIcon)
1379+
{
1380+
const float iconHeight = (float)EditorResources::MinimizeIcon->GetHeight();
1381+
const ImVec2 buttonMin = ImGui::GetItemRectMin();
1382+
const float padY = (14.0f - iconHeight) * 0.5f;
1383+
const ImVec2 iconMin(
1384+
buttonMin.x + (buttonWidth - iconWidth) * 0.5f,
1385+
buttonMin.y + (buttonHeight - 14.0f) * 0.5f);
1386+
const ImVec2 iconMax(iconMin.x + iconWidth, iconMin.y + 14.0f);
1387+
ImGuiEx::DrawButtonImage(EditorResources::MinimizeIcon, buttonColN, buttonColH, buttonColP,
1388+
ImGuiEx::RectExpanded(ImRect(iconMin, iconMax), 0.0f, -padY));
1389+
}
1390+
if (ImGui::IsItemClicked(ImGuiMouseButton_Left))
1391+
{
1392+
if (nativeWindow)
13201393
Application::Get().QueueEvent([nativeWindow]() { glfwIconifyWindow(nativeWindow); });
1321-
});
1394+
}
13221395

1323-
drawWindowControlButton("##maximizeRestoreWindow", isMaximized ? EditorResources::RestoreIcon : EditorResources::MaximizeIcon, buttonsStartX + 42.0f, [nativeWindow, isMaximized]()
1396+
drawWindowControlButton("##maximizeRestoreWindow", isMaximized ? EditorResources::RestoreIcon : EditorResources::MaximizeIcon, maximizeButtonX, [nativeWindow, isMaximized]()
13241397
{
13251398
if (!nativeWindow)
13261399
return;
@@ -1329,13 +1402,16 @@ namespace Lux {
13291402
if (isMaximized)
13301403
glfwRestoreWindow(nativeWindow);
13311404
else
1332-
glfwMaximizeWindow(nativeWindow);
1405+
Application::Get().GetWindow().Maximize();
13331406
});
13341407
});
13351408

1336-
drawWindowControlButton("##closeWindow", EditorResources::CloseIcon, buttonsStartX + 80.0f, []()
1409+
drawWindowControlButton("##closeWindow", EditorResources::CloseIcon, closeButtonX, []()
13371410
{
1338-
Application::Get().DispatchEvent<WindowCloseEvent, true>();
1411+
Application::Get().QueueEvent([]()
1412+
{
1413+
Application::Get().DispatchEvent<WindowCloseEvent, true>();
1414+
});
13391415
});
13401416
}
13411417

0 commit comments

Comments
 (0)