From 4c4d39d4bbcbd7b0fe50c09b9d1bc35e08352339 Mon Sep 17 00:00:00 2001 From: SHAM-DP Date: Tue, 31 Jan 2023 18:55:50 +0800 Subject: [PATCH] Added double click asset id in inspector to scroll to asset in asset browser Added asset browser filter by name and type --- SHADE_Engine/src/Assets/SHAssetManager.cpp | 23 +++ .../AssetBrowser/SHAssetBrowser.cpp | 155 +++++++++++++++++- .../AssetBrowser/SHAssetBrowser.h | 12 +- .../HierarchyPanel/SHHierarchyPanel.h | 2 +- .../Inspector/SHEditorComponentView.hpp | 46 +++++- SHADE_Engine/src/Editor/SHEditor.cpp | 24 ++- SHADE_Engine/src/Editor/SHEditor.h | 3 +- SHADE_Engine/src/Editor/SHEditorWidgets.hpp | 2 +- 8 files changed, 253 insertions(+), 14 deletions(-) diff --git a/SHADE_Engine/src/Assets/SHAssetManager.cpp b/SHADE_Engine/src/Assets/SHAssetManager.cpp index 44d62f66..363b7829 100644 --- a/SHADE_Engine/src/Assets/SHAssetManager.cpp +++ b/SHADE_Engine/src/Assets/SHAssetManager.cpp @@ -27,6 +27,7 @@ #include "Libraries/Compilers/SHShaderSourceCompiler.h" #include "Filesystem/SHFileSystem.h" +#include namespace SHADE { @@ -733,3 +734,25 @@ namespace SHADE } } } + +namespace rttr +{ + using namespace SHADE; + RTTR_REGISTRATION + { + registration::enumeration("Asset Type") + ( + value("Invalid", AssetType::INVALID), + value("Shader", AssetType::SHADER), + value("Shader [Built-In]", AssetType::SHADER_BUILT_IN), + value("Texture", AssetType::TEXTURE), + value("Model", AssetType::MODEL), + value("Scene", AssetType::SCENE), + value("Prefab", AssetType::PREFAB), + value("Material", AssetType::MATERIAL), + value("Mesh", AssetType::MESH), + value("Script", AssetType::SCRIPT), + value("Font", AssetType::FONT) + ); + } +} diff --git a/SHADE_Engine/src/Editor/EditorWindow/AssetBrowser/SHAssetBrowser.cpp b/SHADE_Engine/src/Editor/EditorWindow/AssetBrowser/SHAssetBrowser.cpp index a7ba7dc0..791396df 100644 --- a/SHADE_Engine/src/Editor/EditorWindow/AssetBrowser/SHAssetBrowser.cpp +++ b/SHADE_Engine/src/Editor/EditorWindow/AssetBrowser/SHAssetBrowser.cpp @@ -16,6 +16,9 @@ #include "Editor/EditorWindow/SHEditorWindowManager.h" #include "Scripting/SHVSUtilities.h" #include "Scripting/SHScriptEngine.h" +#include "Tools/Utilities/SHStringUtilities.h" +#include +#include namespace SHADE { @@ -27,6 +30,13 @@ namespace SHADE void SHAssetBrowser::Init() { SHEditorWindow::Init(); + rttr::array_range typeNames = typeEnumAlign.get_names(); + + for(auto const& name : typeNames) + { + uint64_t val = typeEnumAlign.name_to_value(name).to_uint64(); + typeFilters[val] = true; + } } void SHAssetBrowser::Update() @@ -34,7 +44,10 @@ namespace SHADE SHEditorWindow::Update(); if (Begin()) { - RecursivelyDrawTree(rootFolder); + for(auto subFolder : rootFolder->subFolders) + { + RecursivelyDrawTree(subFolder); + } DrawMenuBar(); DrawCurrentFolder(); DrawAssetBeingCreated(); @@ -50,6 +63,11 @@ namespace SHADE refreshQueued = true; } + void SHAssetBrowser::SetScrollTo(AssetID assetid) + { + assetToScrollTo = assetid; + } + void SHAssetBrowser::Refresh() noexcept { SHAssetManager::RefreshDirectory(); @@ -69,6 +87,7 @@ namespace SHADE { isAssetBeingCreated = true; } + DrawAssetBrowserFilter(); ImGui::EndMenuBar(); } } @@ -81,13 +100,34 @@ namespace SHADE auto files = folder->files; const bool isSelected = std::ranges::find(selectedFolders, folder) != selectedFolders.end(); ImGuiTreeNodeFlags flags = (subFolders.empty() && files.empty()) ? ImGuiTreeNodeFlags_Leaf : ImGuiTreeNodeFlags_OpenOnArrow; + if(!filter.empty() && (!subFolders.empty() || !files.empty())) + { + ImGui::SetNextItemOpen(true); + } if (isSelected) flags |= ImGuiTreeNodeFlags_Selected; if (folder == rootFolder) flags |= ImGuiTreeNodeFlags_DefaultOpen; - bool isOpen = ImGui::TreeNodeEx(folder, flags, "%s %s", ICON_MD_FOLDER, folder->name.data()); - ImGuiID folderID = ImGui::GetItemID(); + if(assetToScrollTo != 0) + { + if(auto asset = SHAssetManager::GetAsset(assetToScrollTo)) + { + if(!asset->path.empty()) + { + ImGui::SetNextItemOpen(SHStringUtilities::StringFindInsensitive(asset->path.string(), folder->name.data()) != std::string::npos); + } + else if(auto parent = SHAssetManager::GetAsset(asset->parent)) + { + ImGui::SetNextItemOpen(SHStringUtilities::StringFindInsensitive(parent->path.string(), folder->name.data()) != std::string::npos); + } + } + } + + bool isOpen = false; + if(filter.empty()) + isOpen = ImGui::TreeNodeEx(folder, flags, "%s %s", ICON_MD_FOLDER, folder->name.data()); + const ImRect nodeRect = ImRect(ImGui::GetItemRectMin(), ImGui::GetItemRectMax()); //if (ImGui::BeginPopupContextItem()) @@ -101,7 +141,7 @@ namespace SHADE selectedFolders.push_back(folder); } - if (isOpen) + if (isOpen || !filter.empty()) { const ImColor treeLineColor = ImGui::GetColorU32(ImGuiCol_CheckMark); const float horizontalOffset = 0.0f; @@ -127,7 +167,8 @@ namespace SHADE } drawList->AddLine(vertLineStart, vertLineEnd, treeLineColor, 1); - ImGui::TreePop(); + if(filter.empty()) + ImGui::TreePop(); } return nodeRect; } @@ -167,8 +208,26 @@ namespace SHADE { ImGuiTreeNodeFlags flags = ImGuiTreeNodeFlags_Leaf; static constexpr std::string_view icon = ICON_MD_FILE_PRESENT; + bool highlighted = false; + if (!filter.empty()) + { + if (SHStringUtilities::StringFindInsensitive(file.name.data(), filter) == std::string::npos) + { + return ImRect(ImGui::GetItemRectMin(), ImGui::GetItemRectMax()); + } + else + { + highlighted = true; + ImGui::PushStyleColor(ImGuiCol_Text, highlightedColor); + } + } ImGui::PushID(file.name.data()); + bool const isOpen = ImGui::TreeNodeEx(file.name.data(), flags, "%s %s%s", icon.data(), file.name.data(), file.ext.data()); + if(highlighted) + { + ImGui::PopStyleColor(); + } const ImRect nodeRect = ImRect(ImGui::GetItemRectMin(), ImGui::GetItemRectMax()); if(ImGui::BeginPopupContextItem()) { @@ -194,6 +253,27 @@ namespace SHADE { if (asset == nullptr) return ImRect(ImGui::GetItemRectMin(), ImGui::GetItemRectMax()); + + if (!typeFilters[static_cast(asset->type)]) + { + return ImRect(ImGui::GetItemRectMin(), ImGui::GetItemRectMax()); + } + + bool highlighted = false; + if(!filter.empty()) + { + ImGui::SetNextItemOpen(true); + if(SHStringUtilities::StringFindInsensitive(asset->name.data(), filter) == std::string::npos) + { + return ImRect(ImGui::GetItemRectMin(), ImGui::GetItemRectMax()); + } + else + { + highlighted = true; + ImGui::PushStyleColor(ImGuiCol_Text, highlightedColor); + } + } + const bool isSelected = std::ranges::find(selectedAssets, asset->id) != selectedAssets.end(); ImGuiTreeNodeFlags flags = (!asset->subAssets.empty()) ? ImGuiTreeNodeFlags_OpenOnArrow : ImGuiTreeNodeFlags_Leaf; if (isSelected) @@ -214,8 +294,34 @@ namespace SHADE case AssetType::MAX_COUNT: break; default:; } + + if(assetToScrollTo != 0) + { + if(asset->id == assetToScrollTo) + { + ImGui::SetScrollHereY(); + selectedAssets.clear(); + selectedAssets.push_back(asset->id); + assetToScrollTo = 0; + } + else + { + for (auto const& subAsset : asset->subAssets) + { + if(subAsset->id == assetToScrollTo) + { + ImGui::SetNextItemOpen(true); + } + } + } + } bool const isOpen = ImGui::TreeNodeEx(asset, flags, "%s %s%s", icon.data(), asset->name.data(), ext.data()); + + if(highlighted) + { + ImGui::PopStyleColor(); + } const ImRect nodeRect = ImRect(ImGui::GetItemRectMin(), ImGui::GetItemRectMax()); if (SHDragDrop::BeginSource()) { @@ -339,4 +445,43 @@ namespace SHADE // QueueRefresh(); //} } + + void SHAssetBrowser::DrawAssetBrowserFilter() + { + if (ImGui::InputTextWithHint("##hierarchyPanelFilter", "Filter", &filter)) + { + } + if (ImGui::Button("x")) + { + filter.clear(); + } + if(ImGui::BeginMenu("Type")) + { + if (ImGui::Button("All")) + { + for (auto& [id, value] : typeFilters) + value = true; + } + ImGui::SameLine(); + if (ImGui::Button("None")) + { + for (auto& [id, value] : typeFilters) + value = false; + } + for (auto& [id, value] : typeFilters) + { + if(ImGui::Checkbox(typeEnumAlign.value_to_name(id).data(), &value)) + { + + } + if(ImGui::IsItemClicked(ImGuiMouseButton_Right)) + { + for (auto& [id2, value2] : typeFilters) + value2 = false; + value = true; + } + } + ImGui::EndMenu(); + } + } } diff --git a/SHADE_Engine/src/Editor/EditorWindow/AssetBrowser/SHAssetBrowser.h b/SHADE_Engine/src/Editor/EditorWindow/AssetBrowser/SHAssetBrowser.h index 6d3c5eb4..0ff5225e 100644 --- a/SHADE_Engine/src/Editor/EditorWindow/AssetBrowser/SHAssetBrowser.h +++ b/SHADE_Engine/src/Editor/EditorWindow/AssetBrowser/SHAssetBrowser.h @@ -4,18 +4,21 @@ #include "Assets/SHAsset.h" #include "Editor/EditorWindow/SHEditorWindow.h" #include "Filesystem/SHFolder.h" +#include namespace SHADE { class SHAssetBrowser final : public SHEditorWindow { public: + static constexpr ImVec4 highlightedColor = ImVec4(0.f, 0.7f, 0.0f, 1.0f); SHAssetBrowser(); void Init(); void Update(); void QueueRefresh() noexcept; + void SetScrollTo(AssetID assetid); private: void DrawMenuBar(); ImRect RecursivelyDrawTree(FolderPointer folder); @@ -23,6 +26,7 @@ namespace SHADE ImRect DrawFile(SHFile& file) noexcept; ImRect DrawAsset(SHAsset const* const asset, FileExt const& ext = "") noexcept; void DrawAssetBeingCreated() noexcept; + void DrawAssetBrowserFilter(); void Refresh() noexcept; @@ -30,9 +34,13 @@ namespace SHADE std::vector selectedFolders; std::vector selectedAssets; static constexpr float tileWidth = 50.0f; + static constexpr std::string_view newAssetPopup = "Create New Asset"; + std::string nameOfAssetBeingCreated, filter; + rttr::enumeration typeEnumAlign = rttr::type::get().get_enumeration(); + std::unordered_map typeFilters; + + AssetID assetToScrollTo = 0; bool refreshQueued = false; bool isAssetBeingCreated = false; - static constexpr std::string_view newAssetPopup = "Create New Asset"; - std::string nameOfAssetBeingCreated; }; } diff --git a/SHADE_Engine/src/Editor/EditorWindow/HierarchyPanel/SHHierarchyPanel.h b/SHADE_Engine/src/Editor/EditorWindow/HierarchyPanel/SHHierarchyPanel.h index d217a307..cf5f0980 100644 --- a/SHADE_Engine/src/Editor/EditorWindow/HierarchyPanel/SHHierarchyPanel.h +++ b/SHADE_Engine/src/Editor/EditorWindow/HierarchyPanel/SHHierarchyPanel.h @@ -15,11 +15,11 @@ namespace SHADE { class SHSceneNode; - constexpr ImVec4 highlightedColor = ImVec4(0.f, 0.7f, 0.0f, 1.0f); class SHHierarchyPanel final : public SHEditorWindow { public: + static constexpr ImVec4 highlightedColor = ImVec4(0.f, 0.7f, 0.0f, 1.0f); SHHierarchyPanel(); void Init() override; void Update() override; diff --git a/SHADE_Engine/src/Editor/EditorWindow/Inspector/SHEditorComponentView.hpp b/SHADE_Engine/src/Editor/EditorWindow/Inspector/SHEditorComponentView.hpp index a2873bd0..48d334fa 100644 --- a/SHADE_Engine/src/Editor/EditorWindow/Inspector/SHEditorComponentView.hpp +++ b/SHADE_Engine/src/Editor/EditorWindow/Inspector/SHEditorComponentView.hpp @@ -24,6 +24,8 @@ #include "SHInspectorCommands.h" #include "Physics/Collision/SHCollisionTagMatrix.h" #include "Animation/SHAnimatorComponent.h" +#include "../SHEditorWindowManager.h" +#include "../AssetBrowser/SHAssetBrowser.h" namespace SHADE { template @@ -502,6 +504,15 @@ namespace SHADE SHResourceManager::FinaliseChanges(); }, SHDragDrop::DRAG_RESOURCE); + if (ImGui::IsItemHovered() && ImGui::IsMouseDoubleClicked(ImGuiMouseButton_Left)) + { + if(Handle const& mesh = component->GetMesh()) + { + AssetID assetID = SHResourceManager::GetAssetID(mesh).value_or(0); + SHEditorWindowManager::GetEditorWindow()->SetScrollTo(assetID); + } + } + const auto MAT_NAME = mat ? SHResourceManager::GetAssetName(mat->GetBaseMaterial()).value_or("") : ""; SHEditorWidgets::DragDropReadOnlyField("Material", MAT_NAME, [component]() @@ -521,6 +532,15 @@ namespace SHADE auto gfxSystem = SHSystemManager::GetSystem(); component->SetMaterial(gfxSystem->AddOrGetBaseMaterialInstance(SHResourceManager::LoadOrGet(id))); }, SHDragDrop::DRAG_RESOURCE); + if (ImGui::IsItemHovered() && ImGui::IsMouseDoubleClicked(ImGuiMouseButton_Left)) + { + if(Handle const& mat = component->GetMaterial()) + { + AssetID assetID = SHResourceManager::GetAssetID(mat->GetBaseMaterial()).value_or(0); + SHEditorWindowManager::GetEditorWindow()->SetScrollTo(assetID); + } + } + } else { @@ -558,7 +578,14 @@ namespace SHADE component->SetFont(SHResourceManager::LoadOrGet(id)); SHResourceManager::FinaliseChanges(); }, SHDragDrop::DRAG_RESOURCE); - + if (ImGui::IsItemHovered() && ImGui::IsMouseDoubleClicked(ImGuiMouseButton_Left)) + { + if (Handle const& font = component->GetFont()) + { + AssetID assetID = SHResourceManager::GetAssetID(font).value_or(0); + SHEditorWindowManager::GetEditorWindow()->SetScrollTo(assetID); + } + } SHEditorWidgets::InputText("Text", [component](void) { @@ -606,7 +633,14 @@ namespace SHADE component->SetRig(SHResourceManager::LoadOrGet(id)); SHResourceManager::FinaliseChanges(); }, SHDragDrop::DRAG_RESOURCE); - + if (ImGui::IsItemHovered() && ImGui::IsMouseDoubleClicked(ImGuiMouseButton_Left)) + { + if (Handle const& rig = component->GetRig()) + { + AssetID assetID = SHResourceManager::GetAssetID(rig).value_or(0); + SHEditorWindowManager::GetEditorWindow()->SetScrollTo(assetID); + } + } Handle const& clip = component->GetCurrentClip(); const auto CLIP_NAME = clip ? SHResourceManager::GetAssetName(clip).value_or("") : ""; SHEditorWidgets::DragDropReadOnlyField("Clip", CLIP_NAME, @@ -624,6 +658,14 @@ namespace SHADE } component->SetClip(SHResourceManager::LoadOrGet(id)); }, SHDragDrop::DRAG_RESOURCE); + if (ImGui::IsItemHovered() && ImGui::IsMouseDoubleClicked(ImGuiMouseButton_Left)) + { + if (Handle const& clip = component->GetCurrentClip()) + { + AssetID assetID = SHResourceManager::GetAssetID(clip).value_or(0); + SHEditorWindowManager::GetEditorWindow()->SetScrollTo(assetID); + } + } } else { diff --git a/SHADE_Engine/src/Editor/SHEditor.cpp b/SHADE_Engine/src/Editor/SHEditor.cpp index 4d180635..d151fd64 100644 --- a/SHADE_Engine/src/Editor/SHEditor.cpp +++ b/SHADE_Engine/src/Editor/SHEditor.cpp @@ -96,8 +96,10 @@ namespace SHADE SHLOG_CRITICAL("Failed to create ImGui Context") } } - + +#ifdef SHEDITOR editorConfig = &SHConfigurationManager::LoadEditorConfig(); +#endif //Add editor windows SHEditorWindowManager::CreateEditorWindow(); @@ -131,8 +133,9 @@ namespace SHADE InitBackend(); +#ifdef SHEDITOR SetStyle(static_cast