Load/Save dialogues implemented

This commit is contained in:
2026-04-01 00:04:06 +03:00
parent abd961ea0f
commit c31892ac05
2 changed files with 170 additions and 4 deletions

View File

@@ -7,6 +7,8 @@
#include "../ui/RenderableEditor.hpp"
#include <imgui.h>
#include <algorithm>
#include <filesystem>
#include <cstring>
EditorUISystem::EditorUISystem(flecs::world &world,
Ogre::SceneManager *sceneMgr)
@@ -115,6 +117,11 @@ void EditorUISystem::update()
if (m_gizmo && m_gizmo->isAttached()) {
m_gizmo->update();
}
// Render file dialog if open
if (m_showFileDialog) {
renderFileDialog();
}
}
void EditorUISystem::setSelectedEntity(flecs::entity entity)
@@ -149,11 +156,11 @@ void EditorUISystem::renderHierarchyWindow()
if (ImGui::BeginMenuBar()) {
// File menu
if (ImGui::BeginMenu("File")) {
if (ImGui::MenuItem("Save Scene", "Ctrl+S")) {
saveScene("scene.json");
if (ImGui::MenuItem("Save Scene...", "Ctrl+S")) {
showFileDialog(true);
}
if (ImGui::MenuItem("Load Scene", "Ctrl+O")) {
loadScene("scene.json");
if (ImGui::MenuItem("Load Scene...", "Ctrl+O")) {
showFileDialog(false);
}
ImGui::EndMenu();
}
@@ -703,3 +710,145 @@ void EditorUISystem::loadScene(const std::string& filepath)
"Failed to load scene: " + m_serializer->getLastError());
}
}
// File Dialog Implementation
void EditorUISystem::showFileDialog(bool isSave)
{
m_showFileDialog = true;
m_fileDialogIsSave = isSave;
m_refreshDirectory = true;
// Initialize current path if empty
if (m_currentPath.empty()) {
m_currentPath = std::filesystem::current_path().string();
}
// Set default filename for save dialog
if (isSave && strlen(m_filenameBuffer) == 0) {
std::strncpy(m_filenameBuffer, "scene.json", sizeof(m_filenameBuffer) - 1);
}
}
void EditorUISystem::closeFileDialog()
{
m_showFileDialog = false;
}
void EditorUISystem::renderFileDialog()
{
const char* title = m_fileDialogIsSave ? "Save Scene" : "Load Scene";
// Center the dialog
ImVec2 center = ImGui::GetMainViewport()->GetCenter();
ImGui::SetNextWindowPos(center, ImGuiCond_Appearing, ImVec2(0.5f, 0.5f));
ImGui::SetNextWindowSize(ImVec2(500, 400), ImGuiCond_FirstUseEver);
if (!ImGui::Begin(title, &m_showFileDialog)) {
ImGui::End();
return;
}
// Current path display
ImGui::Text("Location: %s", m_currentPath.c_str());
ImGui::Separator();
// Refresh directory contents if needed
if (m_refreshDirectory) {
m_directoryContents.clear();
try {
for (const auto& entry : std::filesystem::directory_iterator(m_currentPath)) {
m_directoryContents.push_back(entry.path().filename().string());
}
std::sort(m_directoryContents.begin(), m_directoryContents.end());
} catch (...) {
// Ignore errors (e.g., permission denied)
}
m_refreshDirectory = false;
}
// Parent directory button
if (ImGui::Button("..")) {
std::filesystem::path p(m_currentPath);
if (p.has_parent_path()) {
m_currentPath = p.parent_path().string();
m_refreshDirectory = true;
}
}
ImGui::SameLine();
ImGui::Text("(Parent Directory)");
// File list
ImGui::BeginChild("FileList", ImVec2(0, -60), true);
for (const auto& name : m_directoryContents) {
std::filesystem::path fullPath = std::filesystem::path(m_currentPath) / name;
bool isDirectory = std::filesystem::is_directory(fullPath);
// Skip non-json files in load mode (but show directories)
if (!m_fileDialogIsSave && !isDirectory) {
if (fullPath.extension() != ".json") {
continue;
}
}
std::string label = isDirectory ? "[D] " + name : name;
if (ImGui::Selectable(label.c_str(), m_selectedFile == name)) {
if (isDirectory) {
m_currentPath = fullPath.string();
m_refreshDirectory = true;
m_selectedFile.clear();
} else {
m_selectedFile = name;
std::strncpy(m_filenameBuffer, name.c_str(), sizeof(m_filenameBuffer) - 1);
}
}
// Double-click to enter directory or select file
if (ImGui::IsItemHovered() && ImGui::IsMouseDoubleClicked(0)) {
if (isDirectory) {
m_currentPath = fullPath.string();
m_refreshDirectory = true;
m_selectedFile.clear();
}
}
}
ImGui::EndChild();
// Filename input
ImGui::Separator();
ImGui::Text("Filename:");
ImGui::SameLine();
ImGui::InputText("##filename", m_filenameBuffer, sizeof(m_filenameBuffer));
// Buttons
if (ImGui::Button(m_fileDialogIsSave ? "Save" : "Load", ImVec2(120, 0))) {
std::string filename(m_filenameBuffer);
if (!filename.empty()) {
// Add .json extension if missing in save mode
if (m_fileDialogIsSave && filename.find('.') == std::string::npos) {
filename += ".json";
}
std::string fullPath = (std::filesystem::path(m_currentPath) / filename).string();
if (m_fileDialogIsSave) {
saveScene(fullPath);
} else {
loadScene(fullPath);
}
closeFileDialog();
}
}
ImGui::SameLine();
if (ImGui::Button("Cancel", ImVec2(120, 0))) {
closeFileDialog();
}
ImGui::End();
}

View File

@@ -5,6 +5,7 @@
#include <Ogre.h>
#include <memory>
#include <string>
#include <vector>
#include "../ui/ComponentRegistry.hpp"
#include "../components/EntityName.hpp"
#include "../gizmo/Gizmo.hpp"
@@ -75,6 +76,13 @@ public:
*/
void loadScene(const std::string& filepath);
/**
* Show file dialog for save/load
*/
void showFileDialog(bool isSave);
void renderFileDialog();
void closeFileDialog();
private:
// File menu
void renderFileMenu();
@@ -116,6 +124,15 @@ private:
// Settings
bool m_parentSceneNodes = true; // Whether child entities inherit parent's SceneNode
// File dialog state
bool m_showFileDialog = false;
bool m_fileDialogIsSave = false; // true = save, false = load
std::string m_currentPath;
std::string m_selectedFile;
std::vector<std::string> m_directoryContents;
bool m_refreshDirectory = true;
char m_filenameBuffer[256] = "scene.json";
// Queries
flecs::query<EntityNameComponent> m_nameQuery;