Add module properties popup.
Some checks failed
Build-StoryEditor / build_linux (push) Has been cancelled
Build-StoryEditor / build_win32 (push) Has been cancelled

This commit is contained in:
Anthony Rabine 2025-10-21 15:55:40 +02:00
parent dc11cb33dd
commit 8aa18fa5af
7 changed files with 165 additions and 22 deletions

View file

@ -34,6 +34,7 @@ public:
virtual void OpenProject(const std::string &uuid) = 0;
virtual void SaveProject() = 0;
virtual void SaveModule() = 0;
virtual void ImportProject(const std::string &fileName, int format) = 0;
virtual void Log(const std::string &txt, bool critical = false) = 0;
virtual void PlaySoundFile(const std::string &fileName) = 0;
@ -41,6 +42,7 @@ public:
virtual void OpenFunction(const std::string &uuid, const std::string &name) = 0;
virtual std::shared_ptr<IStoryProject> GetCurrentProject() = 0;
virtual std::shared_ptr<IStoryProject> GetCurrentModule() = 0;
// Node interaction
virtual void BuildCode(bool compileonly) = 0;

View file

@ -854,5 +854,10 @@ void AppController::ImportProject(const std::string &filePathName, int format)
std::shared_ptr<IStoryProject> AppController::GetCurrentProject()
{
return m_story; // Retourne le projet actuel
return m_story;
}
std::shared_ptr<IStoryProject> AppController::GetCurrentModule()
{
return m_module;
}

View file

@ -60,20 +60,19 @@ public:
void CloseProject();
void SaveProject();
std::shared_ptr<StoryProject> NewModule();
void SaveModule();
void CloseModule();
std::shared_ptr<StoryProject> OpenModule(const std::string &uuid);
void OpenStory(const std::string &path = "");
void SaveStory(const std::string &path = "");
void ExportStory(const std::string &filename);
std::shared_ptr<StoryProject> GetCurrentStory() const { return m_story; }
std::shared_ptr<StoryProject> GetCurrentModule() const { return m_module; }
void CompileNodes(IStoryProject::Type type);
void Build(bool compileonly);
void BuildModule(bool compileonly);
void BuildCode(std::shared_ptr<StoryProject> story, bool compileonly, bool force = false);
// --- Fonctions de IStoryManager ---
void SaveModule() override;
virtual void SetExternalSourceFile(const std::string &filename) override;
virtual void LoadBinaryStory(const std::string &filename) override;
virtual void ToggleBreakpoint(int line) override;
@ -90,6 +89,7 @@ public:
virtual std::string VmState() const override;
virtual void BuildCode(bool compileonly);
virtual std::shared_ptr<IStoryProject> GetCurrentProject() override;
virtual std::shared_ptr<IStoryProject> GetCurrentModule() override;
// --- Fonctions de IAudioEvent ---
virtual void EndOfAudio() override;

View file

