diff --git a/Hazel/src/Hazel/Scene/SceneSerializer.cpp b/Hazel/src/Hazel/Scene/SceneSerializer.cpp index c490de4e6..fde02ce69 100644 --- a/Hazel/src/Hazel/Scene/SceneSerializer.cpp +++ b/Hazel/src/Hazel/Scene/SceneSerializer.cpp @@ -362,7 +362,7 @@ namespace Hazel { { YAML::Emitter out; out << YAML::BeginMap; - out << YAML::Key << "Scene" << YAML::Value << "Untitled"; + out << YAML::Key << "Scene" << YAML::Value << std::filesystem::path(filepath).stem().string(); out << YAML::Key << "Entities" << YAML::Value << YAML::BeginSeq; m_Scene->m_Registry.each([&](auto entityID) { diff --git a/Hazelnut/src/Panels/ContentBrowserPanel.cpp b/Hazelnut/src/Panels/ContentBrowserPanel.cpp index 65f6dd7c5..667ba45bd 100644 --- a/Hazelnut/src/Panels/ContentBrowserPanel.cpp +++ b/Hazelnut/src/Panels/ContentBrowserPanel.cpp @@ -4,14 +4,81 @@ #include "Hazel/Project/Project.h" #include +#include "Hazel/Core/Application.h" namespace Hazel { + namespace Utils { + + static bool IsImageFile(const std::filesystem::path& path) + { + if (path.extension() == ".png" || path.extension() == ".jpg") + return true; + + return false; + } + + } + ContentBrowserPanel::ContentBrowserPanel() : m_BaseDirectory(Project::GetAssetDirectory()), m_CurrentDirectory(m_BaseDirectory) { m_DirectoryIcon = Texture2D::Create("Resources/Icons/ContentBrowser/DirectoryIcon.png"); m_FileIcon = Texture2D::Create("Resources/Icons/ContentBrowser/FileIcon.png"); + + auto FileAssetEvent = [this](const std::string& filepath, const filewatch::Event change_type) + { + switch (change_type) + { + case filewatch::Event::added: + { + Application::Get().SubmitToMainThread([this, filepath]() + { + if (Utils::IsImageFile(filepath)) + { + std::filesystem::path texturePath = filepath; + texturePath = m_BaseDirectory / filepath; + + // NOTE: Waiting for Texture to load fully on directory otherwise we'll get black thumbnails + // Waiting Time can vary depending on asset size + // To remove this we need a way to know if file has loaded completely or not + using namespace std::literals::chrono_literals; + std::this_thread::sleep_for(0.02s); + + m_TextureIcons[texturePath.string()] = Texture2D::Create(texturePath.string()); + HZ_WARN("{}: File Added", texturePath.string()); + } + }); + + break; + } + case filewatch::Event::removed: + { + Application::Get().SubmitToMainThread([this, filepath]() + { + std::filesystem::path texturePath = filepath; + texturePath = m_BaseDirectory / filepath; + + m_TextureIcons.erase(texturePath.string()); + HZ_WARN("{}: File Deleted", texturePath.string()); + }); + + break; + } + } + }; + + m_ContentBrowserFileWatcher = CreateScope>(m_BaseDirectory.string(), FileAssetEvent); + + // Loading Textures + for (auto& directoryEntry : std::filesystem::recursive_directory_iterator(m_BaseDirectory)) + { + const auto& path = directoryEntry.path(); + const auto& filenameString = path.string(); + + if (Utils::IsImageFile(path)) + m_TextureIcons[filenameString] = Texture2D::Create(filenameString); + } } void ContentBrowserPanel::OnImGuiRender() @@ -20,7 +87,7 @@ namespace Hazel { if (m_CurrentDirectory != std::filesystem::path(m_BaseDirectory)) { - if (ImGui::Button("<-")) + if (ImGui::Button("Back")) { m_CurrentDirectory = m_CurrentDirectory.parent_path(); } @@ -43,9 +110,17 @@ namespace Hazel { std::string filenameString = path.filename().string(); ImGui::PushID(filenameString.c_str()); - Ref icon = directoryEntry.is_directory() ? m_DirectoryIcon : m_FileIcon; + Ref icon = nullptr; + + if (Utils::IsImageFile(path)) + icon = m_TextureIcons[path.string()]; + + else + icon = directoryEntry.is_directory() ? m_DirectoryIcon : m_FileIcon; + ImGui::PushStyleColor(ImGuiCol_Button, ImVec4(0, 0, 0, 0)); - ImGui::ImageButton((ImTextureID)icon->GetRendererID(), { thumbnailSize, thumbnailSize }, { 0, 1 }, { 1, 0 }); + if (icon) + ImGui::ImageButton((ImTextureID)icon->GetRendererID(), { thumbnailSize, thumbnailSize }, { 0, 1 }, { 1, 0 }); if (ImGui::BeginDragDropSource()) { diff --git a/Hazelnut/src/Panels/ContentBrowserPanel.h b/Hazelnut/src/Panels/ContentBrowserPanel.h index 466575947..b59671a97 100644 --- a/Hazelnut/src/Panels/ContentBrowserPanel.h +++ b/Hazelnut/src/Panels/ContentBrowserPanel.h @@ -3,6 +3,7 @@ #include "Hazel/Renderer/Texture.h" #include +#include "FileWatch.h" namespace Hazel { @@ -18,6 +19,9 @@ namespace Hazel { Ref m_DirectoryIcon; Ref m_FileIcon; + std::unordered_map> m_TextureIcons; + + Scope> m_ContentBrowserFileWatcher; }; } diff --git a/Hazelnut/src/Panels/SceneHierarchyPanel.cpp b/Hazelnut/src/Panels/SceneHierarchyPanel.cpp index e174ce1aa..37b402e98 100644 --- a/Hazelnut/src/Panels/SceneHierarchyPanel.cpp +++ b/Hazelnut/src/Panels/SceneHierarchyPanel.cpp @@ -399,11 +399,26 @@ namespace Hazel { } }); - DrawComponent("Sprite Renderer", entity, [](auto& component) + DrawComponent("Sprite Renderer", entity, [defaultTexture = m_DefaultTexture](auto& component) { ImGui::ColorEdit4("Color", glm::value_ptr(component.Color)); - ImGui::Button("Texture", ImVec2(100.0f, 0.0f)); + uint32_t buttonTex = component.Texture ? component.Texture->GetRendererID() + : defaultTexture->GetRendererID(); + + ImGui::ImageButton((ImTextureID)buttonTex, ImVec2{ 100.0f, 100.0f }); + + if (ImGui::IsItemClicked(ImGuiMouseButton_Right)) + ImGui::OpenPopup("RemoveTexture"); + + if (ImGui::BeginPopup("RemoveTexture")) + { + if (ImGui::MenuItem("Remove Texture")) + component.Texture = nullptr; + + ImGui::EndPopup(); + } + if (ImGui::BeginDragDropTarget()) { if (const ImGuiPayload* payload = ImGui::AcceptDragDropPayload("CONTENT_BROWSER_ITEM")) @@ -416,6 +431,7 @@ namespace Hazel { else HZ_WARN("Could not load texture {0}", texturePath.filename().string()); } + ImGui::EndDragDropTarget(); } diff --git a/Hazelnut/src/Panels/SceneHierarchyPanel.h b/Hazelnut/src/Panels/SceneHierarchyPanel.h index a63a284ff..ddfcb7fdb 100644 --- a/Hazelnut/src/Panels/SceneHierarchyPanel.h +++ b/Hazelnut/src/Panels/SceneHierarchyPanel.h @@ -27,6 +27,7 @@ namespace Hazel { private: Ref m_Context; Entity m_SelectionContext; + const Ref m_DefaultTexture = Texture2D::Create(1, 1); }; }