Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implemented Texture Icons/Thumbnails #595

Open
wants to merge 9 commits into
base: master
Choose a base branch
from
2 changes: 1 addition & 1 deletion Hazel/src/Hazel/Scene/SceneSerializer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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)
{
Expand Down
81 changes: 78 additions & 3 deletions Hazelnut/src/Panels/ContentBrowserPanel.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,81 @@
#include "Hazel/Project/Project.h"

#include <imgui/imgui.h>
#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<filewatch::FileWatch<std::string>>(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()
Expand All @@ -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();
}
Expand All @@ -43,9 +110,17 @@ namespace Hazel {
std::string filenameString = path.filename().string();

ImGui::PushID(filenameString.c_str());
Ref<Texture2D> icon = directoryEntry.is_directory() ? m_DirectoryIcon : m_FileIcon;
Ref<Texture2D> 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())
{
Expand Down
4 changes: 4 additions & 0 deletions Hazelnut/src/Panels/ContentBrowserPanel.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
#include "Hazel/Renderer/Texture.h"

#include <filesystem>
#include "FileWatch.h"

namespace Hazel {

Expand All @@ -18,6 +19,9 @@ namespace Hazel {

Ref<Texture2D> m_DirectoryIcon;
Ref<Texture2D> m_FileIcon;
std::unordered_map<std::string, Ref<Texture2D>> m_TextureIcons;

Scope<filewatch::FileWatch<std::string>> m_ContentBrowserFileWatcher;
};

}
20 changes: 18 additions & 2 deletions Hazelnut/src/Panels/SceneHierarchyPanel.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -399,11 +399,26 @@ namespace Hazel {
}
});

DrawComponent<SpriteRendererComponent>("Sprite Renderer", entity, [](auto& component)
DrawComponent<SpriteRendererComponent>("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"))
Expand All @@ -416,6 +431,7 @@ namespace Hazel {
else
HZ_WARN("Could not load texture {0}", texturePath.filename().string());
}

ImGui::EndDragDropTarget();
}

Expand Down
1 change: 1 addition & 0 deletions Hazelnut/src/Panels/SceneHierarchyPanel.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ namespace Hazel {
private:
Ref<Scene> m_Context;
Entity m_SelectionContext;
const Ref<Texture2D> m_DefaultTexture = Texture2D::Create(1, 1);
};

}