@ -0,0 +1,116 @@
// module_properties_dialog.h
#ifndef MODULE_PROPERTIES_DIALOG_H
#define MODULE_PROPERTIES_DIALOG_H
#include "dialog_base.h"
#include <string>
#include "i_story_manager.h"
#include "IconsMaterialDesignIcons.h"
class ModulePropertiesDialog : public DialogBase
{
public:
ModulePropertiesDialog(IStoryManager &storyManager)
: m_storyManager(storyManager)
{
m_module_name[0] = '\0';
}
// Affiche le popup "Module Properties".
// Doit être appelée à chaque frame dans la boucle de rendu ImGui.
void Draw() override
{
auto module = m_storyManager.GetCurrentModule();
if (module)
{
if (m_firstOpen)
{
ImVec2 center = ImGui::GetMainViewport()->GetCenter();
ImGui::SetNextWindowPos(center, ImGuiCond_Appearing, ImVec2(0.5f, 0.5f));
m_firstOpen = false;
// Copy current module name to the edit buffer
std::size_t length = module->GetName().copy(m_module_name, sizeof(m_module_name) - 1);
m_module_name[length] = '\0';
}
DrawContent(module);
}
else
{
Reset();
return;
}
}
private:
IStoryManager &m_storyManager;
char m_module_name[256] = "";
// Implémentation de la méthode virtuelle pure GetTitle()
const char* GetTitle() const override
{
return "ModulePropertiesPopup";
}
void DrawContent(std::shared_ptr<IStoryProject> module)
{
if (ImGui::BeginPopupModal(GetTitle(), nullptr, ImGuiWindowFlags_AlwaysAutoResize))
{
ImGui::Text(ICON_MDI_PUZZLE_OUTLINE " Module Properties");
ImGui::Separator();
ImGui::Spacing();
// Module Name
ImGui::Text("Module name:");
ImGui::SameLine();
ImGui::SetNextItemWidth(300.0f);
ImGui::InputTextWithHint("##module_name", "Enter module name", m_module_name, IM_ARRAYSIZE(m_module_name));
ImGui::Spacing();
ImGui::Separator();
ImGui::Spacing();
// Buttons
if (ImGui::Button("OK", ImVec2(120, 0)))
{
// Validate and save
if (strlen(m_module_name) > 0)
{
module->SetName(m_module_name);
m_storyManager.SaveModule();
ImGui::CloseCurrentPopup();
Reset();
}
else
{
// Show error: name cannot be empty
ImGui::OpenPopup("EmptyNameError");
}
}
ImGui::SetItemDefaultFocus();
ImGui::SameLine();
if (ImGui::Button("Cancel", ImVec2(120, 0)))
{
ImGui::CloseCurrentPopup();
Reset();
}
// Error popup for empty name
if (ImGui::BeginPopupModal("EmptyNameError", NULL, ImGuiWindowFlags_AlwaysAutoResize))
{
ImGui::Text(ICON_MDI_ALERT " Module name cannot be empty!");
ImGui::Spacing();
if (ImGui::Button("OK", ImVec2(120, 0)))
{
ImGui::CloseCurrentPopup();
}
ImGui::EndPopup();
}
ImGui::EndPopup();
}
}
};
#endif // MODULE_PROPERTIES_DIALOG_H

View file

