-
-
Save colesnicov/07ff09ad8c43e9e6e7c8a23582345718 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <filesystem> | |
#include <imgui.h> | |
#define BIT(x) (1 << x) | |
std::pair<bool, uint32_t> DirectoryTreeViewRecursive(const std::filesystem::path& path, uint32_t* count, int* selection_mask) | |
{ | |
ImGuiTreeNodeFlags base_flags = ImGuiTreeNodeFlags_OpenOnArrow | ImGuiTreeNodeFlags_OpenOnDoubleClick | ImGuiTreeNodeFlags_SpanAvailWidth | ImGuiTreeNodeFlags_SpanFullWidth; | |
bool any_node_clicked = false; | |
uint32_t node_clicked = 0; | |
for (const auto& entry : std::filesystem::directory_iterator(path)) | |
{ | |
ImGuiTreeNodeFlags node_flags = base_flags; | |
const bool is_selected = (*selection_mask & BIT(*count)) != 0; | |
if (is_selected) | |
node_flags |= ImGuiTreeNodeFlags_Selected; | |
std::string name = entry.path().string(); | |
auto lastSlash = name.find_last_of("/\\"); | |
lastSlash = lastSlash == String::npos ? 0 : lastSlash + 1; | |
name = name.substr(lastSlash, name.size() - lastSlash); | |
bool entryIsFile = !std::filesystem::is_directory(entry.path()); | |
if (entryIsFile) | |
node_flags |= ImGuiTreeNodeFlags_Leaf | ImGuiTreeNodeFlags_NoTreePushOnOpen; | |
bool node_open = ImGui::TreeNodeEx((void*)(intptr_t)(*count), node_flags, name.c_str()); | |
if (ImGui::IsItemClicked()) | |
{ | |
node_clicked = *count; | |
any_node_clicked = true; | |
} | |
(*count)--; | |
if (!entryIsFile) | |
{ | |
if (node_open) | |
{ | |
auto clickState = DirectoryTreeViewRecursive(entry.path(), count, selection_mask); | |
if (!any_node_clicked) | |
{ | |
any_node_clicked = clickState.first; | |
node_clicked = clickState.second; | |
} | |
ImGui::TreePop(); | |
} | |
else | |
{ | |
for (const auto& e : std::filesystem::recursive_directory_iterator(entry.path())) | |
(*count)--; | |
} | |
} | |
} | |
return { any_node_clicked, node_clicked }; | |
} | |
void OnImGui(std::string directoryPath) | |
{ | |
ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2{ 0.0f, 0.0f }); | |
ImGui::Begin("Assets"); | |
if (ImGui::CollapsingHeader("Assets")) | |
{ | |
uint32_t count = 0; | |
for (const auto& entry : std::filesystem::recursive_directory_iterator(directoryPath)) | |
count++; | |
static int selection_mask = 0; | |
auto clickState = DirectoryTreeViewRecursive(directoryPath, &count, &selection_mask); | |
if (clickState.first) | |
{ | |
// Update selection state | |
// (process outside of tree loop to avoid visual inconsistencies during the clicking frame) | |
if (ImGui::GetIO().KeyCtrl) | |
selection_mask ^= BIT(clickState.second); // CTRL+click to toggle | |
else //if (!(selection_mask & (1 << clickState.second))) // Depending on selection behavior you want, may want to preserve selection when clicking on item that is part of the selection | |
selection_mask = BIT(clickState.second); // Click to single-select | |
} | |
} | |
ImGui::End(); | |
ImGui::PopStyleVar(); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment