diff --git a/Hazel/src/Hazel/Core/Window.h b/Hazel/src/Hazel/Core/Window.h index baff4ce16..a969ccde6 100644 --- a/Hazel/src/Hazel/Core/Window.h +++ b/Hazel/src/Hazel/Core/Window.h @@ -39,6 +39,8 @@ namespace Hazel { virtual void SetVSync(bool enabled) = 0; virtual bool IsVSync() const = 0; + virtual void SetTitle(const std::string& title) = 0; + virtual void* GetNativeWindow() const = 0; static Scope Create(const WindowProps& props = WindowProps()); diff --git a/Hazel/src/Hazel/Scene/Scene.cpp b/Hazel/src/Hazel/Scene/Scene.cpp index e946d4b59..a8507ac42 100644 --- a/Hazel/src/Hazel/Scene/Scene.cpp +++ b/Hazel/src/Hazel/Scene/Scene.cpp @@ -128,6 +128,11 @@ namespace Hazel { return {}; } + void Scene::SetName(const std::string& name) + { + m_Name = name; + } + template void Scene::OnComponentAdded(Entity entity, T& component) { diff --git a/Hazel/src/Hazel/Scene/Scene.h b/Hazel/src/Hazel/Scene/Scene.h index a6374660e..e4e489854 100644 --- a/Hazel/src/Hazel/Scene/Scene.h +++ b/Hazel/src/Hazel/Scene/Scene.h @@ -23,6 +23,9 @@ namespace Hazel { void OnViewportResize(uint32_t width, uint32_t height); Entity GetPrimaryCameraEntity(); + + void SetName(const std::string& name); + const std::string& GetName() const { return m_Name; } private: template void OnComponentAdded(Entity entity, T& component); @@ -30,6 +33,8 @@ namespace Hazel { entt::registry m_Registry; uint32_t m_ViewportWidth = 0, m_ViewportHeight = 0; + std::string m_Name = "Untitled"; + friend class Entity; friend class SceneSerializer; friend class SceneHierarchyPanel; diff --git a/Hazel/src/Hazel/Scene/SceneSerializer.cpp b/Hazel/src/Hazel/Scene/SceneSerializer.cpp index e30f5967d..d54eef411 100644 --- a/Hazel/src/Hazel/Scene/SceneSerializer.cpp +++ b/Hazel/src/Hazel/Scene/SceneSerializer.cpp @@ -156,7 +156,7 @@ namespace Hazel { { YAML::Emitter out; out << YAML::BeginMap; - out << YAML::Key << "Scene" << YAML::Value << "Untitled"; + out << YAML::Key << "Scene" << YAML::Value << m_Scene->GetName(); out << YAML::Key << "Entities" << YAML::Value << YAML::BeginSeq; m_Scene->m_Registry.each([&](auto entityID) { @@ -196,6 +196,7 @@ namespace Hazel { std::string sceneName = data["Scene"].as(); HZ_CORE_TRACE("Deserializing scene '{0}'", sceneName); + m_Scene->SetName(sceneName); auto entities = data["Entities"]; if (entities) diff --git a/Hazel/src/Platform/Windows/WindowsWindow.cpp b/Hazel/src/Platform/Windows/WindowsWindow.cpp index be7684efb..032f1f185 100644 --- a/Hazel/src/Platform/Windows/WindowsWindow.cpp +++ b/Hazel/src/Platform/Windows/WindowsWindow.cpp @@ -197,4 +197,9 @@ namespace Hazel { return m_Data.VSync; } + void WindowsWindow::SetTitle(const std::string& title) + { + m_Data.Title = title; + glfwSetWindowTitle(m_Window, title.c_str()); + } } diff --git a/Hazel/src/Platform/Windows/WindowsWindow.h b/Hazel/src/Platform/Windows/WindowsWindow.h index cb1d19cb2..06147c468 100644 --- a/Hazel/src/Platform/Windows/WindowsWindow.h +++ b/Hazel/src/Platform/Windows/WindowsWindow.h @@ -23,6 +23,8 @@ namespace Hazel { void SetVSync(bool enabled) override; bool IsVSync() const override; + void SetTitle(const std::string& title) override; + virtual void* GetNativeWindow() const { return m_Window; } private: virtual void Init(const WindowProps& props); @@ -43,4 +45,4 @@ namespace Hazel { WindowData m_Data; }; -} \ No newline at end of file +} diff --git a/Hazelnut/assets/scenes/3DExample.hazel b/Hazelnut/assets/scenes/3DExample.hazel index 6d2ff15b2..464ed0ebc 100644 --- a/Hazelnut/assets/scenes/3DExample.hazel +++ b/Hazelnut/assets/scenes/3DExample.hazel @@ -1,4 +1,4 @@ -Scene: Untitled +Scene: 3DExample Entities: - Entity: 12837192831273 TagComponent: diff --git a/Hazelnut/assets/scenes/Example.hazel b/Hazelnut/assets/scenes/Example.hazel index 9d177bd46..1535f9e76 100644 --- a/Hazelnut/assets/scenes/Example.hazel +++ b/Hazelnut/assets/scenes/Example.hazel @@ -1,4 +1,4 @@ -Scene: Untitled +Scene: Example Entities: - Entity: 12837192831273 TagComponent: diff --git a/Hazelnut/assets/scenes/PinkCube.hazel b/Hazelnut/assets/scenes/PinkCube.hazel index 2142971ef..3cff7ef20 100644 --- a/Hazelnut/assets/scenes/PinkCube.hazel +++ b/Hazelnut/assets/scenes/PinkCube.hazel @@ -1,4 +1,4 @@ -Scene: Untitled +Scene: PinkCube Entities: - Entity: 12837192831273 TagComponent: diff --git a/Hazelnut/src/EditorLayer.cpp b/Hazelnut/src/EditorLayer.cpp index 454a5d4c6..3a1ecf80c 100644 --- a/Hazelnut/src/EditorLayer.cpp +++ b/Hazelnut/src/EditorLayer.cpp @@ -35,14 +35,25 @@ namespace Hazel { fbSpec.Height = 720; m_Framebuffer = Framebuffer::Create(fbSpec); - m_ActiveScene = CreateRef(); + // When setting the active scene later in this method, we try to resize its viewport + // If viewport size is still 0, we'll assert + // So set it to some valid value now + // Then later in OnUpdate()/OnImGuiRender() fix it to the correct value + m_ViewportSize = { fbSpec.Width, fbSpec.Height }; + + // Try to load a scene from command line args + // If it fails (no args, invalid scene, etc.) then fallback to default new untitled scene + bool loadedScene = false; auto commandLineArgs = Application::Get().GetCommandLineArgs(); if (commandLineArgs.Count > 1) { - auto sceneFilePath = commandLineArgs[1]; - SceneSerializer serializer(m_ActiveScene); - serializer.Deserialize(sceneFilePath); + loadedScene = OpenScene(std::filesystem::path(commandLineArgs[1])); + } + + if (!loadedScene) + { + NewScene(); } m_EditorCamera = EditorCamera(30.0f, 1.778f, 0.1f, 1000.0f); @@ -97,8 +108,6 @@ namespace Hazel { m_CameraEntity.AddComponent().Bind(); m_SecondCamera.AddComponent().Bind(); #endif - - m_SceneHierarchyPanel.SetContext(m_ActiveScene); } void EditorLayer::OnDetach() @@ -460,9 +469,9 @@ namespace Hazel { void EditorLayer::NewScene() { - m_ActiveScene = CreateRef(); - m_ActiveScene->OnViewportResize((uint32_t)m_ViewportSize.x, (uint32_t)m_ViewportSize.y); - m_SceneHierarchyPanel.SetContext(m_ActiveScene); + Ref newScene = CreateRef(); + SetActiveScene(newScene); + SetEditorScenePath(std::filesystem::path()); } void EditorLayer::OpenScene() @@ -472,22 +481,24 @@ namespace Hazel { OpenScene(filepath); } - void EditorLayer::OpenScene(const std::filesystem::path& path) + bool EditorLayer::OpenScene(const std::filesystem::path& path) { if (path.extension().string() != ".hazel") { HZ_WARN("Could not load {0} - not a scene file", path.filename().string()); - return; + return false; } Ref newScene = CreateRef(); SceneSerializer serializer(newScene); - if (serializer.Deserialize(path.string())) + if (!serializer.Deserialize(path.string())) { - m_ActiveScene = newScene; - m_ActiveScene->OnViewportResize((uint32_t)m_ViewportSize.x, (uint32_t)m_ViewportSize.y); - m_SceneHierarchyPanel.SetContext(m_ActiveScene); + return false; } + + SetActiveScene(newScene); + SetEditorScenePath(path); + return true; } void EditorLayer::SaveSceneAs() @@ -497,6 +508,7 @@ namespace Hazel { { SceneSerializer serializer(m_ActiveScene); serializer.Serialize(filepath); + SetEditorScenePath(std::filesystem::path(filepath)); } } @@ -510,5 +522,31 @@ namespace Hazel { m_SceneState = SceneState::Edit; } + + void EditorLayer::SetActiveScene(const Ref& activeScene) + { + HZ_ASSERT(activeScene, "EditorLayer ActiveScene cannot be null"); + + m_ActiveScene = activeScene; + m_ActiveScene->OnViewportResize((uint32_t)m_ViewportSize.x, (uint32_t)m_ViewportSize.y); + + m_SceneHierarchyPanel.SetContext(m_ActiveScene); + + SyncWindowTitle(); + } + void EditorLayer::SetEditorScenePath(const std::filesystem::path& path) + { + m_EditorScenePath = path; + SyncWindowTitle(); + } + + void EditorLayer::SyncWindowTitle() + { + std::string title = "Hazelnut"; + title += " - " + m_ActiveScene->GetName(); + title += " (" + (m_EditorScenePath.empty() ? "unsaved" : m_EditorScenePath.string()) + ")"; + + Application::Get().GetWindow().SetTitle(title); + } } diff --git a/Hazelnut/src/EditorLayer.h b/Hazelnut/src/EditorLayer.h index 35bdd9cb8..67142c534 100644 --- a/Hazelnut/src/EditorLayer.h +++ b/Hazelnut/src/EditorLayer.h @@ -26,12 +26,16 @@ namespace Hazel { void NewScene(); void OpenScene(); - void OpenScene(const std::filesystem::path& path); + bool OpenScene(const std::filesystem::path& path); void SaveSceneAs(); void OnScenePlay(); void OnSceneStop(); + void SetActiveScene(const Ref& activeScene); + void SetEditorScenePath(const std::filesystem::path& path); + void SyncWindowTitle(); + // UI Panels void UI_Toolbar(); private: @@ -43,6 +47,8 @@ namespace Hazel { Ref m_Framebuffer; Ref m_ActiveScene; + std::filesystem::path m_EditorScenePath; + Entity m_SquareEntity; Entity m_CameraEntity; Entity m_SecondCamera;