#include "ViewportController.hpp" #include "imgui/imgui.h" #include extern "C" { #include "tinyfiledialogs.h" } TSE::EDITOR::ViewportController::ViewportController() { ImGuiIO& io = ImGui::GetIO(); io.ConfigFlags |= ImGuiConfigFlags_ViewportsEnable | ImGuiConfigFlags_DockingEnable; } bool wantOpenCreate = false; void TSE::EDITOR::ViewportController::ShowFileMenu() { // if(ImGui::MenuItem("New Project")) // { // wantOpenCreate = true; // gCreateState.confirmed = false; // gCreateState.nameBuf[0] = '\0'; // gCreateState.pathBuf[0] = '\0'; // } // if(ImGui::MenuItem("Load Project")) // { // } // if(ImGui::MenuItem("Save Project")) // { // } // ImGui::Separator(); // if(ImGui::MenuItem("Build")) // { // } // ImGui::Separator(); if(ImGui::MenuItem("Exit")) { exit(0); } } static std::optional PickFolderBlocking(const char* startPath) { const char* chosen = tinyfd_selectFolderDialog("Ordner wählen", startPath); if (chosen && chosen[0]) return std::string(chosen); return std::nullopt; } void TSE::EDITOR::ViewportController::NewProjectPopup() { if (wantOpenCreate) { ImGui::OpenPopup("Neues Element##CreateItemModal"); wantOpenCreate = false; } // WICHTIG: Diese SetNext*-Aufrufe OHNE IF davor! ImGui::SetNextWindowSize(ImVec2(520, 0), ImGuiCond_Appearing); ImGui::SetNextWindowPos(ImGui::GetMainViewport()->GetCenter(), ImGuiCond_Appearing, ImVec2(0.5f, 0.5f)); ImGui::SetNextWindowSizeConstraints(ImVec2(480, 0), ImVec2(620, FLT_MAX)); // --- POPUP --- if (ImGui::BeginPopupModal("Neues Element##CreateItemModal", nullptr, ImGuiWindowFlags_AlwaysAutoResize)) { ImGui::TextUnformatted("Name"); ImGui::SetNextItemWidth(-1); ImGui::InputText("##name", gCreateState.nameBuf, IM_ARRAYSIZE(gCreateState.nameBuf)); ImGui::Dummy(ImVec2(0, 8)); ImGui::TextUnformatted("Ordner"); ImGui::PushItemWidth(-40); ImGui::InputText("##path", gCreateState.pathBuf, IM_ARRAYSIZE(gCreateState.pathBuf)); ImGui::PopItemWidth(); ImGui::SameLine(); if (!gCreateState.pickingFolder) { if (ImGui::Button("...", ImVec2(28, 0))) { const char* startPath = (gCreateState.pathBuf[0] ? gCreateState.pathBuf : nullptr); gCreateState.pickingFolder = true; // Erzwinge neuen Thread: std::launch::async gCreateState.pickFuture = std::async(std::launch::async, [startPath]{ return PickFolderBlocking(startPath); }); } } else { // Während der Auswahl: Button disabled + kleines Status-Label ImGui::BeginDisabled(); ImGui::Button("...", ImVec2(28, 0)); ImGui::EndDisabled(); ImGui::SameLine(); ImGui::TextUnformatted("Öffne Ordner-Dialog..."); // Poll das Future: sobald fertig, Ergebnis übernehmen using namespace std::chrono_literals; if (gCreateState.pickFuture.valid() && gCreateState.pickFuture.wait_for(0ms) == std::future_status::ready) { if (auto res = gCreateState.pickFuture.get(); res && !res->empty()) { std::snprintf(gCreateState.pathBuf, IM_ARRAYSIZE(gCreateState.pathBuf), "%s", res->c_str()); } gCreateState.pickingFolder = false; } } ImGui::Dummy(ImVec2(0, 10)); ImGui::Separator(); ImGui::Dummy(ImVec2(0, 2)); // Buttons rechts float btnW = 80.0f; float totalW = btnW*2 + ImGui::GetStyle().ItemSpacing.x; float avail = ImGui::GetContentRegionAvail().x; ImGui::SetCursorPosX(ImGui::GetCursorPosX() + avail - totalW); if (ImGui::Button("OK", ImVec2(btnW, 0))) { bool valid = gCreateState.nameBuf[0] && gCreateState.pathBuf[0]; if (valid) { gCreateState.confirmed = true; ImGui::CloseCurrentPopup(); } } ImGui::SameLine(); if (ImGui::Button("Cancel", ImVec2(btnW, 0))) { gCreateState.confirmed = false; ImGui::CloseCurrentPopup(); } ImGui::EndPopup(); } if(gCreateState.confirmed) { gCreateState.confirmed = false; //ProjectManager::NewProject(gCreateState.pathBuf, gCreateState.nameBuf); } } void TSE::EDITOR::ViewportController::ShowViewsMenu() { for(auto ui : uiElements) { if(ImGui::MenuItem(ui.first.c_str())) { ui.second->SetEnabled(true); } } } void TSE::EDITOR::ViewportController::MenuBar() { ImGui::BeginMainMenuBar(); if(ImGui::BeginMenu("File")) { ShowFileMenu(); ImGui::EndMenu(); } if(ImGui::BeginMenu("Views")) { ShowViewsMenu(); ImGui::EndMenu(); } ImGui::EndMainMenuBar(); } void TSE::EDITOR::ViewportController::Docking() { ImGuiWindowFlags wndFlags = ImGuiWindowFlags_NoDocking; 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); // wndFlags |= ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoCollapse | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoMove; // wndFlags |= ImGuiWindowFlags_NoBringToFrontOnFocus | ImGuiWindowFlags_NoNavFocus; // ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, {0,0}); // ImGui::Begin("DockSpace", &dockSpaceOpen, wndFlags); // ImGui::PopStyleVar(3); uint dockspaceID = ImGui::GetID("MyDockSpace"); ImGui::DockSpaceOverViewport(dockspaceID, viewport); // ImGui::DockSpace(dockspaceID, {0,0}); // ImGui::End(); } void TSE::EDITOR::ViewportController::Update() { MenuBar(); NewProjectPopup(); Docking(); for(auto ui : uiElements) { ui.second->Render(); } } void TSE::EDITOR::ViewportController::AddGuiElement(const std::string &name, IGUIElement *element) { uiElements[name] = element; } TSE::EDITOR::IGUIElement *TSE::EDITOR::ViewportController::GetGuiElement(const std::string &name) { return uiElements.at(name); }