Skip to content

Commit 834d737

Browse files
committed
Merge remote-tracking branch 'origin/copilot/implement-hazel-asset-system' into copilot/implement-hazel-asset-system
2 parents 241cc84 + a03f5b4 commit 834d737

6 files changed

Lines changed: 111 additions & 64 deletions

File tree

Editor/Source/EditorLayer.cpp

Lines changed: 32 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,9 @@
2727
#include "Lux/Utilities/FileDialogs.h"
2828
#include "Lux/Math/Math.h"
2929
#include "Panels/TextEditorPanel.h"
30+
#include "Panels/SceneHierarchyPanel.h"
31+
#include "Panels/ContentBrowserPanel.h"
32+
#include "Panels/SceneRendererPanel.h"
3033

3134
namespace Lux {
3235

@@ -125,7 +128,9 @@ namespace Lux {
125128
/////////// Configure Panels ///////////
126129
m_PanelManager = CreateScope<PanelManager>();
127130

128-
m_PanelManager->AddPanel<TextEditorPanel>(PanelCategory::View,"TextEditorPanel","Text Editor",true);
131+
m_PanelManager->AddPanel<SceneHierarchyPanel>(PanelCategory::View, SCENE_HIERARCHY_PANEL_ID, "Scene Hierarchy", true);
132+
m_PanelManager->AddPanel<ContentBrowserPanel>(PanelCategory::View, CONTENT_BROWSER_PANEL_ID, "Content Browser", true);
133+
m_PanelManager->AddPanel<TextEditorPanel>(PanelCategory::View, "TextEditorPanel", "Text Editor", true);
129134

130135
Ref<SceneRendererPanel> sceneRendererPanel = m_PanelManager->AddPanel<SceneRendererPanel>(PanelCategory::View, SCENE_RENDERER_PANEL_ID, "Scene Renderer", true);
131136

@@ -143,9 +148,6 @@ namespace Lux {
143148
// Light Settings panel
144149
m_PanelManager->AddPanel<LightSettingsPanel>(PanelCategory::View, "LightSettingsPanel", "Light Settings", true);
145150

146-
// Render statistics panel
147-
m_PanelManager->AddPanel<RenderStatsPanel>(PanelCategory::View, "RenderStatsPanel", "Render Stats", true);
148-
149151
m_IconPlay = TextureImporter::LoadTexture2D("Resources/Editor/Viewport/Play.png");
150152
m_IconPause = TextureImporter::LoadTexture2D("Resources/Editor/Viewport/Pause.png");
151153
m_IconSimulate = TextureImporter::LoadTexture2D("Resources/Editor/Viewport/Simulate.png");
@@ -171,8 +173,6 @@ namespace Lux {
171173
// Now safe to call - m_Renderer2D is valid.
172174
m_Renderer2D->SetTargetFramebuffer(m_Framebuffer);
173175

174-
m_PanelManager->SetSceneContext(m_EditorScene);
175-
176176
EnsureSceneRenderer(m_ActiveScene, m_ViewportSize);
177177
sceneRendererPanel->SetContext(s_SceneRendererState.Renderer);
178178

@@ -187,12 +187,8 @@ namespace Lux {
187187
sceneRendererSpec.ViewportHeight = 720;
188188

189189
m_SceneRenderer = Ref<SceneRenderer>::Create(m_ActiveScene, sceneRendererSpec);
190-
m_SceneRendererPanel.SetContext(m_SceneRenderer);
191-
192-
// FIX: SetContext was never called in OnAttach, so the SceneHierarchyPanel
193-
// had a null context on startup. Entities would not appear in the hierarchy
194-
// and the Properties panel would never draw any components.
195-
m_SceneHierarchyPanel.SetContext(m_EditorScene);
190+
m_PanelManager->SetSceneContext(m_EditorScene);
191+
m_PanelManager->OnProjectChanged(Project::GetActive());
196192

197193
EnsureSceneRenderer(m_ActiveScene, m_ViewportSize);
198194
if (s_SceneRendererState.Renderer)
@@ -216,7 +212,6 @@ namespace Lux {
216212
m_IconStep.reset();
217213
m_SquareVA.reset();
218214
m_FlatColorShader.reset();
219-
m_ContentBrowserPanel.reset();
220215
s_Font.reset();
221216
}
222217

@@ -252,7 +247,9 @@ namespace Lux {
252247
m_Renderer2D->ResetStats();
253248

254249
// Create selection predicate for 3D rendering (highlights selected entity)
255-
Entity selectedEntity = m_SceneHierarchyPanel.GetSelectedEntity();
250+
Entity selectedEntity = {};
251+
if (auto sceneHierarchyPanel = m_PanelManager->GetPanel<SceneHierarchyPanel>(SCENE_HIERARCHY_PANEL_ID))
252+
selectedEntity = sceneHierarchyPanel->GetSelectedEntity();
256253
auto isEntitySelected = [selectedEntity](Entity entity) -> bool {
257254
return selectedEntity && entity == selectedEntity;
258255
};
@@ -384,14 +381,6 @@ namespace Lux {
384381
ImGui::EndMenuBar();
385382
}
386383

387-
m_SceneHierarchyPanel.OnImGuiRender();
388-
389-
// FIX 3: Guard ContentBrowserPanel - it is only created after a project
390-
// is successfully opened via OpenProject(). Calling it unconditionally
391-
// when no project is loaded causes a null pointer dereference crash.
392-
if (m_ContentBrowserPanel)
393-
m_ContentBrowserPanel->OnImGuiRender();
394-
395384
m_PanelManager->OnImGuiRender();
396385

397386
// Stats panel
@@ -465,7 +454,9 @@ namespace Lux {
465454
}
466455

467456
// Gizmos
468-
Entity selectedEntity = m_SceneHierarchyPanel.GetSelectedEntity();
457+
Entity selectedEntity = {};
458+
if (auto sceneHierarchyPanel = m_PanelManager->GetPanel<SceneHierarchyPanel>(SCENE_HIERARCHY_PANEL_ID))
459+
selectedEntity = sceneHierarchyPanel->GetSelectedEntity();
469460
if (selectedEntity && m_GizmoType != -1)
470461
{
471462
ImGuizmo::SetOrthographic(false);
@@ -673,7 +664,8 @@ namespace Lux {
673664
if (e.GetMouseButton() == MouseButton::Left)
674665
{
675666
if (m_ViewportHovered && !ImGuizmo::IsOver() && !Input::IsKeyPressed(Key::LeftAlt))
676-
m_SceneHierarchyPanel.SetSelectedEntity(m_HoveredEntity);
667+
if (auto sceneHierarchyPanel = m_PanelManager->GetPanel<SceneHierarchyPanel>(SCENE_HIERARCHY_PANEL_ID))
668+
sceneHierarchyPanel->SetSelectedEntity(m_HoveredEntity);
677669
}
678670
return false;
679671
}
@@ -743,7 +735,10 @@ namespace Lux {
743735
}
744736

745737
// Selected entity outline
746-
if (Entity selectedEntity = m_SceneHierarchyPanel.GetSelectedEntity())
738+
Entity selectedEntity = {};
739+
if (auto sceneHierarchyPanel = m_PanelManager->GetPanel<SceneHierarchyPanel>(SCENE_HIERARCHY_PANEL_ID))
740+
selectedEntity = sceneHierarchyPanel->GetSelectedEntity();
741+
if (selectedEntity)
747742
{
748743
const TransformComponent& transform = selectedEntity.GetComponent<TransformComponent>();
749744
glm::mat4 t = transform.GetTransform();
@@ -776,7 +771,7 @@ namespace Lux {
776771
AssetHandle startScene = Project::GetActive()->GetConfig().StartScene;
777772
if (startScene)
778773
OpenScene(startScene);
779-
m_ContentBrowserPanel = CreateScope<ContentBrowserPanel>(Project::GetActive());
774+
m_PanelManager->OnProjectChanged(Project::GetActive());
780775
}
781776
}
782777

@@ -804,7 +799,7 @@ namespace Lux {
804799
m_EditorScene->OnViewportResize((uint32_t)m_ViewportSize.x, (uint32_t)m_ViewportSize.y);
805800

806801
m_ActiveScene = m_EditorScene;
807-
m_SceneHierarchyPanel.SetContext(m_ActiveScene);
802+
m_PanelManager->SetSceneContext(m_ActiveScene);
808803
m_EditorScenePath = std::filesystem::path();
809804

810805
if (m_SceneRenderer)
@@ -838,7 +833,7 @@ namespace Lux {
838833
m_EditorScene->OnViewportResize((uint32_t)m_ViewportSize.x, (uint32_t)m_ViewportSize.y);
839834

840835
m_ActiveScene = m_EditorScene;
841-
m_SceneHierarchyPanel.SetContext(m_EditorScene);
836+
m_PanelManager->SetSceneContext(m_EditorScene);
842837
m_EditorScenePath = Project::GetActive()->GetEditorAssetManager()->GetFilePath(handle);
843838

844839
if (m_SceneRenderer)
@@ -888,7 +883,7 @@ namespace Lux {
888883
m_ActiveScene->OnViewportResize((uint32_t)m_ViewportSize.x, (uint32_t)m_ViewportSize.y);
889884

890885
m_ActiveScene->OnRuntimeStart();
891-
m_SceneHierarchyPanel.SetContext(m_ActiveScene);
886+
m_PanelManager->SetSceneContext(m_ActiveScene);
892887

893888
if (m_SceneRenderer)
894889
m_SceneRenderer->SetScene(m_ActiveScene);
@@ -914,7 +909,7 @@ namespace Lux {
914909
m_ActiveScene->OnViewportResize((uint32_t)m_ViewportSize.x, (uint32_t)m_ViewportSize.y);
915910

916911
m_ActiveScene->OnSimulationStart();
917-
m_SceneHierarchyPanel.SetContext(m_ActiveScene);
912+
m_PanelManager->SetSceneContext(m_ActiveScene);
918913

919914
if (m_SceneRenderer)
920915
m_SceneRenderer->SetScene(m_ActiveScene);
@@ -938,7 +933,7 @@ namespace Lux {
938933
m_SceneState = SceneState::Edit;
939934
m_ActiveScene = m_EditorScene;
940935

941-
m_SceneHierarchyPanel.SetContext(m_ActiveScene);
936+
m_PanelManager->SetSceneContext(m_ActiveScene);
942937

943938
if (m_SceneRenderer)
944939
m_SceneRenderer->SetScene(m_ActiveScene);
@@ -963,11 +958,15 @@ namespace Lux {
963958
if (m_SceneState != SceneState::Edit)
964959
return;
965960

966-
Entity selectedEntity = m_SceneHierarchyPanel.GetSelectedEntity();
961+
Entity selectedEntity = {};
962+
Ref<SceneHierarchyPanel> sceneHierarchyPanel = m_PanelManager->GetPanel<SceneHierarchyPanel>(SCENE_HIERARCHY_PANEL_ID);
963+
if (sceneHierarchyPanel)
964+
selectedEntity = sceneHierarchyPanel->GetSelectedEntity();
967965
if (selectedEntity)
968966
{
969967
Entity newEntity = m_EditorScene->DuplicateEntity(selectedEntity);
970-
m_SceneHierarchyPanel.SetSelectedEntity(newEntity);
968+
if (sceneHierarchyPanel)
969+
sceneHierarchyPanel->SetSelectedEntity(newEntity);
971970
}
972971
}
973972
}

Editor/Source/EditorLayer.h

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,6 @@
22

33
#include "Lux.h"
44

5-
#include "Panels/SceneHierarchyPanel.h"
6-
#include "Panels/ContentBrowserPanel.h"
75
#include "Panels/ConsolePanel.h"
86
#include "Panels/RenderStatsPanel.h"
97
#include "Panels/MaterialEditorPanel.h"
@@ -20,7 +18,6 @@
2018

2119
#include "entt/entt.hpp"
2220
#include "Lux/Editor/PanelManager.h"
23-
#include "Panels/SceneRendererPanel.h"
2421
#include "Lux/Renderer/SceneRenderer.h"
2522

2623
namespace Lux
@@ -77,8 +74,6 @@ namespace Lux
7774
Ref<Renderer2D> m_Renderer2D;
7875

7976
Ref<SceneRenderer> m_SceneRenderer;
80-
SceneRendererPanel m_SceneRendererPanel;
81-
bool m_ShowSceneRendererPanel = true;
8277

8378
// Temp
8479
Ref<VertexBuffer> m_SquareVA;
@@ -113,10 +108,6 @@ namespace Lux
113108
};
114109
SceneState m_SceneState = SceneState::Edit;
115110

116-
// Panels
117-
SceneHierarchyPanel m_SceneHierarchyPanel;
118-
Scope<ContentBrowserPanel> m_ContentBrowserPanel;
119-
120111
// Editor resources
121112
Ref<Texture2D> m_IconPlay, m_IconPause, m_IconStep, m_IconSimulate, m_IconStop;
122113
};

Editor/Source/Panels/ContentBrowserPanel.cpp

Lines changed: 55 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -24,22 +24,58 @@ namespace Lux {
2424
}
2525

2626

27-
ContentBrowserPanel::ContentBrowserPanel(Ref<Project> project)
28-
: m_Project(project), m_ThumbnailCache(CreateRef<ThumbnailCache>(project)), m_BaseDirectory(m_Project->GetAssetDirectory()), m_CurrentDirectory(m_BaseDirectory)
27+
ContentBrowserPanel::ContentBrowserPanel()
2928
{
30-
m_TreeNodes.push_back(TreeNode(".", 0));
31-
3229
m_DirectoryIcon = TextureImporter::LoadTexture2D("Resources/Icons/ContentBrowser/DirectoryIcon.png");
3330
m_FileIcon = TextureImporter::LoadTexture2D("Resources/Icons/ContentBrowser/FileIcon.png");
31+
m_Mode = Mode::FileSystem;
32+
}
3433

35-
RefreshAssetTree();
34+
ContentBrowserPanel::ContentBrowserPanel(Ref<Project> project)
35+
: ContentBrowserPanel()
36+
{
37+
InitializeFromProject(project);
38+
}
3639

37-
m_Mode = Mode::FileSystem;
40+
void ContentBrowserPanel::OnProjectChanged(const Ref<Project>& project)
41+
{
42+
InitializeFromProject(project);
3843
}
3944

40-
void ContentBrowserPanel::OnImGuiRender()
45+
void ContentBrowserPanel::InitializeFromProject(const Ref<Project>& project)
4146
{
42-
ImGui::Begin("Content Browser");
47+
m_Project = project;
48+
m_TreeNodes.clear();
49+
m_AssetTree.clear();
50+
51+
if (!m_Project)
52+
{
53+
m_ThumbnailCache.reset();
54+
m_BaseDirectory.clear();
55+
m_CurrentDirectory.clear();
56+
return;
57+
}
58+
59+
m_ThumbnailCache = CreateRef<ThumbnailCache>(project);
60+
m_BaseDirectory = m_Project->GetAssetDirectory();
61+
m_CurrentDirectory = m_BaseDirectory;
62+
m_TreeNodes.push_back(TreeNode(".", 0));
63+
RefreshAssetTree();
64+
}
65+
66+
void ContentBrowserPanel::OnImGuiRender(bool& isOpen)
67+
{
68+
if (!isOpen)
69+
return;
70+
71+
ImGui::Begin("Content Browser", &isOpen);
72+
73+
if (!m_Project)
74+
{
75+
ImGui::TextDisabled("No active project.");
76+
ImGui::End();
77+
return;
78+
}
4379

4480
const char* label = m_Mode == Mode::Asset ? "Asset" : "File";
4581
if (ImGui::Button(label))
@@ -71,7 +107,7 @@ namespace Lux {
71107
{
72108
TreeNode* node = &m_TreeNodes[0];
73109

74-
auto currentDir = std::filesystem::relative(m_CurrentDirectory, Project::GetActiveAssetDirectory());
110+
auto currentDir = std::filesystem::relative(m_CurrentDirectory, m_Project->GetAssetDirectory());
75111
for (const auto& p : currentDir)
76112
{
77113
if (node->Path == currentDir)
@@ -90,7 +126,7 @@ namespace Lux {
90126

91127
for (const auto& [item, treeNodeIndex] : node->Children)
92128
{
93-
bool isDirectory = std::filesystem::is_directory(Project::GetActiveAssetDirectory() / item);
129+
bool isDirectory = std::filesystem::is_directory(m_Project->GetAssetDirectory() / item);
94130

95131
std::string itemStr = item.generic_string();
96132

@@ -174,7 +210,7 @@ namespace Lux {
174210

175211
ImGui::PushID(filenameString.c_str());
176212

177-
auto relativePath = std::filesystem::relative(path, Project::GetActiveAssetDirectory());
213+
auto relativePath = std::filesystem::relative(path, m_Project->GetAssetDirectory());
178214

179215
Ref<Texture2D> thumbnail = m_DirectoryIcon;
180216
if (!directoryEntry.is_directory())
@@ -215,7 +251,7 @@ namespace Lux {
215251
{
216252
if (ImGui::MenuItem("Import"))
217253
{
218-
Project::GetActive()->GetEditorAssetManager()->ImportAsset(relativePath);
254+
m_Project->GetEditorAssetManager()->ImportAsset(relativePath);
219255
RefreshAssetTree();
220256
}
221257
ImGui::EndPopup();
@@ -227,7 +263,7 @@ namespace Lux {
227263
if (ImGui::BeginDragDropSource())
228264
{
229265
AssetHandle handle = 0;
230-
const auto& registry = Project::GetActive()->GetEditorAssetManager()->GetAssetRegistry();
266+
const auto& registry = m_Project->GetEditorAssetManager()->GetAssetRegistry();
231267
for (const auto& [h, meta] : registry)
232268
{
233269
if (meta.FilePath == relativePath)
@@ -267,13 +303,17 @@ namespace Lux {
267303
// TODO: status bar
268304
ImGui::End();
269305

270-
m_ThumbnailCache->OnUpdate();
306+
if (m_ThumbnailCache)
307+
m_ThumbnailCache->OnUpdate();
271308
}
272309

273310

274311
void ContentBrowserPanel::RefreshAssetTree()
275312
{
276-
const auto& assetRegistry = Project::GetActive()->GetEditorAssetManager()->GetAssetRegistry();
313+
if (!m_Project)
314+
return;
315+
316+
const auto& assetRegistry = m_Project->GetEditorAssetManager()->GetAssetRegistry();
277317
for (const auto& [handle, metadata] : assetRegistry)
278318
{
279319
uint32_t currentNodeIndex = 0;

Editor/Source/Panels/ContentBrowserPanel.h

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
#pragma once
22

3+
#include "Lux/Editor/EditorPanel.h"
4+
#include "Lux/Project/Project.h"
35
#include "Lux/Renderer/Texture.h"
46

57
#include "ThumbnailCache.h"
@@ -10,13 +12,16 @@
1012

1113
namespace Lux {
1214

13-
class ContentBrowserPanel
15+
class ContentBrowserPanel : public EditorPanel
1416
{
1517
public:
18+
ContentBrowserPanel();
1619
ContentBrowserPanel(Ref<Project> project);
1720

18-
void OnImGuiRender();
21+
virtual void OnImGuiRender(bool& isOpen) override;
22+
virtual void OnProjectChanged(const Ref<Project>& project) override;
1923
private:
24+
void InitializeFromProject(const Ref<Project>& project);
2025
void RefreshAssetTree();
2126
private:
2227
Ref<Project> m_Project;

0 commit comments

Comments
 (0)