Files
Modularity/src/EditorUI.cpp
2025-12-18 16:38:45 -05:00

306 lines
11 KiB
C++

#include "EditorUI.h"
// FileBrowser implementation
FileBrowser::FileBrowser() {
currentPath = fs::current_path();
projectRoot = currentPath;
}
void FileBrowser::refresh() {
entries.clear();
try {
for (const auto& entry : fs::directory_iterator(currentPath)) {
// Skip hidden files if not showing them
std::string filename = entry.path().filename().string();
if (!showHiddenFiles && !filename.empty() && filename[0] == '.') {
continue;
}
// Apply search filter if any
if (!matchesFilter(entry)) {
continue;
}
entries.push_back(entry);
}
// Sort: folders first, then alphabetically
std::sort(entries.begin(), entries.end(), [](const auto& a, const auto& b) {
if (a.is_directory() != b.is_directory()) {
return a.is_directory() > b.is_directory();
}
return a.path().filename().string() < b.path().filename().string();
});
} catch (...) {
}
needsRefresh = false;
}
void FileBrowser::navigateUp() {
if (currentPath.has_parent_path() && currentPath != currentPath.root_path()) {
// Don't go above project root
if (currentPath != projectRoot) {
navigateTo(currentPath.parent_path());
}
}
}
void FileBrowser::navigateTo(const fs::path& path) {
if (fs::is_directory(path)) {
// Add to history
if (historyIndex < 0 || pathHistory.empty() || pathHistory[historyIndex] != currentPath) {
// Clear forward history
if (historyIndex >= 0 && historyIndex < (int)pathHistory.size() - 1) {
pathHistory.erase(pathHistory.begin() + historyIndex + 1, pathHistory.end());
}
pathHistory.push_back(currentPath);
historyIndex = (int)pathHistory.size() - 1;
}
currentPath = path;
needsRefresh = true;
}
}
void FileBrowser::navigateBack() {
if (historyIndex > 0) {
historyIndex--;
currentPath = pathHistory[historyIndex];
needsRefresh = true;
}
}
void FileBrowser::navigateForward() {
if (historyIndex < (int)pathHistory.size() - 1) {
historyIndex++;
currentPath = pathHistory[historyIndex];
needsRefresh = true;
}
}
void FileBrowser::setProjectRoot(const fs::path& root) {
projectRoot = root;
currentPath = root;
pathHistory.clear();
historyIndex = -1;
needsRefresh = true;
}
FileCategory FileBrowser::getFileCategory(const fs::directory_entry& entry) const {
if (entry.is_directory()) return FileCategory::Folder;
std::string ext = entry.path().extension().string();
std::transform(ext.begin(), ext.end(), ext.begin(), ::tolower);
// Scene files
if (ext == ".modu" || ext == ".scene") return FileCategory::Scene;
// Model files
if (ext == ".fbx" || ext == ".obj" || ext == ".gltf" || ext == ".glb" ||
ext == ".dae" || ext == ".blend" || ext == ".3ds" || ext == ".ply" ||
ext == ".stl" || ext == ".x" || ext == ".md5mesh" || ext == ".rmesh") {
return FileCategory::Model;
}
// Material files
if (ext == ".mat") return FileCategory::Material;
// Texture files
if (ext == ".png" || ext == ".jpg" || ext == ".jpeg" || ext == ".bmp" ||
ext == ".tga" || ext == ".dds" || ext == ".hdr") {
return FileCategory::Texture;
}
// Shader files
if (ext == ".glsl" || ext == ".vert" || ext == ".frag" || ext == ".hlsl" ||
ext == ".shader") {
return FileCategory::Shader;
}
// Script files
if (ext == ".cpp" || ext == ".c" || ext == ".h" || ext == ".hpp" ||
ext == ".lua" || ext == ".py" || ext == ".cs") {
return FileCategory::Script;
}
// Audio files
if (ext == ".wav" || ext == ".mp3" || ext == ".ogg" || ext == ".flac") {
return FileCategory::Audio;
}
// Text files
if (ext == ".txt" || ext == ".md" || ext == ".json" || ext == ".xml" ||
ext == ".yaml" || ext == ".ini" || ext == ".cfg") {
return FileCategory::Text;
}
return FileCategory::Unknown;
}
const char* FileBrowser::getFileIcon(const fs::directory_entry& entry) const {
FileCategory category = getFileCategory(entry);
switch (category) {
case FileCategory::Folder: return "folder";
case FileCategory::Scene: return "scene";
case FileCategory::Model: return "model";
case FileCategory::Material: return "material";
case FileCategory::Texture: return "image";
case FileCategory::Shader: return "shader";
case FileCategory::Script: return "code";
case FileCategory::Audio: return "audio";
case FileCategory::Text: return "text";
default: return "file";
}
}
bool FileBrowser::isModelFile(const fs::directory_entry& entry) const {
return getFileCategory(entry) == FileCategory::Model;
}
bool FileBrowser::isSceneFile(const fs::directory_entry& entry) const {
return getFileCategory(entry) == FileCategory::Scene;
}
bool FileBrowser::isTextureFile(const fs::directory_entry& entry) const {
return getFileCategory(entry) == FileCategory::Texture;
}
bool FileBrowser::isOBJFile(const fs::directory_entry& entry) const {
if (entry.is_directory()) return false;
std::string ext = entry.path().extension().string();
std::transform(ext.begin(), ext.end(), ext.begin(), ::tolower);
return ext == ".obj";
}
bool FileBrowser::matchesFilter(const fs::directory_entry& entry) const {
if (searchFilter.empty()) return true;
std::string filename = entry.path().filename().string();
std::string filterLower = searchFilter;
std::string filenameLower = filename;
std::transform(filterLower.begin(), filterLower.end(), filterLower.begin(), ::tolower);
std::transform(filenameLower.begin(), filenameLower.end(), filenameLower.begin(), ::tolower);
return filenameLower.find(filterLower) != std::string::npos;
}
void applyModernTheme() {
ImGuiStyle& style = ImGui::GetStyle();
ImVec4* colors = style.Colors;
ImVec4 slate = ImVec4(0.09f, 0.10f, 0.12f, 1.00f);
ImVec4 panel = ImVec4(0.11f, 0.12f, 0.14f, 1.00f);
ImVec4 overlay = ImVec4(0.07f, 0.08f, 0.10f, 0.98f);
ImVec4 accent = ImVec4(0.33f, 0.63f, 0.98f, 1.00f);
ImVec4 accentMuted = ImVec4(0.25f, 0.46f, 0.78f, 1.00f);
ImVec4 highlight = ImVec4(0.18f, 0.23f, 0.30f, 1.00f);
colors[ImGuiCol_Text] = ImVec4(0.87f, 0.89f, 0.92f, 1.00f);
colors[ImGuiCol_TextDisabled] = ImVec4(0.52f, 0.56f, 0.62f, 1.00f);
colors[ImGuiCol_WindowBg] = panel;
colors[ImGuiCol_ChildBg] = ImVec4(0.10f, 0.11f, 0.13f, 1.00f);
colors[ImGuiCol_PopupBg] = overlay;
colors[ImGuiCol_Border] = ImVec4(0.21f, 0.24f, 0.28f, 0.60f);
colors[ImGuiCol_BorderShadow] = ImVec4(0, 0, 0, 0);
colors[ImGuiCol_MenuBarBg] = ImVec4(0.06f, 0.07f, 0.08f, 1.00f);
colors[ImGuiCol_Header] = highlight;
colors[ImGuiCol_HeaderHovered] = ImVec4(0.22f, 0.28f, 0.36f, 1.00f);
colors[ImGuiCol_HeaderActive] = ImVec4(0.24f, 0.44f, 0.72f, 1.00f);
colors[ImGuiCol_Button] = ImVec4(0.17f, 0.19f, 0.22f, 1.00f);
colors[ImGuiCol_ButtonHovered] = ImVec4(0.23f, 0.27f, 0.33f, 1.00f);
colors[ImGuiCol_ButtonActive] = ImVec4(0.26f, 0.36f, 0.46f, 1.00f);
colors[ImGuiCol_FrameBg] = ImVec4(0.14f, 0.15f, 0.18f, 1.00f);
colors[ImGuiCol_FrameBgHovered] = ImVec4(0.20f, 0.22f, 0.27f, 1.00f);
colors[ImGuiCol_FrameBgActive] = ImVec4(0.26f, 0.32f, 0.41f, 1.00f);
colors[ImGuiCol_TitleBg] = ImVec4(0.06f, 0.07f, 0.08f, 1.00f);
colors[ImGuiCol_TitleBgActive] = ImVec4(0.10f, 0.12f, 0.14f, 1.00f);
colors[ImGuiCol_TitleBgCollapsed] = ImVec4(0.04f, 0.05f, 0.06f, 1.00f);
colors[ImGuiCol_Tab] = ImVec4(0.12f, 0.13f, 0.15f, 1.00f);
colors[ImGuiCol_TabHovered] = ImVec4(0.20f, 0.28f, 0.38f, 1.00f);
colors[ImGuiCol_TabActive] = ImVec4(0.16f, 0.19f, 0.23f, 1.00f);
colors[ImGuiCol_TabUnfocused] = ImVec4(0.09f, 0.10f, 0.12f, 1.00f);
colors[ImGuiCol_TabUnfocusedActive] = ImVec4(0.13f, 0.15f, 0.18f, 1.00f);
colors[ImGuiCol_Separator] = ImVec4(0.18f, 0.20f, 0.24f, 1.00f);
colors[ImGuiCol_SeparatorHovered] = ImVec4(0.24f, 0.32f, 0.42f, 1.00f);
colors[ImGuiCol_SeparatorActive] = ImVec4(0.30f, 0.44f, 0.60f, 1.00f);
colors[ImGuiCol_ScrollbarBg] = ImVec4(0.07f, 0.08f, 0.10f, 1.00f);
colors[ImGuiCol_ScrollbarGrab] = ImVec4(0.21f, 0.23f, 0.27f, 1.00f);
colors[ImGuiCol_ScrollbarGrabHovered] = ImVec4(0.26f, 0.30f, 0.36f, 1.00f);
colors[ImGuiCol_ScrollbarGrabActive] = ImVec4(0.30f, 0.36f, 0.44f, 1.00f);
colors[ImGuiCol_CheckMark] = accent;
colors[ImGuiCol_SliderGrab] = accent;
colors[ImGuiCol_SliderGrabActive] = accentMuted;
colors[ImGuiCol_ResizeGrip] = ImVec4(0.22f, 0.26f, 0.33f, 1.00f);
colors[ImGuiCol_ResizeGripHovered] = ImVec4(0.32f, 0.46f, 0.62f, 0.80f);
colors[ImGuiCol_ResizeGripActive] = accent;
colors[ImGuiCol_DockingPreview] = ImVec4(0.33f, 0.63f, 0.98f, 0.60f);
colors[ImGuiCol_DockingEmptyBg] = ImVec4(0.05f, 0.06f, 0.07f, 1.00f);
colors[ImGuiCol_TextSelectedBg] = ImVec4(0.33f, 0.63f, 0.98f, 0.25f);
colors[ImGuiCol_NavHighlight] = accent;
colors[ImGuiCol_TableHeaderBg] = ImVec4(0.15f, 0.17f, 0.20f, 1.00f);
style.WindowRounding = 5.0f;
style.ChildRounding = 5.0f;
style.FrameRounding = 6.0f;
style.PopupRounding = 6.0f;
style.ScrollbarRounding = 10.0f;
style.GrabRounding = 6.0f;
style.TabRounding = 6.0f;
style.WindowPadding = ImVec2(10.0f, 10.0f);
style.FramePadding = ImVec2(9.0f, 5.0f);
style.ItemSpacing = ImVec2(10.0f, 6.0f);
style.ItemInnerSpacing = ImVec2(6.0f, 4.0f);
style.IndentSpacing = 18.0f;
style.WindowBorderSize = 1.0f;
style.FrameBorderSize = 1.0f;
style.PopupBorderSize = 1.0f;
style.TabBorderSize = 1.0f;
}
void setupDockspace(const std::function<void()>& menuBarContent) {
static bool dockspaceOpen = true;
static ImGuiDockNodeFlags dockspaceFlags = ImGuiDockNodeFlags_None;
ImGuiWindowFlags windowFlags = ImGuiWindowFlags_MenuBar | ImGuiWindowFlags_NoDocking;
const ImGuiViewport* viewport = ImGui::GetMainViewport();
ImGui::SetNextWindowPos(viewport->WorkPos);
ImGui::SetNextWindowSize(viewport->WorkSize);
ImGui::SetNextWindowViewport(viewport->ID);
ImGui::PushStyleVar(ImGuiStyleVar_WindowRounding, 0.0f);
ImGui::PushStyleVar(ImGuiStyleVar_WindowBorderSize, 0.0f);
windowFlags |= ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoCollapse |
ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoMove |
ImGuiWindowFlags_NoBringToFrontOnFocus | ImGuiWindowFlags_NoNavFocus;
ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(0.0f, 0.0f));
ImGui::Begin("DockSpace", &dockspaceOpen, windowFlags);
ImGui::PopStyleVar(3);
if (ImGui::BeginMenuBar()) {
if (menuBarContent) {
menuBarContent();
}
ImGui::EndMenuBar();
}
ImGuiID dockspaceId = ImGui::GetID("MainDockspace");
ImGui::DockSpace(dockspaceId, ImVec2(0.0f, 0.0f), dockspaceFlags);
ImGui::End();
}