missing files

This commit is contained in:
anthony@rabine.fr 2025-10-02 17:48:25 +02:00
parent 6d544f5879
commit 0be3ff2203
10 changed files with 134 additions and 358 deletions

View file

@ -143,7 +143,6 @@ set(SRCS
# src/node_editor/media_node_widget.cpp # src/node_editor/media_node_widget.cpp
src/node_editor/base_node_widget.cpp src/node_editor/base_node_widget.cpp
src/node_editor/node_editor_window.cpp src/node_editor/node_editor_window.cpp
src/node_editor/call_function_node_widget.cpp
src/node_editor/module_node_widget.cpp src/node_editor/module_node_widget.cpp
src/node_editor/variable_node_widget.cpp src/node_editor/variable_node_widget.cpp
src/node_editor/operator_node_widget.cpp src/node_editor/operator_node_widget.cpp
@ -185,7 +184,6 @@ set(SRCS
../core/story-manager/src/nodes/compare_node.cpp ../core/story-manager/src/nodes/compare_node.cpp
../core/story-manager/src/nodes/branch_node.cpp ../core/story-manager/src/nodes/branch_node.cpp
../core/story-manager/src/nodes/variable_node.cpp ../core/story-manager/src/nodes/variable_node.cpp
../core/story-manager/src/nodes/call_function_node.cpp
../core/story-manager/src/nodes/module_node.cpp ../core/story-manager/src/nodes/module_node.cpp
../core/story-manager/src/nodes/print_node.cpp ../core/story-manager/src/nodes/print_node.cpp
../core/story-manager/src/nodes/syscall_node.cpp ../core/story-manager/src/nodes/syscall_node.cpp

View file

@ -34,7 +34,7 @@
#include "print_node_widget.h" #include "print_node_widget.h"
#include "syscall_node_widget.h" #include "syscall_node_widget.h"
#include "function_entry_widget.h" #include "function_entry_widget.h"
#include "function_exit_widget.h"
MainWindow::MainWindow(ILogger& logger, EventBus& eventBus, AppController& appController) MainWindow::MainWindow(ILogger& logger, EventBus& eventBus, AppController& appController)
: m_logger(logger) : m_logger(logger)
@ -74,7 +74,6 @@ MainWindow::MainWindow(ILogger& logger, EventBus& eventBus, AppController& appCo
m_widgetFactory.registerNode<PrintNodeWidget>(PrintNodeUuid); m_widgetFactory.registerNode<PrintNodeWidget>(PrintNodeUuid);
m_widgetFactory.registerNode<SyscallNodeWidget>(SyscallNodeUuid); m_widgetFactory.registerNode<SyscallNodeWidget>(SyscallNodeUuid);
m_widgetFactory.registerNode<FunctionEntryWidget>(FunctionEntryNodeUuid); m_widgetFactory.registerNode<FunctionEntryWidget>(FunctionEntryNodeUuid);
m_widgetFactory.registerNode<FunctionExitWidget>(FunctionExitNodeUuid);
m_eventBus.Subscribe<OpenProjectEvent>([this](const OpenProjectEvent &event) { m_eventBus.Subscribe<OpenProjectEvent>([this](const OpenProjectEvent &event) {
OpenProject(event.GetUuid()); OpenProject(event.GetUuid());

View file

@ -25,4 +25,68 @@ void BaseNodeWidget::Initialize()
} }
void BaseNodeWidget::DrawSocket(const Nw::Pin &pin)
{
ImDrawList* draw_list = ImGui::GetWindowDrawList();
// Taille du socket
float socket_size = 4.0f;
// Définir les 5 points du polygone (flèche pointant vers la droite pour Output)
// Pour Input, la flèche pointerait vers la gauche
ImVec2 p1, p2, p3, p4, p5;
if (pin.pinKind == Nw::PinKind::Output) {
// Flèche pointant vers la droite (→)
p1 = ImVec2(pin.pinPoint.x - socket_size * 1.5f, pin.pinPoint.y - socket_size);
p2 = ImVec2(pin.pinPoint.x - socket_size * 0.5f, pin.pinPoint.y - socket_size);
p3 = ImVec2(pin.pinPoint.x + socket_size * 0.5f, pin.pinPoint.y); // Pointe
p4 = ImVec2(pin.pinPoint.x - socket_size * 0.5f, pin.pinPoint.y + socket_size);
p5 = ImVec2(pin.pinPoint.x - socket_size * 1.5f, pin.pinPoint.y + socket_size);
} else {
// Flèche pointant vers la gauche (←)
p1 = ImVec2(pin.pinPoint.x + socket_size * 1.5f, pin.pinPoint.y - socket_size);
p2 = ImVec2(pin.pinPoint.x + socket_size * 0.5f, pin.pinPoint.y - socket_size);
p3 = ImVec2(pin.pinPoint.x - socket_size * 0.5f, pin.pinPoint.y); // Pointe
p4 = ImVec2(pin.pinPoint.x + socket_size * 0.5f, pin.pinPoint.y + socket_size);
p5 = ImVec2(pin.pinPoint.x + socket_size * 1.5f, pin.pinPoint.y + socket_size);
}
ImVec2 vertices[] = {p1, p2, p3, p4, p5};
// Rectangle pour la détection de hover
ImVec2 tl = pin.pinPoint - ImVec2(socket_size * 1.5f, socket_size);
ImVec2 br = pin.pinPoint + ImVec2(socket_size * 1.5f, socket_size);
bool hovered = ImGui::IsItemHovered() || ImGui::IsMouseHoveringRect(tl, br);
// Dessin du socket
if (pin.isConnected) {
// Rempli quand connecté
draw_list->AddConvexPolyFilled(vertices, IM_ARRAYSIZE(vertices),
pin.style.color);
} else {
// Contour seulement quand non connecté
if (hovered) {
draw_list->AddPolyline(vertices, IM_ARRAYSIZE(vertices),
pin.style.color,
ImDrawFlags_Closed,
pin.style.socket_hovered_radius); // Épaisseur au hover
} else {
draw_list->AddPolyline(vertices, IM_ARRAYSIZE(vertices),
pin.style.color,
ImDrawFlags_Closed,
pin.style.socket_thickness); // Épaisseur normale
}
}
// Optionnel : dessiner la décoration (fond hover) si nécessaire
if (hovered) {
draw_list->AddRectFilled(pin.pos - pin.style.padding,
pin.pos + pin.size + pin.style.padding,
pin.style.bg_hover_color,
pin.style.bg_radius);
}
}

View file

@ -96,7 +96,7 @@ public:
virtual void DrawProperties(std::shared_ptr<IStoryProject> story) = 0; virtual void DrawProperties(std::shared_ptr<IStoryProject> story) = 0;
virtual void DrawSocket(const Nw::Pin &pin) {} virtual void DrawSocket(const Nw::Pin &pin);
virtual bool HasSync() const { virtual bool HasSync() const {

View file

@ -1,38 +0,0 @@
#include <sstream>
#include "call_function_node_widget.h"
#include "IconsMaterialDesignIcons.h"
#include "story_project.h"
#include "uuid.h"
CallFunctionNodeWidget::CallFunctionNodeWidget(IStoryManager &manager, std::shared_ptr<BaseNode> node)
: BaseNodeWidget(manager, node)
, m_manager(manager)
{
m_functionUuid = Uuid().String();
}
void CallFunctionNodeWidget::Draw()
{
ImGui::TextUnformatted(m_functionName.c_str());
if (ImGui::Button("> Open function"))
{
m_manager.OpenFunction(m_functionUuid, m_functionName);
}
}
void CallFunctionNodeWidget::Initialize()
{
BaseNodeWidget::Initialize();
m_functionName = "Function";
}
void CallFunctionNodeWidget::DrawProperties(std::shared_ptr<IStoryProject> story)
{
}

View file

@ -1,9 +1,9 @@
// call_function_node_widget.h
#pragma once #pragma once
#include <vector> #include <vector>
#include <map> #include <map>
#include <mutex> #include <string>
#include <set>
#include "base_node_widget.h" #include "base_node_widget.h"
#include "i_story_manager.h" #include "i_story_manager.h"
@ -11,22 +11,74 @@
#include "call_function_node.h" #include "call_function_node.h"
#include "gui.h" #include "gui.h"
class CallFunctionNodeWidget : public BaseNodeWidget class CallFunctionNodeWidget : public BaseNodeWidget
{ {
public: public:
CallFunctionNodeWidget(IStoryManager &manager, std::shared_ptr<BaseNode> node); CallFunctionNodeWidget(IStoryManager &manager, std::shared_ptr<BaseNode> node)
: BaseNodeWidget(manager, node)
, m_manager(manager)
{
m_callFunctionNode = std::dynamic_pointer_cast<CallFunctionNode>(node);
SetTitle("Call Function");
}
void Draw() override; void Initialize() override {
BaseNodeWidget::Initialize();
m_functionName = m_callFunctionNode->GetFunctionName();
m_functionUuid = m_callFunctionNode->GetFunctionUuid();
}
virtual void DrawProperties(std::shared_ptr<IStoryProject> story) override; void DrawProperties(std::shared_ptr<IStoryProject> story) override {
virtual void Initialize() override; ImGui::AlignTextToFramePadding();
// Liste déroulante des fonctions disponibles
if (ImGui::BeginCombo("Function", m_functionName.empty() ? "<Select function>" : m_functionName.c_str())) {
// Récupérer la liste des fonctions du projet
auto functions = story->GetFunctionsList(); // À implémenter dans IStoryProject
for (size_t i = 0; i < functions.size(); ++i) {
const bool is_selected = (m_functionUuid == functions[i].uuid);
if (ImGui::Selectable(functions[i].name.c_str(), is_selected)) {
m_functionUuid = functions[i].uuid;
m_functionName = functions[i].name;
m_callFunctionNode->SetFunction(m_functionUuid, m_functionName);
}
if (is_selected)
ImGui::SetItemDefaultFocus();
}
ImGui::EndCombo();
}
// Bouton pour ouvrir la fonction dans l'éditeur
ImGui::Spacing();
// Désactiver le bouton si aucune fonction n'est sélectionnée
if (m_functionUuid.empty()) {
ImGui::BeginDisabled();
}
if (ImGui::Button("> Open function")) {
m_manager.OpenFunction(m_functionUuid, m_functionName);
}
if (m_functionUuid.empty()) {
ImGui::EndDisabled();
}
}
void Draw() override {
// Afficher le nom de la fonction dans le noeud
ImGui::TextUnformatted(m_functionName.empty()
? "<No function>"
: m_functionName.c_str());
}
private: private:
IStoryManager &m_manager; IStoryManager &m_manager;
std::shared_ptr<CallFunctionNode> m_callFunctionNode; std::shared_ptr<CallFunctionNode> m_callFunctionNode;
std::string m_functionName; std::string m_functionName;
std::string m_functionUuid; std::string m_functionUuid;
}; };

View file

@ -11,109 +11,6 @@
#include "function_entry_node.h" #include "function_entry_node.h"
#include "gui.h" #include "gui.h"
void DrawBlueprintSyncSocket(ImDrawList* draw_list, const ImVec2& center, float size, ImU32 color, bool filled = true) {
const float half_size = size * 0.5f;
const float triangle_size = size * 0.6f; // Triangle légèrement plus petit que le carré
// Coordonnées du carré (partie gauche)
ImVec2 square_min = ImVec2(center.x - half_size, center.y - half_size);
ImVec2 square_max = ImVec2(center.x, center.y + half_size);
// Coordonnées du triangle (partie droite, pointant vers la droite)
ImVec2 triangle_p1 = ImVec2(center.x, center.y - triangle_size * 0.5f); // Point haut
ImVec2 triangle_p2 = ImVec2(center.x, center.y + triangle_size * 0.5f); // Point bas
ImVec2 triangle_p3 = ImVec2(center.x + triangle_size * 0.7f, center.y); // Point de la pointe
if (filled) {
// Dessiner le carré rempli
draw_list->AddRectFilled(square_min, square_max, color);
// Dessiner le triangle rempli
draw_list->AddTriangleFilled(triangle_p1, triangle_p2, triangle_p3, color);
} else {
// Dessiner les contours
const float thickness = 2.0f;
// Contour du carré
draw_list->AddRect(square_min, square_max, color, 0.0f, 0, thickness);
// Contour du triangle
draw_list->AddTriangle(triangle_p1, triangle_p2, triangle_p3, color, thickness);
}
}
// Version avec dégradé pour un effet plus moderne
void DrawBlueprintSyncSocketGradient(ImDrawList* draw_list, const ImVec2& center, float size, ImU32 color_start, ImU32 color_end) {
const float half_size = size * 0.5f;
const float triangle_size = size * 0.6f;
// Coordonnées du carré
ImVec2 square_min = ImVec2(center.x - half_size, center.y - half_size);
ImVec2 square_max = ImVec2(center.x, center.y + half_size);
// Coordonnées du triangle
ImVec2 triangle_p1 = ImVec2(center.x, center.y - triangle_size * 0.5f);
ImVec2 triangle_p2 = ImVec2(center.x, center.y + triangle_size * 0.5f);
ImVec2 triangle_p3 = ImVec2(center.x + triangle_size * 0.7f, center.y);
// Carré avec dégradé horizontal
draw_list->AddRectFilledMultiColor(
square_min, square_max,
color_start, color_end,
color_end, color_start
);
// Triangle uni (couleur de fin du dégradé)
draw_list->AddTriangleFilled(triangle_p1, triangle_p2, triangle_p3, color_end);
}
// Variante avec animation de pulsation pour indiquer l'activité
void DrawBlueprintSyncSocketAnimated(ImDrawList* draw_list, const ImVec2& center, float size, ImU32 color, float time) {
// Effet de pulsation basé sur le temps
float pulse = 0.8f + 0.2f * sinf(time * 3.0f); // Oscille entre 0.8 et 1.0
float animated_size = size * pulse;
// Socket principal
DrawBlueprintSyncSocket(draw_list, center, animated_size, color, true);
// Halo subtil autour
ImU32 halo_color = ImGui::ColorConvertFloat4ToU32(ImVec4(
((color >> IM_COL32_R_SHIFT) & 0xFF) / 255.0f,
((color >> IM_COL32_G_SHIFT) & 0xFF) / 255.0f,
((color >> IM_COL32_B_SHIFT) & 0xFF) / 255.0f,
0.3f * (pulse - 0.8f) * 5.0f // Alpha qui varie avec la pulsation
));
DrawBlueprintSyncSocket(draw_list, center, size * 1.2f, halo_color, false);
}
// Utilisation dans ImNodeFlow
void DrawSyncSocketInNode(ImDrawList* draw_list, const ImVec2& socket_pos, bool is_connected, bool is_hovered) {
const float socket_size = 16.0f;
// Couleurs selon l'état
ImU32 base_color = IM_COL32(100, 150, 255, 255); // Bleu par défaut
ImU32 connected_color = IM_COL32(50, 255, 100, 255); // Vert si connecté
ImU32 hover_color = IM_COL32(255, 200, 50, 255); // Orange au survol
ImU32 final_color = base_color;
if (is_connected) final_color = connected_color;
if (is_hovered) final_color = hover_color;
// Dessiner le socket
if (is_connected) {
// Version animée si connecté
float time = ImGui::GetTime();
DrawBlueprintSyncSocketAnimated(draw_list, socket_pos, socket_size, final_color, time);
} else {
// Version statique
DrawBlueprintSyncSocket(draw_list, socket_pos, socket_size, final_color, true);
}
}
class FunctionEntryWidget : public BaseNodeWidget class FunctionEntryWidget : public BaseNodeWidget
{ {
public: public:
@ -129,141 +26,6 @@ public:
ImGui::SetNextItemWidth(100.f); ImGui::SetNextItemWidth(100.f);
} }
void DrawSocket(const Nw::Pin &pin) override
{
ImDrawList* draw_list = ImGui::GetWindowDrawList();
// Taille du socket
float socket_size = 4.0f;
// Définir les 5 points du polygone (flèche pointant vers la droite pour Output)
// Pour Input, la flèche pointerait vers la gauche
ImVec2 p1, p2, p3, p4, p5;
if (pin.pinKind == Nw::PinKind::Output) {
// Flèche pointant vers la droite (→)
p1 = ImVec2(pin.pinPoint.x - socket_size * 1.5f, pin.pinPoint.y - socket_size);
p2 = ImVec2(pin.pinPoint.x - socket_size * 0.5f, pin.pinPoint.y - socket_size);
p3 = ImVec2(pin.pinPoint.x + socket_size * 0.5f, pin.pinPoint.y); // Pointe
p4 = ImVec2(pin.pinPoint.x - socket_size * 0.5f, pin.pinPoint.y + socket_size);
p5 = ImVec2(pin.pinPoint.x - socket_size * 1.5f, pin.pinPoint.y + socket_size);
} else {
// Flèche pointant vers la gauche (←)
p1 = ImVec2(pin.pinPoint.x + socket_size * 1.5f, pin.pinPoint.y - socket_size);
p2 = ImVec2(pin.pinPoint.x + socket_size * 0.5f, pin.pinPoint.y - socket_size);
p3 = ImVec2(pin.pinPoint.x - socket_size * 0.5f, pin.pinPoint.y); // Pointe
p4 = ImVec2(pin.pinPoint.x + socket_size * 0.5f, pin.pinPoint.y + socket_size);
p5 = ImVec2(pin.pinPoint.x + socket_size * 1.5f, pin.pinPoint.y + socket_size);
}
ImVec2 vertices[] = {p1, p2, p3, p4, p5};
// Rectangle pour la détection de hover
ImVec2 tl = pin.pinPoint - ImVec2(socket_size * 1.5f, socket_size);
ImVec2 br = pin.pinPoint + ImVec2(socket_size * 1.5f, socket_size);
bool hovered = ImGui::IsItemHovered() || ImGui::IsMouseHoveringRect(tl, br);
// Dessin du socket
if (pin.isConnected) {
// Rempli quand connecté
draw_list->AddConvexPolyFilled(vertices, IM_ARRAYSIZE(vertices),
pin.style.color);
} else {
// Contour seulement quand non connecté
if (hovered) {
draw_list->AddPolyline(vertices, IM_ARRAYSIZE(vertices),
pin.style.color,
ImDrawFlags_Closed,
pin.style.socket_hovered_radius); // Épaisseur au hover
} else {
draw_list->AddPolyline(vertices, IM_ARRAYSIZE(vertices),
pin.style.color,
ImDrawFlags_Closed,
pin.style.socket_thickness); // Épaisseur normale
}
}
// Optionnel : dessiner la décoration (fond hover) si nécessaire
if (hovered) {
draw_list->AddRectFilled(pin.pos - pin.style.padding,
pin.pos + pin.size + pin.style.padding,
pin.style.bg_hover_color,
pin.style.bg_radius);
}
/*
// bonne position du socket
ImDrawList* draw_list = ImGui::GetWindowDrawList();
// 1. Dessiner le socket à pin.pinPoint (pas à pin.pos !)
if (pin.isConnected) {
draw_list->AddCircleFilled(pin.pinPoint,
pin.style.socket_connected_radius,
pin.style.color);
} else {
// Gérer le hover vous-même si nécessaire
ImVec2 tl = pin.pinPoint - ImVec2(pin.style.socket_radius, pin.style.socket_radius);
ImVec2 br = pin.pinPoint + ImVec2(pin.style.socket_radius, pin.style.socket_radius);
bool hovered = ImGui::IsMouseHoveringRect(tl, br);
draw_list->AddCircle(pin.pinPoint,
hovered ? pin.style.socket_hovered_radius
: pin.style.socket_radius,
pin.style.color,
pin.style.socket_shape,
pin.style.socket_thickness);
}
*/
/*
ImDrawList* draw_list = ImGui::GetWindowDrawList();
float socket_size = 4;
// pin.pos.x = pin.pos.x + 10;
ImVec2 w_pos = ImGui::GetCursorPos();
std::cout << "x = " << w_pos.x << ", y = " << w_pos.y << std::endl;;
// Définir les points du polygone pour le symbole de synchronisation
// C'est un polygone fermé à 5 points
ImVec2 p1(pin.pos.x - socket_size * 0.5f, pin.pos.y - socket_size);
ImVec2 p2(pin.pos.x + socket_size * 0.5f, pin.pos.y - socket_size);
ImVec2 p3(pin.pos.x + socket_size * 0.5f, pin.pos.y + socket_size);
ImVec2 p4(pin.pos.x - socket_size * 0.5f, pin.pos.y + socket_size);
ImVec2 p5(pin.pos.x + socket_size * 1.5f, pin.pos.y);
ImVec2 vertices[] = {p1, p2, p5, p3, p4}; // Ordre des sommets
// Pour la détection de survol (hover) on peut toujours utiliser le rectangle englobant
ImVec2 tl = pin.pos - ImVec2(socket_size * 1.5f, socket_size);
ImVec2 br = pin.pos + ImVec2(socket_size * 1.5f, socket_size);
if (pin.isConnected)
{
draw_list->AddConvexPolyFilled(vertices, IM_ARRAYSIZE(vertices), IM_COL32(255,255,255,255));
}
else
{
if (ImGui::IsItemHovered() || ImGui::IsMouseHoveringRect(tl, br))
{
draw_list->AddPolyline(vertices, IM_ARRAYSIZE(vertices),IM_COL32(255,255,255,255), ImDrawFlags_Closed, 2.0f);
}
else
{
draw_list->AddPolyline(vertices, IM_ARRAYSIZE(vertices), IM_COL32(255,255,255,255), ImDrawFlags_Closed, 1.3f);
}
}
*/
}
virtual bool HasSync() const override { virtual bool HasSync() const override {
return false; return false;
} }

View file

@ -1,42 +0,0 @@
#pragma once
#include <vector>
#include <map>
#include <mutex>
#include <set>
#include "base_node_widget.h"
#include "i_story_manager.h"
#include "i_story_project.h"
#include "function_exit_node.h"
#include "gui.h"
class FunctionExitWidget : public BaseNodeWidget
{
public:
FunctionExitWidget(IStoryManager &manager, std::shared_ptr<BaseNode> node)
: BaseNodeWidget(manager, node)
, m_manager(manager)
{
m_functionExitNode = std::dynamic_pointer_cast<FunctionExitNode>(node);
SetTitle("Function Exit");
}
void Draw() override {
ImGui::SetNextItemWidth(100.f);
}
virtual void DrawProperties(std::shared_ptr<IStoryProject> story) override {
}
virtual void Initialize() override {
}
private:
IStoryManager &m_manager;
std::shared_ptr<FunctionExitNode> m_functionExitNode;
};

View file

@ -11,24 +11,6 @@
#include "i_story_manager.h" #include "i_story_manager.h"
#include "ImNodeFlow.h" #include "ImNodeFlow.h"
class SimpleSum : public ImFlow::BaseNode {
public:
SimpleSum() {
setTitle("Simple sum");
setStyle(ImFlow::NodeStyle::green());
ImFlow::BaseNode::addIN<int>("In", 0, ImFlow::ConnectionFilter::SameType());
ImFlow::BaseNode::addOUT<int>("Out", nullptr)->behaviour([this]() { return getInVal<int>("In") + m_valB; });
}
void draw() override {
ImGui::SetNextItemWidth(100.f);
ImGui::InputInt("##ValB", &m_valB);
}
private:
int m_valB = 0;
};
// Generic delegate // Generic delegate
class NodeDelegate : public ImFlow::BaseNode { class NodeDelegate : public ImFlow::BaseNode {
@ -45,12 +27,6 @@ public:
setTitle(m_widget->GetTitle()); setTitle(m_widget->GetTitle());
setStyle(ImFlow::NodeStyle::green()); setStyle(ImFlow::NodeStyle::green());
// Add Sync input if it is an executable node
if (m_widget->HasSync())
{
ImFlow::BaseNode::addIN<int>(">", 0, ImFlow::ConnectionFilter::SameType());
}
// Add inputs // Add inputs
for (int i = 0; i < m_widget->Inputs(); ++i) { for (int i = 0; i < m_widget->Inputs(); ++i) {

View file

@ -75,6 +75,11 @@ void NodeEditorWindow::LoadPage(const std::string &uuid, const std::string &name
{ {
// New page // New page
page = std::make_shared<NodeEditorPage>(uuid, name); page = std::make_shared<NodeEditorPage>(uuid, name);
auto storyPage = m_story->GetPage(uuid);
if (!storyPage) {
storyPage = m_story->CreatePage(uuid);
}
storyPage->SetName(name);
} }
else else
{ {