mirror of
https://github.com/arabine/open-story-teller.git
synced 2025-12-06 17:09:06 +01:00
Add error list dock window, cleaned some nodes
This commit is contained in:
parent
8111f0a362
commit
3e00fb1c83
20 changed files with 399 additions and 121 deletions
|
|
@ -7,7 +7,7 @@
|
|||
PrintNode::PrintNode(const std::string &type)
|
||||
: BaseNode(type, "Print Node")
|
||||
{
|
||||
// Create empty variable in memory
|
||||
// Create empty variable in memory for the format string
|
||||
auto v = std::make_shared<Variable>(m_label);
|
||||
v->SetConstant(true);
|
||||
m_label = v->GetLabel();
|
||||
|
|
@ -15,6 +15,17 @@ PrintNode::PrintNode(const std::string &type)
|
|||
|
||||
SetBehavior(BaseNode::BEHAVIOR_EXECUTION);
|
||||
|
||||
// Add execution input port (sync)
|
||||
AddInputPort(Port::EXECUTION_PORT, ">");
|
||||
|
||||
// Add 4 data input ports for arguments
|
||||
for (int i = 0; i < MAX_INPUT_COUNT; ++i) {
|
||||
AddInputPort(Port::DATA_PORT, "arg" + std::to_string(i));
|
||||
}
|
||||
|
||||
// Add execution output port
|
||||
AddOutputPort(Port::EXECUTION_PORT, ">");
|
||||
|
||||
SetText("");
|
||||
}
|
||||
|
||||
|
|
@ -24,11 +35,9 @@ void PrintNode::Initialize()
|
|||
m_variables.at(m_label)->SetTextValue(j["text"].get<std::string>());
|
||||
}
|
||||
|
||||
|
||||
void PrintNode::SetText(const std::string &text)
|
||||
{
|
||||
m_variables.at(m_label)->SetValue<std::string>(text);
|
||||
|
||||
SetInternalData({{"text", text}});
|
||||
}
|
||||
|
||||
|
|
@ -40,5 +49,4 @@ std::string PrintNode::GetLabel() const
|
|||
std::string PrintNode::GetText() const
|
||||
{
|
||||
return m_variables.at(m_label)->GetValue<std::string>();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -16,9 +16,9 @@ public:
|
|||
void SetText(const std::string &text);
|
||||
std::string GetLabel() const;
|
||||
std::string GetText() const;
|
||||
|
||||
static constexpr int MAX_INPUT_COUNT = 4;
|
||||
|
||||
private:
|
||||
std::string m_label; // Label for the string literal
|
||||
uint32_t m_arguments{0}; // number of arguments
|
||||
};
|
||||
|
||||
};
|
||||
|
|
@ -3,19 +3,19 @@
|
|||
#include "connection.h"
|
||||
#include "sys_lib.h"
|
||||
|
||||
|
||||
VariableNode::VariableNode(const std::string &type)
|
||||
: BaseNode(type, "Variable Node")
|
||||
: BaseNode(type, "Variable Node", BaseNode::BEHAVIOR_DATA)
|
||||
{
|
||||
nlohmann::json j{ {"uuid", ""} };
|
||||
SetInternalData(j);
|
||||
SetBehavior(BaseNode::BEHAVIOR_DATA);
|
||||
|
||||
// Add data output port
|
||||
AddOutputPort(Port::DATA_PORT, "value");
|
||||
}
|
||||
|
||||
void VariableNode::Initialize()
|
||||
{
|
||||
nlohmann::json j = GetInternalData();
|
||||
|
||||
m_variableUuid = j["uuid"].get<std::string>();
|
||||
}
|
||||
|
||||
|
|
@ -33,5 +33,16 @@ std::string VariableNode::GetVariableUuid() const
|
|||
return m_variableUuid;
|
||||
}
|
||||
|
||||
void VariableNode::SetVariable(std::shared_ptr<Variable> var)
|
||||
{
|
||||
m_variable = var;
|
||||
if (var) {
|
||||
SetVariableUuid(var->GetUuid());
|
||||
SetTitle(var->GetLabel());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
std::shared_ptr<Variable> VariableNode::GetVariable() const
|
||||
{
|
||||
return m_variable;
|
||||
}
|
||||
|
|
@ -1,27 +1,26 @@
|
|||
#pragma once
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "variable.h"
|
||||
#include "i_story_manager.h"
|
||||
#include "base_node.h"
|
||||
#include "i_script_node.h"
|
||||
#include "i_story_project.h"
|
||||
#include "variable.h"
|
||||
|
||||
class VariableNode : public BaseNode
|
||||
{
|
||||
public:
|
||||
|
||||
VariableNode(const std::string &type = "variable-node");
|
||||
VariableNode(const std::string &type);
|
||||
|
||||
virtual void Initialize() override;
|
||||
|
||||
void SetVariableUuid(const std::string &uuid);
|
||||
|
||||
std::string GetVariableUuid() const;
|
||||
|
||||
void SetVariable(std::shared_ptr<Variable> var);
|
||||
std::shared_ptr<Variable> GetVariable() const;
|
||||
|
||||
private:
|
||||
std::string m_variableUuid;
|
||||
|
||||
};
|
||||
|
||||
std::shared_ptr<Variable> m_variable;
|
||||
};
|
||||
|
|
@ -179,7 +179,7 @@ void StoryProject::DeleteNode(const std::string_view &page_uuid, const std::stri
|
|||
}
|
||||
}
|
||||
|
||||
std::shared_ptr<StoryPage> StoryProject::GetPage(const std::string &uuid)
|
||||
std::shared_ptr<StoryPage> StoryProject::GetPage(const std::string_view &uuid)
|
||||
{
|
||||
for (const auto & p : m_pages)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -102,7 +102,7 @@ public:
|
|||
|
||||
// Node interaction
|
||||
std::shared_ptr<StoryPage> CreatePage(const std::string_view uuid);
|
||||
std::shared_ptr<StoryPage> GetPage(const std::string &uuid);
|
||||
std::shared_ptr<StoryPage> GetPage(const std::string_view &uuid);
|
||||
void AddNode(const std::string_view &page, std::shared_ptr<BaseNode> node);
|
||||
|
||||
void AddConnection(const std::string_view &page, std::shared_ptr<Connection> c);
|
||||
|
|
|
|||
|
|
@ -147,6 +147,21 @@ public:
|
|||
return GetValue<bool>();
|
||||
}
|
||||
|
||||
std::string GetValueAsString() const {
|
||||
switch (m_valueType) {
|
||||
case ValueType::INTEGER:
|
||||
return std::to_string(GetValue<int>());
|
||||
case ValueType::FLOAT:
|
||||
return std::to_string(GetValue<float>());
|
||||
case ValueType::BOOL:
|
||||
return GetValue<bool>() ? "true" : "false";
|
||||
case ValueType::STRING:
|
||||
return GetValue<std::string>();
|
||||
default:
|
||||
return "<unknown>";
|
||||
}
|
||||
}
|
||||
|
||||
using VariableValue = std::variant<int, float, bool, std::string>;
|
||||
|
||||
std::string GetUuid() const {
|
||||
|
|
|
|||
|
|
@ -138,6 +138,7 @@ set(SRCS
|
|||
## Docks
|
||||
src/docks/emulator_dock.cpp
|
||||
src/docks/resources_dock.cpp
|
||||
src/docks/error_list_dock.cpp
|
||||
|
||||
# src/node_editor/media_node_widget.cpp
|
||||
src/node_editor/base_node_widget.cpp
|
||||
|
|
|
|||
|
|
@ -9,32 +9,32 @@ Size=400,400
|
|||
Collapsed=0
|
||||
|
||||
[Window][Library Manager]
|
||||
Pos=435,26
|
||||
Size=845,388
|
||||
Pos=656,26
|
||||
Size=624,313
|
||||
Collapsed=0
|
||||
DockId=0x00000003,0
|
||||
|
||||
[Window][Console]
|
||||
Pos=60,450
|
||||
Size=610,270
|
||||
Size=475,270
|
||||
Collapsed=0
|
||||
DockId=0x00000004,0
|
||||
|
||||
[Window][Emulator]
|
||||
Pos=435,26
|
||||
Size=845,388
|
||||
Pos=656,26
|
||||
Size=624,313
|
||||
Collapsed=0
|
||||
DockId=0x00000003,5
|
||||
|
||||
[Window][Code viewer]
|
||||
Pos=435,26
|
||||
Size=845,388
|
||||
Pos=656,26
|
||||
Size=624,313
|
||||
Collapsed=0
|
||||
DockId=0x00000003,4
|
||||
|
||||
[Window][Resources]
|
||||
Pos=435,26
|
||||
Size=845,388
|
||||
Pos=656,26
|
||||
Size=624,313
|
||||
Collapsed=0
|
||||
DockId=0x00000003,1
|
||||
|
||||
|
|
@ -50,26 +50,26 @@ Size=150,42
|
|||
Collapsed=0
|
||||
|
||||
[Window][Variables]
|
||||
Pos=672,450
|
||||
Size=608,270
|
||||
Pos=537,450
|
||||
Size=743,270
|
||||
Collapsed=0
|
||||
DockId=0x00000005,0
|
||||
|
||||
[Window][CPU]
|
||||
Pos=435,26
|
||||
Size=845,388
|
||||
Pos=656,26
|
||||
Size=624,313
|
||||
Collapsed=0
|
||||
DockId=0x00000003,2
|
||||
|
||||
[Window][RAM view]
|
||||
Pos=435,26
|
||||
Size=845,388
|
||||
Pos=656,26
|
||||
Size=624,313
|
||||
Collapsed=0
|
||||
DockId=0x00000003,3
|
||||
|
||||
[Window][Properties]
|
||||
Pos=435,416
|
||||
Size=845,32
|
||||
Pos=656,341
|
||||
Size=624,107
|
||||
Collapsed=0
|
||||
DockId=0x00000006,0
|
||||
|
||||
|
|
@ -90,13 +90,13 @@ Collapsed=0
|
|||
|
||||
[Window][Module editor]
|
||||
Pos=60,26
|
||||
Size=373,422
|
||||
Size=594,422
|
||||
Collapsed=0
|
||||
DockId=0x00000001,0
|
||||
|
||||
[Window][Story editor]
|
||||
Pos=60,26
|
||||
Size=373,422
|
||||
Size=594,422
|
||||
Collapsed=0
|
||||
DockId=0x00000001,1
|
||||
|
||||
|
|
@ -105,6 +105,12 @@ Pos=490,260
|
|||
Size=687,422
|
||||
Collapsed=0
|
||||
|
||||
[Window][Error List]
|
||||
Pos=60,450
|
||||
Size=475,270
|
||||
Collapsed=0
|
||||
DockId=0x00000004,1
|
||||
|
||||
[Table][0x7728942D,5]
|
||||
RefScale=20
|
||||
Column 0 Width=44 Sort=0v
|
||||
|
|
@ -144,11 +150,11 @@ Column 0 Sort=0v
|
|||
[Docking][Data]
|
||||
DockSpace ID=0x08BD597D Window=0x1BBC0F80 Pos=60,26 Size=1220,694 Split=Y
|
||||
DockNode ID=0x00000007 Parent=0x08BD597D SizeRef=1220,422 Split=X
|
||||
DockNode ID=0x00000001 Parent=0x00000007 SizeRef=373,694 CentralNode=1 Selected=0x93ADCAAB
|
||||
DockNode ID=0x00000002 Parent=0x00000007 SizeRef=845,694 Split=Y Selected=0x52EB28B5
|
||||
DockNode ID=0x00000003 Parent=0x00000002 SizeRef=718,388 Selected=0x63869CAF
|
||||
DockNode ID=0x00000006 Parent=0x00000002 SizeRef=718,32 Selected=0x8C72BEA8
|
||||
DockNode ID=0x00000001 Parent=0x00000007 SizeRef=790,694 CentralNode=1 Selected=0x93ADCAAB
|
||||
DockNode ID=0x00000002 Parent=0x00000007 SizeRef=624,694 Split=Y Selected=0x52EB28B5
|
||||
DockNode ID=0x00000003 Parent=0x00000002 SizeRef=718,476 Selected=0x63869CAF
|
||||
DockNode ID=0x00000006 Parent=0x00000002 SizeRef=718,163 Selected=0x8C72BEA8
|
||||
DockNode ID=0x00000008 Parent=0x08BD597D SizeRef=1220,270 Split=X Selected=0xEA83D666
|
||||
DockNode ID=0x00000004 Parent=0x00000008 SizeRef=610,192 Selected=0xEA83D666
|
||||
DockNode ID=0x00000005 Parent=0x00000008 SizeRef=608,192 Selected=0x6DE9B20C
|
||||
DockNode ID=0x00000004 Parent=0x00000008 SizeRef=475,192 Selected=0xD246D6BE
|
||||
DockNode ID=0x00000005 Parent=0x00000008 SizeRef=743,192 Selected=0x6DE9B20C
|
||||
|
||||
|
|
|
|||
99
story-editor/src/docks/error_list_dock.cpp
Normal file
99
story-editor/src/docks/error_list_dock.cpp
Normal file
|
|
@ -0,0 +1,99 @@
|
|||
#include "error_list_dock.h"
|
||||
#include "imgui.h"
|
||||
|
||||
void ErrorListDock::Draw() {
|
||||
WindowBase::BeginDraw();
|
||||
|
||||
|
||||
ImGui::SetWindowSize(ImVec2(800, 200), ImGuiCond_FirstUseEver);
|
||||
|
||||
// Header avec compteur
|
||||
size_t errorCount = GetErrorCount();
|
||||
size_t warningCount = GetWarningCount();
|
||||
|
||||
if (errorCount > 0) {
|
||||
ImGui::PushStyleColor(ImGuiCol_Text, ImVec4(0.9f, 0.2f, 0.2f, 1.0f));
|
||||
ImGui::Text("%s %zu", ICON_FA_TIMES_CIRCLE, errorCount);
|
||||
ImGui::PopStyleColor();
|
||||
} else {
|
||||
ImGui::TextColored(ImVec4(0.5f, 0.5f, 0.5f, 1.0f), "%s 0", ICON_FA_TIMES_CIRCLE);
|
||||
}
|
||||
|
||||
ImGui::SameLine();
|
||||
if (warningCount > 0) {
|
||||
ImGui::PushStyleColor(ImGuiCol_Text, ImVec4(1.0f, 0.8f, 0.0f, 1.0f));
|
||||
ImGui::Text("%s %zu", ICON_FA_EXCLAMATION_TRIANGLE, warningCount);
|
||||
ImGui::PopStyleColor();
|
||||
} else {
|
||||
ImGui::TextColored(ImVec4(0.5f, 0.5f, 0.5f, 1.0f), "%s 0", ICON_FA_EXCLAMATION_TRIANGLE);
|
||||
}
|
||||
|
||||
ImGui::SameLine();
|
||||
ImGui::Spacing();
|
||||
ImGui::SameLine();
|
||||
|
||||
if (ImGui::Button(ICON_FA_TRASH " Clear")) {
|
||||
Clear();
|
||||
}
|
||||
|
||||
ImGui::Separator();
|
||||
|
||||
// AJOUT du BeginChild pour la zone scrollable
|
||||
ImGui::BeginChild("ErrorListContent", ImVec2(0, 0), false, ImGuiWindowFlags_AlwaysVerticalScrollbar);
|
||||
|
||||
// Afficher un message si pas d'erreurs
|
||||
if (m_errors.empty()) {
|
||||
ImGui::TextColored(ImVec4(0.3f, 0.8f, 0.3f, 1.0f),
|
||||
"%s No errors or warnings", ICON_FA_CHECK_CIRCLE);
|
||||
} else {
|
||||
// Table des erreurs
|
||||
if (ImGui::BeginTable("ErrorTable", 3,
|
||||
ImGuiTableFlags_Borders | ImGuiTableFlags_RowBg |
|
||||
ImGuiTableFlags_Resizable | ImGuiTableFlags_ScrollY))
|
||||
{
|
||||
ImGui::TableSetupColumn("Type", ImGuiTableColumnFlags_WidthFixed, 80);
|
||||
ImGui::TableSetupColumn("Message", ImGuiTableColumnFlags_WidthStretch);
|
||||
ImGui::TableSetupColumn("Node", ImGuiTableColumnFlags_WidthFixed, 80);
|
||||
ImGui::TableHeadersRow();
|
||||
|
||||
for (size_t i = 0; i < m_errors.size(); ++i) {
|
||||
const auto& error = m_errors[i];
|
||||
|
||||
ImGui::TableNextRow();
|
||||
|
||||
// Type column
|
||||
ImGui::TableSetColumnIndex(0);
|
||||
ImGui::PushStyleColor(ImGuiCol_Text, error.GetTypeColor());
|
||||
ImGui::Text("%s %s", error.GetTypeIcon().c_str(),
|
||||
error.type == CompilationError::ERROR ? "Error" :
|
||||
error.type == CompilationError::WARNING ? "Warning" : "Info");
|
||||
ImGui::PopStyleColor();
|
||||
|
||||
// Message column
|
||||
ImGui::TableSetColumnIndex(1);
|
||||
ImGui::TextWrapped("%s", error.message.c_str());
|
||||
|
||||
// Node column (clickable to navigate)
|
||||
ImGui::TableSetColumnIndex(2);
|
||||
if (!error.nodeId.empty()) {
|
||||
if (ImGui::SmallButton(("Go##" + std::to_string(i)).c_str())) {
|
||||
// TODO: Emit event to navigate to node
|
||||
}
|
||||
ImGui::SameLine();
|
||||
ImGui::TextDisabled("?");
|
||||
if (ImGui::IsItemHovered()) {
|
||||
ImGui::SetTooltip("Node: %s", error.nodeId.c_str());
|
||||
}
|
||||
} else {
|
||||
ImGui::TextDisabled("-");
|
||||
}
|
||||
}
|
||||
|
||||
ImGui::EndTable();
|
||||
}
|
||||
}
|
||||
|
||||
ImGui::EndChild();
|
||||
|
||||
WindowBase::EndDraw();
|
||||
}
|
||||
75
story-editor/src/docks/error_list_dock.h
Normal file
75
story-editor/src/docks/error_list_dock.h
Normal file
|
|
@ -0,0 +1,75 @@
|
|||
#pragma once
|
||||
|
||||
#include "window_base.h"
|
||||
#include "IconsFontAwesome5_c.h"
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include <algorithm>
|
||||
|
||||
struct CompilationError {
|
||||
enum Type {
|
||||
ERROR,
|
||||
WARNING,
|
||||
INFO
|
||||
};
|
||||
|
||||
Type type;
|
||||
std::string message;
|
||||
std::string nodeId; // UUID du nœud concerné
|
||||
int line;
|
||||
|
||||
std::string GetTypeIcon() const {
|
||||
switch(type) {
|
||||
case ERROR: return ICON_FA_TIMES_CIRCLE;
|
||||
case WARNING: return ICON_FA_EXCLAMATION_TRIANGLE;
|
||||
case INFO: return ICON_FA_INFO_CIRCLE;
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
ImVec4 GetTypeColor() const {
|
||||
switch(type) {
|
||||
case ERROR: return ImVec4(0.9f, 0.2f, 0.2f, 1.0f);
|
||||
case WARNING: return ImVec4(1.0f, 0.8f, 0.0f, 1.0f);
|
||||
case INFO: return ImVec4(0.3f, 0.7f, 1.0f, 1.0f);
|
||||
}
|
||||
return ImVec4(1.0f, 1.0f, 1.0f, 1.0f);
|
||||
}
|
||||
};
|
||||
|
||||
class ErrorListDock : public WindowBase {
|
||||
public:
|
||||
ErrorListDock() : WindowBase("Error List") {}
|
||||
|
||||
void Draw() override;
|
||||
|
||||
void Clear() { m_errors.clear(); }
|
||||
void AddError(const CompilationError& error) { m_errors.push_back(error); }
|
||||
void AddError(const std::string& message, const std::string& nodeId = "", int line = 0) {
|
||||
m_errors.push_back({CompilationError::ERROR, message, nodeId, line});
|
||||
}
|
||||
void AddWarning(const std::string& message, const std::string& nodeId = "", int line = 0) {
|
||||
m_errors.push_back({CompilationError::WARNING, message, nodeId, line});
|
||||
}
|
||||
void AddInfo(const std::string& message, const std::string& nodeId = "", int line = 0) {
|
||||
m_errors.push_back({CompilationError::INFO, message, nodeId, line});
|
||||
}
|
||||
|
||||
bool HasErrors() const {
|
||||
return std::any_of(m_errors.begin(), m_errors.end(),
|
||||
[](const auto& e) { return e.type == CompilationError::ERROR; });
|
||||
}
|
||||
|
||||
size_t GetErrorCount() const {
|
||||
return std::count_if(m_errors.begin(), m_errors.end(),
|
||||
[](const auto& e) { return e.type == CompilationError::ERROR; });
|
||||
}
|
||||
|
||||
size_t GetWarningCount() const {
|
||||
return std::count_if(m_errors.begin(), m_errors.end(),
|
||||
[](const auto& e) { return e.type == CompilationError::WARNING; });
|
||||
}
|
||||
|
||||
private:
|
||||
std::vector<CompilationError> m_errors;
|
||||
};
|
||||
|
|
@ -664,16 +664,16 @@ void Gui::ApplyTheme()
|
|||
colors[ImGuiCol_ResizeGripActive] = ImVec4(0.13f, 0.75f, 1.00f, 0.80f);
|
||||
|
||||
// ===== AMÉLIORATION DES ONGLETS =====
|
||||
// Onglet inactif (non sélectionné)
|
||||
colors[ImGuiCol_Tab] = ImVec4(0.15f, 0.15f, 0.15f, 1.00f);
|
||||
// Onglet inactif (non sélectionné) - TRÈS FONCÉ
|
||||
colors[ImGuiCol_Tab] = ImVec4(0.08f, 0.08f, 0.08f, 1.00f);
|
||||
// Onglet survolé
|
||||
colors[ImGuiCol_TabHovered] = ImVec4(0.25f, 0.60f, 0.80f, 1.00f);
|
||||
// Onglet actif (sélectionné) - couleur vive et contrastée
|
||||
// Onglet actif (sélectionné dans fenêtre focusée) - BLEU VIF
|
||||
colors[ImGuiCol_TabActive] = ImVec4(0.20f, 0.65f, 0.85f, 1.00f);
|
||||
// Onglet inactif dans une fenêtre non-focusée
|
||||
colors[ImGuiCol_TabUnfocused] = ImVec4(0.12f, 0.12f, 0.12f, 1.00f);
|
||||
// Onglet actif dans une fenêtre non-focusée
|
||||
colors[ImGuiCol_TabUnfocusedActive] = ImVec4(0.18f, 0.45f, 0.60f, 1.00f);
|
||||
// Onglet inactif dans une fenêtre non-focusée - TRÈS FONCÉ
|
||||
colors[ImGuiCol_TabUnfocused] = ImVec4(0.06f, 0.06f, 0.06f, 1.00f);
|
||||
// Onglet actif dans une fenêtre non-focusée - BEAUCOUP PLUS FONCÉ
|
||||
colors[ImGuiCol_TabUnfocusedActive] = ImVec4(0.10f, 0.10f, 0.12f, 1.00f);
|
||||
|
||||
colors[ImGuiCol_PlotLines] = ImVec4(0.61f, 0.61f, 0.61f, 1.00f);
|
||||
colors[ImGuiCol_PlotLinesHovered] = ImVec4(1.00f, 0.43f, 0.35f, 1.00f);
|
||||
|
|
@ -701,8 +701,8 @@ void Gui::ApplyTheme()
|
|||
style.PopupRounding = 2.0f;
|
||||
style.ScrollbarRounding = 12.0f;
|
||||
style.ScrollbarSize = 13.0f;
|
||||
style.TabBorderSize = 0.0f; // Pas de bordure autour des onglets
|
||||
style.TabRounding = 4.0f; // Coins arrondis pour les onglets
|
||||
style.TabBorderSize = 0.0f;
|
||||
style.TabRounding = 4.0f;
|
||||
style.WindowRounding = 4.0f;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -12,7 +12,8 @@
|
|||
enum ToastType {
|
||||
Success,
|
||||
Warning,
|
||||
Error
|
||||
Error,
|
||||
Info
|
||||
};
|
||||
|
||||
struct Toast {
|
||||
|
|
@ -26,7 +27,7 @@ struct Toast {
|
|||
class ImGuiToastNotifier {
|
||||
private:
|
||||
std::vector<Toast> toasts;
|
||||
const float TOAST_WIDTH = 300.0f;
|
||||
const float TOAST_WIDTH = 350.0f;
|
||||
const float TOAST_PADDING = 10.0f;
|
||||
|
||||
public:
|
||||
|
|
@ -34,12 +35,43 @@ public:
|
|||
toasts.push_back({title, text, type, std::chrono::steady_clock::now(), duration});
|
||||
}
|
||||
|
||||
// Helper methods pour les cas communs
|
||||
void success(const std::string& message) {
|
||||
addToast("Success", message, ToastType::Success, 3.0f);
|
||||
}
|
||||
|
||||
void error(const std::string& message, float duration = 5.0f) {
|
||||
addToast("Error", message, ToastType::Error, duration);
|
||||
}
|
||||
|
||||
void warning(const std::string& message) {
|
||||
addToast("Warning", message, ToastType::Warning, 4.0f);
|
||||
}
|
||||
|
||||
void info(const std::string& message) {
|
||||
addToast("Info", message, ToastType::Info, 3.0f);
|
||||
}
|
||||
|
||||
// Pour les erreurs de compilation
|
||||
void compilationFailed(size_t errorCount, size_t warningCount = 0) {
|
||||
std::string msg = std::to_string(errorCount) + " error(s) found";
|
||||
if (warningCount > 0) {
|
||||
msg += ", " + std::to_string(warningCount) + " warning(s)";
|
||||
}
|
||||
msg += ". Check Error List for details.";
|
||||
addToast("Compilation Failed", msg, ToastType::Error, 6.0f);
|
||||
}
|
||||
|
||||
void compilationSuccess(float duration = 2.5f) {
|
||||
addToast("Compilation Success", "Build completed successfully", ToastType::Success, duration);
|
||||
}
|
||||
|
||||
void render() {
|
||||
if (toasts.empty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Get the main viewport work area (excludes menu bar, status bar, etc.)
|
||||
// Get the main viewport work area
|
||||
ImGuiViewport* viewport = ImGui::GetMainViewport();
|
||||
ImVec2 work_pos = viewport->WorkPos;
|
||||
ImVec2 work_size = viewport->WorkSize;
|
||||
|
|
@ -54,7 +86,6 @@ public:
|
|||
ImGui::SetNextWindowSize(ImVec2(TOAST_WIDTH, 0), ImGuiCond_Always);
|
||||
ImGui::SetNextWindowBgAlpha(0.90f);
|
||||
|
||||
// Add NoNav to prevent interfering with other windows
|
||||
ImGuiWindowFlags window_flags =
|
||||
ImGuiWindowFlags_NoDecoration |
|
||||
ImGuiWindowFlags_NoMove |
|
||||
|
|
@ -103,6 +134,10 @@ public:
|
|||
color = ImVec4(0.94f, 0.31f, 0.31f, 1.0f);
|
||||
icon = ICON_FA_TIMES_CIRCLE;
|
||||
break;
|
||||
case Info:
|
||||
color = ImVec4(0.3f, 0.7f, 1.0f, 1.0f);
|
||||
icon = ICON_FA_INFO_CIRCLE;
|
||||
break;
|
||||
}
|
||||
|
||||
// Draw icon and title on the same line
|
||||
|
|
@ -111,13 +146,13 @@ public:
|
|||
ImGui::PopStyleColor();
|
||||
|
||||
ImGui::SameLine();
|
||||
ImGui::PushFont(ImGui::GetIO().Fonts->Fonts[0]); // Use default font for title
|
||||
ImGui::TextUnformatted(it->title.c_str());
|
||||
ImGui::PushFont(ImGui::GetIO().Fonts->Fonts[0]);
|
||||
ImGui::Text("%s", it->title.c_str());
|
||||
ImGui::PopFont();
|
||||
|
||||
// Draw message text with wrapping
|
||||
ImGui::PushTextWrapPos(ImGui::GetCursorPos().x + TOAST_WIDTH - 24.0f);
|
||||
ImGui::TextUnformatted(it->text.c_str());
|
||||
ImGui::TextWrapped("%s", it->text.c_str());
|
||||
ImGui::PopTextWrapPos();
|
||||
|
||||
ImGui::PopStyleVar(); // Alpha
|
||||
|
|
|
|||
|
|
@ -517,6 +517,7 @@ bool MainWindow::Loop()
|
|||
|
||||
// ------------ Draw all windows
|
||||
m_libraryWindow.Draw();
|
||||
m_errorListDock.Draw();
|
||||
|
||||
if (m_appController.IsLibraryManagerInitialized())
|
||||
{
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@
|
|||
#include "debugger_window.h"
|
||||
#include "emulator_dock.h"
|
||||
#include "resources_dock.h"
|
||||
#include "error_list_dock.h"
|
||||
#include "node_editor_window.h"
|
||||
#include "properties_window.h"
|
||||
#include "variables_window.h"
|
||||
|
|
@ -50,6 +51,7 @@ private:
|
|||
|
||||
Gui m_gui;
|
||||
EmulatorDock m_emulatorDock;
|
||||
ErrorListDock m_errorListDock;
|
||||
ConsoleWindow m_consoleWindow;
|
||||
DebuggerWindow m_debuggerWindow;
|
||||
CpuWindow m_cpuWindow;
|
||||
|
|
|
|||
|
|
@ -251,14 +251,20 @@ void NodeEditorWindow::SaveNodesToProject()
|
|||
return;
|
||||
}
|
||||
|
||||
// Clear current project structure
|
||||
m_story->Clear();
|
||||
|
||||
// Pour toutes les pages
|
||||
// IMPORTANT: Ne PAS appeler Clear() car cela efface aussi les variables!
|
||||
// Au lieu de cela, on efface seulement les pages
|
||||
for (const auto& page : m_pages)
|
||||
{
|
||||
// Create the page in the project
|
||||
auto currentPage = m_story->CreatePage(page->Uuid());
|
||||
// Récupérer la page correspondante dans le projet
|
||||
auto projectPage = m_story->GetPage(page->Uuid());
|
||||
|
||||
if (!projectPage) {
|
||||
// La page n'existe pas, la créer
|
||||
projectPage = m_story->CreatePage(page->Uuid());
|
||||
} else {
|
||||
// La page existe, vider son contenu (nodes et links)
|
||||
projectPage->Clear();
|
||||
}
|
||||
|
||||
// 1. Save all nodes with their updated positions
|
||||
for (auto &nodeEntry : page->mINF.getNodes())
|
||||
|
|
@ -280,7 +286,7 @@ void NodeEditorWindow::SaveNodesToProject()
|
|||
baseNode->SetPosition(nodePos.x, nodePos.y);
|
||||
|
||||
// Add node to project
|
||||
m_story->AddNode(currentPage->Uuid(), baseNode);
|
||||
m_story->AddNode(projectPage->Uuid(), baseNode);
|
||||
|
||||
std::cout << "Saved node: " << baseNode->GetId()
|
||||
<< " at (" << nodePos.x << ", " << nodePos.y << ")" << std::endl;
|
||||
|
|
@ -369,7 +375,7 @@ void NodeEditorWindow::SaveNodesToProject()
|
|||
connection->inPortIndex = rightPinIndex;
|
||||
|
||||
// Add connection to project
|
||||
m_story->AddConnection(currentPage->Uuid(), connection);
|
||||
m_story->AddConnection(projectPage->Uuid(), connection);
|
||||
|
||||
std::cout << "Saved connection: " << connection->outNodeId
|
||||
<< "[" << connection->outPortIndex << "] -> "
|
||||
|
|
@ -378,7 +384,7 @@ void NodeEditorWindow::SaveNodesToProject()
|
|||
}
|
||||
}
|
||||
|
||||
std::cout << "SaveNodesToProject completed successfully" << std::endl;
|
||||
std::cout << "SaveNodesToProject completed successfully (variables preserved)" << std::endl;
|
||||
}
|
||||
|
||||
void NodeEditorWindow::OpenFunction(const std::string &uuid, const std::string &name)
|
||||
|
|
|
|||
|
|
@ -1,4 +1,3 @@
|
|||
|
||||
#include <sstream>
|
||||
#include "print_node_widget.h"
|
||||
|
||||
|
|
@ -13,40 +12,55 @@ PrintNodeWidget::PrintNodeWidget(IStoryManager &manager, std::shared_ptr<BaseNod
|
|||
, m_manager(manager)
|
||||
{
|
||||
m_printNode = std::dynamic_pointer_cast<PrintNode>(node);
|
||||
// Create defaut one input and one output
|
||||
// AddInputs(2);
|
||||
// SetInputPinName(0, ">");
|
||||
// SetInputPinName(1, "Argument 1");
|
||||
// AddOutputs(1);
|
||||
// SetOutPinName(0, ">");
|
||||
SetTitle("Print");
|
||||
}
|
||||
|
||||
void PrintNodeWidget::Initialize()
|
||||
{
|
||||
BaseNodeWidget::Initialize();
|
||||
|
||||
// Copy current text to buffer
|
||||
auto text = m_printNode->GetText();
|
||||
if (text.size() < MAX_PRINT_SIZE) {
|
||||
text.copy(m_buffer, text.size());
|
||||
m_buffer[text.size()] = '\0';
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void PrintNodeWidget::DrawProperties(std::shared_ptr<IStoryProject> story)
|
||||
{
|
||||
ImGui::AlignTextToFramePadding();
|
||||
ImGui::Text("Format string:");
|
||||
|
||||
ImGui::PushItemWidth(200.0f);
|
||||
|
||||
ImGui::PushItemWidth(100.0f);
|
||||
|
||||
auto t = m_printNode->GetText();
|
||||
t.copy(m_buffer, sizeof(m_buffer) - 1);
|
||||
|
||||
bool edited = ImGui::InputText("##edit", m_buffer, sizeof(m_buffer), ImGuiInputTextFlags_EnterReturnsTrue);
|
||||
|
||||
// if (edited)
|
||||
{
|
||||
// Edit the format string
|
||||
if (ImGui::InputText("##format", m_buffer, sizeof(m_buffer))) {
|
||||
m_printNode->SetText(m_buffer);
|
||||
}
|
||||
|
||||
ImGui::PopItemWidth();
|
||||
|
||||
// Show help text
|
||||
ImGui::TextDisabled("Use {0}, {1}, {2}, {3} for arguments");
|
||||
|
||||
// Display current text
|
||||
ImGui::Separator();
|
||||
ImGui::Text("Preview: %s", m_printNode->GetText().c_str());
|
||||
}
|
||||
|
||||
void PrintNodeWidget::Draw()
|
||||
{
|
||||
|
||||
|
||||
}
|
||||
|
||||
// Display format string in the node body
|
||||
std::string displayText = m_printNode->GetText();
|
||||
if (displayText.empty()) {
|
||||
displayText = "<empty>";
|
||||
}
|
||||
|
||||
// Truncate if too long
|
||||
if (displayText.length() > 30) {
|
||||
displayText = displayText.substr(0, 27) + "...";
|
||||
}
|
||||
|
||||
ImGui::TextUnformatted(displayText.c_str());
|
||||
}
|
||||
|
|
@ -10,17 +10,15 @@
|
|||
#include "i_story_project.h"
|
||||
#include "gui.h"
|
||||
#include "print_node.h"
|
||||
#include "media_node.h"
|
||||
|
||||
class PrintNodeWidget : public BaseNodeWidget
|
||||
{
|
||||
public:
|
||||
|
||||
static const int MAX_PRINT_SIZE = 128;
|
||||
static const int MAX_PRINT_SIZE = 256;
|
||||
|
||||
PrintNodeWidget(IStoryManager &manager, std::shared_ptr<BaseNode> node);
|
||||
|
||||
void Draw() override;
|
||||
|
||||
virtual void DrawProperties(std::shared_ptr<IStoryProject> story) override;
|
||||
virtual void Initialize() override;
|
||||
|
||||
|
|
@ -29,4 +27,4 @@ private:
|
|||
std::shared_ptr<PrintNode> m_printNode;
|
||||
|
||||
static char m_buffer[MAX_PRINT_SIZE];
|
||||
};
|
||||
};
|
||||
|
|
@ -1,4 +1,3 @@
|
|||
|
||||
#include <sstream>
|
||||
#include "variable_node_widget.h"
|
||||
|
||||
|
|
@ -17,17 +16,16 @@ VariableNodeWidget::VariableNodeWidget(IStoryManager &manager, std::shared_ptr<B
|
|||
void VariableNodeWidget::Initialize()
|
||||
{
|
||||
BaseNodeWidget::Initialize();
|
||||
|
||||
m_selectedVariableUuid = m_variableNode->GetVariableUuid();
|
||||
}
|
||||
|
||||
|
||||
void VariableNodeWidget::DrawProperties(std::shared_ptr<IStoryProject> story)
|
||||
{
|
||||
// Initialize variable name from UUID on first call
|
||||
if (!m_isInitialized)
|
||||
{
|
||||
m_isInitialized = true;
|
||||
story->ScanVariable([this] (std::shared_ptr<Variable> var) {
|
||||
story->ScanVariable([this](std::shared_ptr<Variable> var) {
|
||||
if (var->GetUuid() == m_selectedVariableUuid)
|
||||
{
|
||||
m_selectedVariableName = var->GetVariableName();
|
||||
|
|
@ -36,39 +34,51 @@ void VariableNodeWidget::DrawProperties(std::shared_ptr<IStoryProject> story)
|
|||
}
|
||||
|
||||
ImGui::AlignTextToFramePadding();
|
||||
ImGui::Text("Variable:");
|
||||
|
||||
static ImGuiComboFlags flags = 0;
|
||||
|
||||
ImGui::SetNextItemOpen(true, ImGuiCond_Once);
|
||||
|
||||
if (ImGui::BeginCombo("Variables list", m_selectedVariableName.c_str(), flags))
|
||||
if (ImGui::BeginCombo("##variables", m_selectedVariableName.c_str(), flags))
|
||||
{
|
||||
int i = 0;
|
||||
story->ScanVariable([&i, this] (std::shared_ptr<Variable> var) {
|
||||
|
||||
// ImGui::PushID(static_cast<int>(i)); // Assure l'unicité des widgets
|
||||
|
||||
story->ScanVariable([&i, this](std::shared_ptr<Variable> var) {
|
||||
const bool is_selected = (m_selectedIndex == i);
|
||||
std::string l = var->GetVariableName();
|
||||
if (ImGui::Selectable(l.c_str(), is_selected))
|
||||
std::string label = var->GetVariableName();
|
||||
|
||||
if (ImGui::Selectable(label.c_str(), is_selected))
|
||||
{
|
||||
m_selectedIndex = i;
|
||||
m_selectedVariableName = l;
|
||||
m_selectedVariableName = label;
|
||||
m_variableNode->SetVariableUuid(var->GetUuid());
|
||||
m_variableNode->SetVariable(var);
|
||||
SetTitle(label);
|
||||
}
|
||||
|
||||
// Set the initial focus when opening the combo (scrolling + keyboard navigation focus)
|
||||
if (is_selected)
|
||||
// Set the initial focus when opening the combo
|
||||
if (is_selected) {
|
||||
ImGui::SetItemDefaultFocus();
|
||||
}
|
||||
|
||||
i++;
|
||||
});
|
||||
ImGui::EndCombo();
|
||||
}
|
||||
|
||||
|
||||
// Show variable details if selected
|
||||
if (!m_selectedVariableUuid.empty()) {
|
||||
ImGui::Separator();
|
||||
story->ScanVariable([this](std::shared_ptr<Variable> var) {
|
||||
if (var->GetUuid() == m_selectedVariableUuid) {
|
||||
ImGui::Text("Type: %s", Variable::ValueTypeToString(var->GetValueType()).c_str());
|
||||
ImGui::Text("Value: %s", var->GetValueAsString().c_str());
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
void VariableNodeWidget::Draw()
|
||||
{
|
||||
// Display variable name in the node
|
||||
ImGui::TextUnformatted(m_selectedVariableName.c_str());
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -10,7 +10,6 @@
|
|||
#include "i_story_project.h"
|
||||
#include "gui.h"
|
||||
#include "variable_node.h"
|
||||
#include "media_node.h"
|
||||
|
||||
class VariableNodeWidget : public BaseNodeWidget
|
||||
{
|
||||
|
|
@ -18,7 +17,6 @@ public:
|
|||
VariableNodeWidget(IStoryManager &manager, std::shared_ptr<BaseNode> node);
|
||||
|
||||
void Draw() override;
|
||||
|
||||
virtual void DrawProperties(std::shared_ptr<IStoryProject> story) override;
|
||||
virtual void Initialize() override;
|
||||
|
||||
|
|
@ -28,5 +26,5 @@ private:
|
|||
std::shared_ptr<VariableNode> m_variableNode;
|
||||
int m_selectedIndex{-1};
|
||||
std::string m_selectedVariableUuid;
|
||||
std::string m_selectedVariableName;
|
||||
};
|
||||
std::string m_selectedVariableName{"<none>"};
|
||||
};
|
||||
Loading…
Reference in a new issue