diff options
| author | Nic Gaffney <gaffney_nic@protonmail.com> | 2024-09-06 22:29:38 -0500 |
|---|---|---|
| committer | Nic Gaffney <gaffney_nic@protonmail.com> | 2024-09-06 22:29:38 -0500 |
| commit | 52a2f5b69eaf3430623ef2ebeeca0c50a3b8217c (patch) | |
| tree | 0fc74f5b192d74452ad74f22ad512b8b663d2139 /vendor/rlImGui-main/examples/asset_browser | |
| parent | ad6d55aeaa7c87a4008e56a5a3922d2608c73239 (diff) | |
| download | particle-sim-52a2f5b69eaf3430623ef2ebeeca0c50a3b8217c.tar.gz | |
Quickfix: rlimgui bindings added to vendor/
Diffstat (limited to 'vendor/rlImGui-main/examples/asset_browser')
7 files changed, 684 insertions, 0 deletions
diff --git a/vendor/rlImGui-main/examples/asset_browser/asset_browser.cpp b/vendor/rlImGui-main/examples/asset_browser/asset_browser.cpp new file mode 100644 index 0000000..a09070a --- /dev/null +++ b/vendor/rlImGui-main/examples/asset_browser/asset_browser.cpp @@ -0,0 +1,280 @@ +/******************************************************************************************* +* +* raylib-extras [ImGui] example - asset browser +* +* This is a more complex ImGui Integration +* It shows how to build windows on top of 2d and 3d views using a render texture +* +* Copyright (c) 2024 Jeffery Myers +* +********************************************************************************************/ + +#define _CRT_NONSTDC_NO_WARNINGS + +#include "asset_browser.h" +#include "imgui_utils.h" +#include "imgui.h" +#include "imgui_internal.h" +#include "raylib.h" +#include "extras/IconsFontAwesome6.h" + +#include <algorithm> + + +AssetBrowserPanel::AssetBrowserPanel() +{ + AssetRoot = GetWorkingDirectory(); + RebuildFolderTree(); + SetCurrentFolder(&FolderRoot); + + CurrentView = &ListView; +} + +void AssetBrowserPanel::Show() +{ + ShowHeader(); + + ImGuiTableFlags flags = ImGuiTableFlags_Resizable | ImGuiTableFlags_SizingStretchSame | ImGuiTableFlags_Borders; + + if (ImGui::BeginTable("AssetBrowserTab", 2, flags, ImGui::GetContentRegionAvail())) + { + ImGui::TableSetupColumn("FolderView", ImGuiTableColumnFlags_None, 0.25f); + ImGui::TableSetupColumn("AssetView", ImGuiTableColumnFlags_None, 0.75f); + ImGui::TableNextRow(); + ImGui::TableNextColumn(); + + if (ImGui::BeginChild("FolderList", ImGui::GetContentRegionAvail(),ImGuiChildFlags_None, ImGuiWindowFlags_None)) + { + ShowFolderTree(); + ImGui::EndChild(); + } + + ImGui::TableNextColumn(); + ShowFilePane(); + ImGui::EndTable(); + } +} + +void AssetBrowserPanel::RebuildFolderTree() +{ + FolderRoot.Children.clear(); + + FolderRoot.FullPath = AssetRoot; + FolderRoot.Name = GetFileNameWithoutExt(AssetRoot.c_str()); + FolderRoot.Parent = nullptr; + FolderRoot.Icon = ICON_FA_SERVER; + FolderRoot.ForceOpenNextFrame = true; + FolderRoot.PopulateChildren(); +} + +void AssetBrowserPanel::SetCurrentFolder(FolderInfo* folder) +{ + if (CurrentFolderContents.Folder == folder) + return; + + CurrentFolderContents.Folder = folder; + CurrentFolderContents.Files.clear(); + + if (folder == nullptr) + return; + + FolderInfo* openFolder = folder; + while (openFolder != nullptr) + { + openFolder->ForceOpenNextFrame = true; + openFolder = openFolder->Parent; + } + + auto files = LoadDirectoryFiles(CurrentFolderContents.Folder->FullPath.c_str()); + + for (unsigned int i = 0; i < files.count; i++) + { + if (DirectoryExists(files.paths[i])) + continue; + + const char* name = GetFileName(files.paths[i]); + if (!name || *name == '.') + continue; + + FileInfo& file = CurrentFolderContents.Files.emplace_back(); + file.FullPath = files.paths[i]; + file.Name = name; + file.Icon = GetFileIcon(name); + } + + UnloadDirectoryFiles(files); +} + +void AssetBrowserPanel::FolderInfo::PopulateChildren() +{ + constexpr Color folderColor = { 255,255,145,255 }; + + auto folders = LoadDirectoryFiles(FullPath.c_str()); + + for (unsigned int i = 0; i < folders.count; i++) + { + if (DirectoryExists(folders.paths[i])) + { + const char* name = GetFileNameWithoutExt(folders.paths[i]); + if (!name || *name == '.') + continue; + + FolderInfo& child = Children.emplace_back(); + child.FullPath = folders.paths[i]; + child.Name = name; + child.Parent = this; + child.Tint = folderColor; + child.Icon = ICON_FA_FOLDER; + child.PopulateChildren(); + } + } + UnloadDirectoryFiles(folders); +} + +bool AssetBrowserPanel::ShowFolderTreeNode(FolderInfo& info) +{ + ImGuiTreeNodeFlags flags = ImGuiTreeNodeFlags_OpenOnArrow | ImGuiTreeNodeFlags_OpenOnDoubleClick; + if (info.Children.empty()) + flags |= ImGuiTreeNodeFlags_Leaf; + + if (CurrentFolderContents.Folder == &info) + flags |= ImGuiTreeNodeFlags_Selected; + + if (info.ForceOpenNextFrame) + { + ImGui::SetNextItemOpen(true); + } + + bool open = ImGui::TreeNodeEx(info.Name.c_str(), flags, "%s %s", info.Icon.c_str(), info.Name.c_str()); + + if (info.ForceOpenNextFrame && CurrentFolderContents.Folder == &info) + ImGui::ScrollToItem(ImGuiScrollFlags_KeepVisibleCenterY); + + info.ForceOpenNextFrame = false; + if (ImGui::IsItemClicked()) + SetCurrentFolder(&info); + + if (open) + { + for (auto& node : info.Children) + ShowFolderTreeNode(node); + + ImGui::TreePop(); + } + + return CurrentFolderContents.Folder == &info; +} + +void AssetBrowserPanel::ShowHeader() +{ + ImGui::PushStyleVar(ImGuiStyleVar_ChildBorderSize, 1); + if (ImGui::BeginChild("Header", ImVec2{ ImGui::GetContentRegionAvail().x, ImGui::GetFrameHeight() })) + { + ImGui::Text("%s Root", ICON_FA_FOLDER_OPEN); + ImGui::SameLine(); + ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x * 0.33f); + ImGui::InputText("###Path", (char*)(CurrentFolderContents.Folder->FullPath.c_str() + AssetRoot.size()), CurrentFolderContents.Folder->FullPath.size(), ImGuiInputTextFlags_ReadOnly); + + ImGui::EndChild(); + } + ImGui::PopStyleVar(); +} + +void AssetBrowserPanel::ShowFolderTree() +{ + ShowFolderTreeNode(FolderRoot); +} + +void AssetBrowserPanel::ShowFilePane() +{ + if (ImGui::BeginChild("FileList", ImGui::GetContentRegionAvail(), ImGuiChildFlags_None, ImGuiWindowFlags_None)) + { + if (CurrentView) + { + auto *item = CurrentView->Show(CurrentFolderContents); + if (item) + { + AssetItemInfo* assetItem = static_cast<AssetItemInfo*>(item); + if (!assetItem->IsFile()) + SetCurrentFolder(static_cast<FolderInfo*>(item)); + } + } + ImGui::EndChild(); + } +} + +ViewableItem* AssetBrowserPanel::AssetContainer::Reset() +{ + FileItr = Files.begin(); + FolderItr = Folder->Children.begin(); + if (FileItr != Files.end()) + return &(*FileItr); + if (FolderItr != Folder->Children.end()) + return &(*FolderItr); + + return nullptr; +} + +size_t AssetBrowserPanel::AssetContainer::Count() +{ + return Files.size() + Folder->Children.size(); +} + +ViewableItem* AssetBrowserPanel::AssetContainer::Next() +{ + if (FileItr != Files.end()) + { + FileItr++; + if (FileItr != Files.end()) + return &(*FileItr); + else + { + if (FolderItr != Folder->Children.end()) + return &(*FolderItr); + else + return nullptr; + } + } + + if (FolderItr != Folder->Children.end()) + { + FolderItr++; + if (FolderItr != Folder->Children.end()) + return &(*FolderItr); + } + + return nullptr; +} + +const char* AssetBrowserPanel::GetFileIcon(const char* filename) +{ + const char* e = GetFileExtension(filename); + + if (e == nullptr) + return ICON_FA_FILE; + + std::string ext = e; + + std::transform(ext.begin(), ext.end(), ext.begin(), + [](unsigned char c) { return std::tolower(c); } // correct + ); + + if (!ext.empty()) + { + if (ext==".png") + return ICON_FA_FILE_IMAGE; + + if (ext==".wav" || ext==".mp3" || ext==".oog") + return ICON_FA_FILE_AUDIO; + + if (ext==".ttf" || ext==".otf" || ext==".fnt") + return ICON_FA_FONT; + + if (ext==".txt" || ext==".md") + return ICON_FA_FILE_LINES; + + if (ext==".lua" || ext==".c" || ext==".h" || ext==".cpp") + return ICON_FA_FILE_CODE; + } + return ICON_FA_FILE; +}
\ No newline at end of file diff --git a/vendor/rlImGui-main/examples/asset_browser/asset_browser.h b/vendor/rlImGui-main/examples/asset_browser/asset_browser.h new file mode 100644 index 0000000..206e699 --- /dev/null +++ b/vendor/rlImGui-main/examples/asset_browser/asset_browser.h @@ -0,0 +1,95 @@ +/******************************************************************************************* +* +* raylib-extras [ImGui] example - asset browser +* +* This is a more complex ImGui Integration +* It shows how to build windows on top of 2d and 3d views using a render texture +* +* Copyright (c) 2024 Jeffery Myers +* +********************************************************************************************/ + +#pragma once + +#include "item_view.h" +#include "raylib.h" + +#include <string> +#include <vector> +#include <list> + +class AssetBrowserPanel +{ +public: + AssetBrowserPanel(); + + void Show(); + +private: + std::string AssetRoot; + + class AssetItemInfo : public ViewableItem + { + protected: + bool File = false; + + public: + AssetItemInfo(bool file) : File(file) {} + bool IsFile() const { return File; } + }; + + class FileInfo : public AssetItemInfo + { + public: + FileInfo() : AssetItemInfo(true) {} + + std::string FullPath; + }; + + class FolderInfo : public AssetItemInfo + { + public: + FolderInfo() : AssetItemInfo(false) {} + + std::string FullPath; + FolderInfo* Parent = nullptr; + std::list<FolderInfo> Children; + + bool ForceOpenNextFrame = false; + + void PopulateChildren(); + }; + + FolderInfo FolderRoot; + + class AssetContainer : public ViewableItemContainer + { + public: + ViewableItem* Reset() override; + size_t Count() override; + ViewableItem* Next() override; + + FolderInfo* Folder = nullptr; + std::vector<FileInfo> Files; + + std::vector<FileInfo>::iterator FileItr; + std::list<FolderInfo>::iterator FolderItr; + }; + + AssetContainer CurrentFolderContents; + + ListItemView ListView; + + ItemView* CurrentView = nullptr; + + void RebuildFolderTree(); + + void SetCurrentFolder(FolderInfo* folder); + + bool ShowFolderTreeNode(FolderInfo& folder); + void ShowFolderTree(); + void ShowFilePane(); + void ShowHeader(); + + const char* GetFileIcon(const char* filename); +};
\ No newline at end of file diff --git a/vendor/rlImGui-main/examples/asset_browser/imgui_utils.cpp b/vendor/rlImGui-main/examples/asset_browser/imgui_utils.cpp new file mode 100644 index 0000000..da87520 --- /dev/null +++ b/vendor/rlImGui-main/examples/asset_browser/imgui_utils.cpp @@ -0,0 +1,94 @@ +/******************************************************************************************* +* +* raylib-extras [ImGui] example - asset browser +* +* This is a more complex ImGui Integration +* It shows how to build windows on top of 2d and 3d views using a render texture +* +* Copyright (c) 2024 Jeffery Myers +* +********************************************************************************************/ + +#include "imgui_utils.h" + +#include "imgui.h" +#include "imgui_internal.h" + +namespace ImGuiUtils +{ + + bool IsSpace(char aCharacter) + { + // all space characters are values 32 or less (space is 32) + // so we can convert them to a bitmask and use a single condition + const int mask = (1 << (' ' - 1)) | (1 << ('\f' - 1)) | (1 << ('\n' - 1)) | (1 << ('\r' - 1)) | (1 << ('\t' - 1)) | (1 << ('\v' - 1)); + return (mask & (1 << ((aCharacter && aCharacter <= 32) * (aCharacter - 1)))) != 0; + } + + //------------------------------------------------------------------------------------------------- + // Todo: Add support for soft-hyphens when using word boundaries? + //------------------------------------------------------------------------------------------------- + void TextWithEllipsis(const char* string, float aMaxWidth, bool useWordBoundaries, float aSpacing) + { + char const* partStart = string; + char const* partEnd = string; + + ImWchar elipsisChar = ImGui::GetFont()->EllipsisChar; + char elipsisText[8]; + ImTextStrToUtf8(elipsisText, sizeof(elipsisText), &elipsisChar, (&elipsisChar) + 1); + + if (aSpacing < 0.0f) aSpacing = ImGui::GetStyle().ItemSpacing.x; + + float const ellipsisWidth = ImGui::CalcTextSize(elipsisText).x + aSpacing; + float width = 0; + bool addElipsis = false; + + while (*partStart != 0 ) + { + // Add space to next segment + while (IsSpace(*partEnd)) + partEnd++; + + if (useWordBoundaries) + { + // get next 'word' by looking for space after non-space + while (*partEnd != 0 && !IsSpace(*partEnd)) + ++partEnd; + } + else + { + if (*partEnd != 0) + ++partEnd; + } + + ImVec2 const wordSize = ImGui::CalcTextSize(partStart, partEnd); + + // Clearly we have space for this word so just add it + if (wordSize.x + width + ellipsisWidth < aMaxWidth) + { + width += wordSize.x; + partStart = partEnd; + } + // If we're just at the end of the word and we just fit then we can commit here + else if (*partEnd == 0 && wordSize.x + width < aMaxWidth) + { + width += wordSize.x; + partStart = partEnd; + } + // we're done so add elipsis where the current segment starts + else + { + addElipsis = true; + break; + } + } + + ImGui::TextUnformatted(string, partStart); + + if (addElipsis) + { + ImGui::SameLine(0.0f, aSpacing); + ImGui::TextUnformatted(elipsisText); + } + } +}
\ No newline at end of file diff --git a/vendor/rlImGui-main/examples/asset_browser/imgui_utils.h b/vendor/rlImGui-main/examples/asset_browser/imgui_utils.h new file mode 100644 index 0000000..124ff8b --- /dev/null +++ b/vendor/rlImGui-main/examples/asset_browser/imgui_utils.h @@ -0,0 +1,19 @@ +/******************************************************************************************* +* +* raylib-extras [ImGui] example - asset browser +* +* This is a more complex ImGui Integration +* It shows how to build windows on top of 2d and 3d views using a render texture +* +* Copyright (c) 2024 Jeffery Myers +* +********************************************************************************************/ + +#pragma once + +#include <string> + +namespace ImGuiUtils +{ + void TextWithEllipsis(const char* string, float maxWidth, bool useWordBoundaries = false, float aSpacing = 0); +}
\ No newline at end of file diff --git a/vendor/rlImGui-main/examples/asset_browser/item_view.h b/vendor/rlImGui-main/examples/asset_browser/item_view.h new file mode 100644 index 0000000..c70191b --- /dev/null +++ b/vendor/rlImGui-main/examples/asset_browser/item_view.h @@ -0,0 +1,47 @@ +/******************************************************************************************* +* +* raylib-extras [ImGui] example - asset browser +* +* This is a more complex ImGui Integration +* It shows how to build windows on top of 2d and 3d views using a render texture +* +* Copyright (c) 2024 Jeffery Myers +* +********************************************************************************************/ + +#pragma once + +#include <string> +#include "raylib.h" + +class ViewableItem +{ +public: + virtual ~ViewableItem() = default; + + std::string Name; + std::string Icon; + Color Tint = BLANK; +}; + +class ViewableItemContainer +{ +public: + virtual ~ViewableItemContainer() = default; + virtual ViewableItem* Reset() = 0; + virtual size_t Count() = 0; + virtual ViewableItem* Next() = 0; +}; + +class ItemView +{ +public: + virtual ~ItemView() = default; + virtual ViewableItem* Show(ViewableItemContainer& container) = 0; +}; + +class ListItemView : public ItemView +{ +public: + ViewableItem* Show(ViewableItemContainer& container) override; +}; diff --git a/vendor/rlImGui-main/examples/asset_browser/item_views.cpp b/vendor/rlImGui-main/examples/asset_browser/item_views.cpp new file mode 100644 index 0000000..0c66a57 --- /dev/null +++ b/vendor/rlImGui-main/examples/asset_browser/item_views.cpp @@ -0,0 +1,53 @@ +/******************************************************************************************* +* +* raylib-extras [ImGui] example - asset browser +* +* This is a more complex ImGui Integration +* It shows how to build windows on top of 2d and 3d views using a render texture +* +* Copyright (c) 2024 Jeffery Myers +* +********************************************************************************************/ + +#include "item_view.h" + +#include "imgui.h" +#include "imgui_utils.h" +#include "rlImGuiColors.h" +#include "raylib.h" + +extern ImFont* IconFont; + +ViewableItem* ListItemView::Show(ViewableItemContainer& container) +{ + ViewableItem* item = container.Reset(); + + ViewableItem* selected = nullptr; + while (item) + { + float x = ImGui::GetCursorPosX(); + + const char* name = TextFormat("###%s", item->Name.c_str()); + if (item->Tint.a > 0) + ImGui::TextColored(rlImGuiColors::Convert(item->Tint), " %s", item->Icon.c_str()); + else + ImGui::Text(" %s", item->Icon.c_str()); + + ImGui::SameLine(0, 0); + ImGui::Text(" %s", item->Name.c_str()); + ImGui::SameLine(0, 0); + + ImGui::SetCursorPosX(x); + //ImGui::SetItemAllowOverlap(); + + ImGui::Selectable(name); + if (ImGui::IsItemHovered() && ImGui::IsMouseDoubleClicked(0)) + { + selected = item; + } + + item = container.Next(); + } + + return selected; +}
\ No newline at end of file diff --git a/vendor/rlImGui-main/examples/asset_browser/main.cpp b/vendor/rlImGui-main/examples/asset_browser/main.cpp new file mode 100644 index 0000000..5119ce9 --- /dev/null +++ b/vendor/rlImGui-main/examples/asset_browser/main.cpp @@ -0,0 +1,96 @@ +/******************************************************************************************* +* +* raylib-extras [ImGui] example - asset browser +* +* This is a more complex ImGui Integration +* It shows how to build windows on top of 2d and 3d views using a render texture +* +* Copyright (c) 2024 Jeffery Myers +* +********************************************************************************************/ + + +#include "raylib.h" +#include "raymath.h" + +#include "imgui.h" +#include "rlImGui.h" +#include "rlImGuiColors.h" +#include "extras/FA6FreeSolidFontData.h" + +#include "asset_browser.h" + +#include <limits> + + +ImFont* IconFont = nullptr; + +int main(int argc, char* argv[]) +{ + // Initialization + //-------------------------------------------------------------------------------------- + int screenWidth = 1900; + int screenHeight = 900; + + SetConfigFlags(FLAG_MSAA_4X_HINT | FLAG_VSYNC_HINT); + InitWindow(screenWidth, screenHeight, "raylib-Extras [ImGui] example - Asset browser"); + SetTargetFPS(144); + + rlImGuiBeginInitImGui(); + ImGui::StyleColorsDark(); + + + static const ImWchar icons_ranges[] = { ICON_MIN_FA, ICON_MAX_FA, 0 }; + ImFontConfig icons_config; + icons_config.MergeMode = true; + icons_config.PixelSnapH = true; + icons_config.FontDataOwnedByAtlas = false; + + icons_config.GlyphMaxAdvanceX = std::numeric_limits<float>::max(); + icons_config.RasterizerMultiply = 1.0f; + icons_config.OversampleH = 2; + icons_config.OversampleV = 1; + + icons_config.GlyphRanges = icons_ranges; + + ImGuiIO& io = ImGui::GetIO(); + io.Fonts->AddFontFromMemoryCompressedTTF((void*)fa_solid_900_compressed_data, fa_solid_900_compressed_size, 12, &icons_config, icons_ranges); + + icons_config.MergeMode = false; + IconFont = io.Fonts->AddFontFromMemoryCompressedTTF((void*)fa_solid_900_compressed_data, fa_solid_900_compressed_size, 72, &icons_config, icons_ranges); + + rlImGuiEndInitImGui(); + + AssetBrowserPanel assetBrowser; + + // Main game loop + while (!WindowShouldClose()) // Detect window close button or ESC key + { + + BeginDrawing(); + ClearBackground(DARKGRAY); + + rlImGuiBegin(); + + ImGui::SetNextWindowPos(ImVec2(0, 0)); + ImGui::SetNextWindowSize(ImVec2(float(GetScreenWidth()), float(GetScreenHeight()))); + if (ImGui::Begin("Frame", 0, ImGuiWindowFlags_NoDecoration | ImGuiWindowFlags_NoSavedSettings)) + { + assetBrowser.Show(); + } + ImGui::End(); + + rlImGuiEnd(); + + EndDrawing(); + //---------------------------------------------------------------------------------- + } + rlImGuiShutdown(); + + // De-Initialization + //-------------------------------------------------------------------------------------- + CloseWindow(); // Close window and OpenGL context + //-------------------------------------------------------------------------------------- + + return 0; +}
\ No newline at end of file |