@ -58,7 +58,7 @@ private:
void DrawContent(std::shared_ptr<IStoryProject> story)
{
if (ImGui::BeginPopupModal(GetTitle(), NULL, ImGuiWindowFlags_AlwaysAutoResize))
if (ImGui::BeginPopupModal(GetTitle(), nullptr, ImGuiWindowFlags_AlwaysAutoResize))
{
ImGui::Text("Project name: "); ImGui::SameLine();

View file

@ -1,5 +1,7 @@
#include "main_window.h"
#include <filesystem>
#include <memory>
#include "main_window.h"
#include <SDL3/SDL.h>
#include "platform_folders.h"
@ -24,6 +26,7 @@
#include "app_controller.h"
#include "all_events.h"
#include "story_project.h"
#include "nodes_factory.h"
#include "media_node_widget.h"
@ -55,6 +58,7 @@ MainWindow::MainWindow(ILogger& logger, EventBus& eventBus, AppController& appCo
, m_moduleEditorWindow(appController, appController.GetNodesFactory(), m_widgetFactory, IStoryProject::PROJECT_TYPE_MODULE)
, m_libraryWindow(appController, appController.GetLibraryManager(), appController.GetNodesFactory(), eventBus)
, m_projectPropertiesDialog(appController, appController.GetResourceManager())
, m_modulePropertiesDialog(appController)
{
CloseProject();
CloseModule();
@ -174,12 +178,12 @@ float MainWindow::DrawMainMenuBar()
{
CloseProject();
m_story = m_appController.NewProject();
auto newProject = m_appController.NewProject();
if (m_story)
if (newProject)
{
m_appController.SaveProject();
OpenProject(m_story->GetUuid());
OpenProject(newProject->GetUuid());
}
}
@ -201,7 +205,7 @@ float MainWindow::DrawMainMenuBar()
}
*/
bool init = m_story ? true : false; // local copy because CloseProject() changes the status between BeginDisabled/EndDisabled
bool init = m_nodeEditorWindow.GetCurrentStory() ? true : false; // local copy because CloseProject() changes the status between BeginDisabled/EndDisabled
if (!init)
ImGui::BeginDisabled();
@ -244,6 +248,11 @@ float MainWindow::DrawMainMenuBar()
CloseModule();
}
if (ImGui::MenuItem("Module settings"))
{
m_modulePropertiesDialog.Show();
}
ImGui::EndMenu();
}
@ -273,10 +282,14 @@ float MainWindow::DrawMainMenuBar()
}
m_aboutDialog.Open();
if (m_story)
if (m_nodeEditorWindow.GetCurrentStory())
{
m_projectPropertiesDialog.Open();
}
if (m_moduleEditorWindow.GetCurrentStory())
{
m_modulePropertiesDialog.Open();
}
return height;
}
@ -339,8 +352,9 @@ bool MainWindow::ShowQuitConfirm()
void MainWindow::OpenProject(const std::string &uuid)
{
m_nodeEditorWindow.Load(m_story);
auto proj = m_story->GetProjectFilePath();
auto p = dynamic_pointer_cast<StoryProject>(m_appController.GetCurrentProject());
m_nodeEditorWindow.Load(p);
auto proj = p->GetProjectFilePath();
// Add to recent if not exists
if (std::find(m_recentProjects.begin(), m_recentProjects.end(), proj) == m_recentProjects.end())
{
@ -452,9 +466,14 @@ void MainWindow::RefreshProjectInformation()
{
std::string fullText = "Story Editor " + LibraryManager::GetVersion();
if (m_story)
auto p = m_nodeEditorWindow.GetCurrentStory();
if (p)
{
fullText += " - " + m_story->GetProjectFilePath();
auto proj = dynamic_pointer_cast<StoryProject>(p);
if (proj)
{
fullText += " - " + proj->GetProjectFilePath();
}
}
m_gui.SetWindowTitle(fullText);
}
@ -607,14 +626,14 @@ bool MainWindow::Loop()
ImGuiIO& io = ImGui::GetIO();
if (io.KeyCtrl && ImGui::IsKeyPressed(ImGuiKey_S, false))
{
if (moduleEditorFocused && m_module)
if (moduleEditorFocused && m_moduleEditorWindow.GetCurrentStory())
{
// Si l'éditeur de module a le focus, sauvegarder le module
m_appController.SaveModule();
m_toastNotifier.success("Module sauvegardé");
m_logger.Log("Module sauvegardé via Ctrl+S");
}
else if (m_story)
else if (m_nodeEditorWindow.GetCurrentStory())
{
// Sinon, sauvegarder l'histoire principale
m_appController.SaveProject();
@ -633,12 +652,12 @@ bool MainWindow::Loop()
{
bool moduleEditorFocused = m_moduleEditorWindow.IsFocused();
if (moduleEditorFocused && m_module)
if (moduleEditorFocused && m_moduleEditorWindow.GetCurrentStory())
{
m_logger.Log("Building module...");
m_appController.CompileNodes(IStoryProject::PROJECT_TYPE_MODULE);
}
else if (m_story)
else if (m_nodeEditorWindow.GetCurrentStory())
{
m_logger.Log("Building story...");
m_appController.CompileNodes(IStoryProject::PROJECT_TYPE_STORY);
@ -648,6 +667,7 @@ bool MainWindow::Loop()
m_aboutDialog.Draw();
m_projectPropertiesDialog.Draw();
m_modulePropertiesDialog.Draw();
m_toastNotifier.render();

View file

@ -21,6 +21,7 @@
// Dialogs
#include "about_dialog.h"
#include "project_properties_dialog.h"
#include "module_properties_dialog.h"
#include "event_bus.h"
#include "app_controller.h"
@ -31,6 +32,7 @@
#include "LanguageSelector.h"
#include "chip32_machine.h"
class MainWindow : public std::enable_shared_from_this<MainWindow>, public ILogSubject
{
public:
@ -48,9 +50,6 @@ private:
AppController &m_appController; // Controller for application logic
NodeWidgetFactory m_widgetFactory;
std::shared_ptr<StoryProject> m_story; // Current story
std::shared_ptr<StoryProject> m_module; // Current module
std::vector<std::string> m_recentProjects;
Gui m_gui;
@ -69,6 +68,7 @@ private:
// Dialogs
AboutDialog m_aboutDialog;
ProjectPropertiesDialog m_projectPropertiesDialog;
ModulePropertiesDialog m_modulePropertiesDialog;
ImGuiToastNotifier m_toastNotifier;
LanguageSelector m_languageSelector;