#include "LayerPanel.h" #include "../utils/Logger.h" #include "../core/commands/LayerCommands.h" #include #include namespace UsdLayerManager { LayerPanel::LayerPanel() : m_layerManager(nullptr) , m_selectedLayerIndex(-1) , m_showCreateDialog(false) { m_newLayerPath[0] = '\0'; m_newLayerName[0] = '\0'; } LayerPanel::~LayerPanel() { } void LayerPanel::SetLayerManager(LayerManager* manager) { m_layerManager = manager; } void LayerPanel::Render() { if (!m_layerManager) return; // Header with buttons ImGui::Text("Layers"); ImGui::SameLine(ImGui::GetWindowWidth() - 110); if (ImGui::Button("Refresh")) { m_layerManager->Refresh(); } ImGui::SameLine(); if (ImGui::Button("Add Layer")) { m_showCreateDialog = true; m_newLayerPath[0] = '\0'; strcpy_s(m_newLayerName, "new_layer.usd"); } ImGui::Separator(); // Create layer dialog if (m_showCreateDialog) { ShowCreateLayerDialog(); } // Layer list auto layers = m_layerManager->GetLayerStack(); if (layers.empty()) { ImGui::TextDisabled("No layers loaded"); return; } // Layer table if (ImGui::BeginTable("LayerTable", 4, ImGuiTableFlags_Borders | ImGuiTableFlags_RowBg | ImGuiTableFlags_Resizable | ImGuiTableFlags_ScrollY)) { ImGui::TableSetupColumn("", ImGuiTableColumnFlags_WidthFixed, 20.0f); ImGui::TableSetupColumn("Name", ImGuiTableColumnFlags_WidthStretch); ImGui::TableSetupColumn("Muted", ImGuiTableColumnFlags_WidthFixed, 60.0f); ImGui::TableSetupColumn("Type", ImGuiTableColumnFlags_WidthFixed, 80.0f); ImGui::TableHeadersRow(); for (int i = 0; i < static_cast(layers.size()); i++) { const auto& layerInfo = layers[i]; ImGui::TableNextRow(); bool isSelected = (m_selectedLayerIndex == i); // Selection column ImGui::TableSetColumnIndex(0); ImGui::PushID(i); if (ImGui::Selectable("##select", isSelected, ImGuiSelectableFlags_SpanAllColumns | ImGuiSelectableFlags_AllowOverlap)) { m_selectedLayerIndex = i; } ImGui::PopID(); // Name column ImGui::TableSetColumnIndex(1); ImVec4 textColor = ImVec4(1.0f, 1.0f, 1.0f, 1.0f); if (layerInfo.isMuted) { textColor = ImVec4(0.5f, 0.5f, 0.5f, 1.0f); } else if (layerInfo.isRootLayer) { textColor = ImVec4(0.5f, 1.0f, 0.5f, 1.0f); } else if (layerInfo.isSessionLayer) { textColor = ImVec4(0.5f, 0.7f, 1.0f, 1.0f); } ImGui::TextColored(textColor, "%s", layerInfo.displayName.c_str()); if (ImGui::IsItemHovered() && !layerInfo.realPath.empty()) { ImGui::SetTooltip("%s\n%s", layerInfo.identifier.c_str(), layerInfo.realPath.c_str()); } // Mute toggle ImGui::TableSetColumnIndex(2); bool muted = layerInfo.isMuted; ImGui::PushID(("mute_" + std::to_string(i)).c_str()); if (ImGui::Checkbox("##muted", &muted)) { if (muted) { m_layerManager->MuteLayer(layerInfo.identifier); } else { m_layerManager->UnmuteLayer(layerInfo.identifier); } } ImGui::PopID(); // Type column ImGui::TableSetColumnIndex(3); if (layerInfo.isRootLayer) { ImGui::TextColored(ImVec4(0.5f, 1.0f, 0.5f, 1.0f), "Root"); } else if (layerInfo.isSessionLayer) { ImGui::TextColored(ImVec4(0.5f, 0.7f, 1.0f, 1.0f), "Session"); } else if (layerInfo.isAnonymous) { ImGui::Text("Anonymous"); } else { ImGui::Text("Sublayer"); } // Context menu RenderLayerContextMenu(i); } ImGui::EndTable(); } } void LayerPanel::RenderLayerContextMenu(int layerIndex) { if (ImGui::BeginPopupContextItem(("layer_ctx_" + std::to_string(layerIndex)).c_str())) { auto layers = m_layerManager->GetLayerStack(); if (layerIndex < 0 || layerIndex >= static_cast(layers.size())) { ImGui::EndPopup(); return; } const auto& info = layers[layerIndex]; if (ImGui::MenuItem(info.isMuted ? "Unmute" : "Mute")) { if (info.isMuted) { m_layerManager->UnmuteLayer(info.identifier); } else { m_layerManager->MuteLayer(info.identifier); } } ImGui::Separator(); if (!info.isRootLayer && !info.isSessionLayer) { if (ImGui::MenuItem("Move Up", nullptr, false, layerIndex > 0)) { if (m_commandHistory) { // Capture order before move. auto layers = m_layerManager->GetLayerStack(); std::vector before, after; for (auto& l : layers) if (!l.isRootLayer && !l.isSessionLayer) before.push_back(l.identifier); after = before; // Find index within sublayer-only list. int subIdx = -1; for (int i = 0; i < static_cast(before.size()); ++i) if (before[i] == info.identifier) { subIdx = i; break; } if (subIdx > 0) std::swap(after[subIdx], after[subIdx - 1]); m_commandHistory->Push(std::make_unique( m_layerManager, before, after)); } else { m_layerManager->MoveSublayerUp(layerIndex); } } if (ImGui::MenuItem("Move Down", nullptr, false, layerIndex < static_cast(layers.size()) - 1)) { if (m_commandHistory) { auto layersNow = m_layerManager->GetLayerStack(); std::vector before, after; for (auto& l : layersNow) if (!l.isRootLayer && !l.isSessionLayer) before.push_back(l.identifier); after = before; int subIdx = -1; for (int i = 0; i < static_cast(before.size()); ++i) if (before[i] == info.identifier) { subIdx = i; break; } if (subIdx >= 0 && subIdx + 1 < static_cast(after.size())) std::swap(after[subIdx], after[subIdx + 1]); m_commandHistory->Push(std::make_unique( m_layerManager, before, after)); } else { m_layerManager->MoveSublayerDown(layerIndex); } } ImGui::Separator(); if (ImGui::MenuItem("Remove")) { if (m_commandHistory) { m_commandHistory->Push(std::make_unique( m_layerManager, layerIndex)); } else { m_layerManager->RemoveSublayer(layerIndex); } } } ImGui::EndPopup(); } } void LayerPanel::ShowCreateLayerDialog() { ImGui::SetNextWindowSize(ImVec2(400, 150), ImGuiCond_Always); ImGui::OpenPopup("Create New Layer"); if (ImGui::BeginPopupModal("Create New Layer", &m_showCreateDialog)) { ImGui::Text("Layer Name:"); ImGui::InputText("##name", m_newLayerName, sizeof(m_newLayerName)); ImGui::Spacing(); ImGui::Text("Save Path:"); ImGui::InputText("##path", m_newLayerPath, sizeof(m_newLayerPath)); ImGui::SameLine(); if (ImGui::Button("Browse...")) { // TODO: File save dialog } ImGui::Spacing(); if (ImGui::Button("Create", ImVec2(120, 0))) { std::string path; if (m_newLayerPath[0] != '\0') { path = std::string(m_newLayerPath) + "/" + m_newLayerName; } else { path = m_newLayerName; } if (!path.empty()) { if (m_commandHistory) { m_commandHistory->Push(std::make_unique( m_layerManager, "./" + path)); } else { m_layerManager->CreateSublayer("./" + path); } m_showCreateDialog = false; } } ImGui::SameLine(); if (ImGui::Button("Cancel", ImVec2(120, 0))) { m_showCreateDialog = false; } ImGui::EndPopup(); } } } // namespace UsdLayerManager