Add all system calls as dedicated nodes
Some checks are pending
Build-StoryEditor / build_linux (push) Waiting to run
Build-StoryEditor / build_win32 (push) Waiting to run

This commit is contained in:
anthony@rabine.fr 2025-10-19 22:00:39 +02:00
parent 149a8b6276
commit 765f78fbc6
35 changed files with 789 additions and 248 deletions

View file

@ -43,7 +43,8 @@ public:
virtual void SetName(const std::string &name) = 0;
virtual void SetUuid(const std::string &uuid) = 0;
virtual void ScanVariable(const std::function<void(std::shared_ptr<Variable> element)>& operation) = 0;
// Callback can return false to break the loop
virtual void ScanVariable(const std::function<bool(std::shared_ptr<Variable> element)>& operation) = 0;
virtual void AddVariable() = 0;
virtual void DeleteVariable(int i) = 0;

View file

@ -1,18 +0,0 @@
#include "compare_node.h"
#include "story_project.h"
#include "connection.h"
#include "sys_lib.h"
CompareNode::CompareNode(const std::string &type)
: BaseNode(type, "Compare Node")
{
}
void CompareNode::Initialize()
{
}

View file

@ -1,19 +0,0 @@
#pragma once
#include <string>
#include "i_story_manager.h"
#include "base_node.h"
#include "i_script_node.h"
#include "i_story_project.h"
class CompareNode : public BaseNode
{
public:
CompareNode(const std::string &type);
virtual void Initialize() override;
private:
};

View file

@ -0,0 +1,35 @@
// core/story-manager/src/nodes/play_media_node.cpp
#include "play_media_node.h"
PlayMediaNode::PlayMediaNode(const std::string &type)
: BaseNode(type, "Play Media")
{
SetBehavior(BaseNode::BEHAVIOR_EXECUTION);
SetupExecutionPorts(true, 1, true); // IN 0 (exec), OUT 0 (exec)
// Ports data
AddInputPort(Port::Type::DATA_PORT, "Image");
AddInputPort(Port::Type::DATA_PORT, "Sound");
nlohmann::json j{
{"status_variable_uuid", m_statusVariableUuid}
};
SetInternalData(j);
}
void PlayMediaNode::Initialize()
{
nlohmann::json j = GetInternalData();
if (j.contains("status_variable_uuid")) {
m_statusVariableUuid = j["status_variable_uuid"].get<std::string>();
}
}
void PlayMediaNode::SetStatusVariable(const std::string& varUuid)
{
m_statusVariableUuid = varUuid;
nlohmann::json j = GetInternalData();
j["status_variable_uuid"] = m_statusVariableUuid;
SetInternalData(j);
}

View file

@ -0,0 +1,21 @@
// core/story-manager/src/nodes/play_media_node.h
#pragma once
#include <string>
#include "base_node.h"
#include "i_story_project.h"
class PlayMediaNode : public BaseNode
{
public:
PlayMediaNode(const std::string &type = "play-media-node");
void Initialize() override;
// Variable optionnelle pour le status de retour
std::string GetStatusVariableUuid() const { return m_statusVariableUuid; }
void SetStatusVariable(const std::string& varUuid);
private:
std::string m_statusVariableUuid; // Optionnel
};

View file

@ -0,0 +1,29 @@
// core/story-manager/src/nodes/send_signal_node.cpp
#include "send_signal_node.h"
SendSignalNode::SendSignalNode(const std::string &type)
: BaseNode(type, "Send Signal")
{
SetBehavior(BaseNode::BEHAVIOR_EXECUTION);
SetupExecutionPorts(true, 1, true); // IN 0, OUT 0
AddInputPort(Port::Type::DATA_PORT, "Signal ID");
nlohmann::json j{{"signal_id", m_signalId}};
SetInternalData(j);
}
void SendSignalNode::Initialize()
{
nlohmann::json j = GetInternalData();
if (j.contains("signal_id")) {
m_signalId = j["signal_id"].get<uint32_t>();
}
}
void SendSignalNode::SetSignalId(uint32_t id)
{
m_signalId = id;
nlohmann::json j{{"signal_id", m_signalId}};
SetInternalData(j);
}

View file

@ -0,0 +1,21 @@
// core/story-manager/src/nodes/send_signal_node.h
#pragma once
#include <string>
#include "base_node.h"
#include "i_story_project.h"
class SendSignalNode : public BaseNode
{
public:
SendSignalNode(const std::string &type = "send-signal-node");
void Initialize() override;
// ID du signal à envoyer
uint32_t GetSignalId() const { return m_signalId; }
void SetSignalId(uint32_t id);
private:
uint32_t m_signalId{0};
};

View file

@ -1,38 +0,0 @@
#include "syscall_node.h"
#include "story_project.h"
#include "connection.h"
#include "sys_lib.h"
SyscallNode::SyscallNode(const std::string &type)
: BaseNode(type, "Syscall Node")
{
nlohmann::json j{ {"syscall_number", m_syscallNumber} };
SetInternalData(j);
}
void SyscallNode::Initialize()
{
nlohmann::json j = GetInternalData();
m_syscallNumber = j["syscall_number"].get<int>();
}
int SyscallNode::GetArgumentsSize() const
{
int size = 0;
switch (m_syscallNumber)
{
case SYSCALL_PLAY_MEDIA:
size = 2;
break;
default:
break;
}
return size;
}

View file

@ -1,42 +0,0 @@
#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"
class SyscallNode : public BaseNode
{
public:
enum SysCallType : int {
SYSCALL_PLAY_MEDIA = 1,
SYSCALL_WAIT_EVENT = 2,
SYSCALL_SEND_SIGNAL = 3,
SYSCALL_PRINT = 4,
SYSCALL_WAIT_MILLISEC = 5
};
SyscallNode(const std::string &type = "syscall-node");
virtual void Initialize() override;
int GetSyscallNumber() const {
return m_syscallNumber;
}
void SetSyscallNumber(int syscallNumber) {
m_syscallNumber = syscallNumber;
SetInternalData({{"syscall_number", m_syscallNumber}});
}
int GetArgumentsSize() const;
private:
int m_syscallNumber{4};
};

View file

@ -0,0 +1,29 @@
// core/story-manager/src/nodes/wait_delay_node.cpp
#include "wait_delay_node.h"
WaitDelayNode::WaitDelayNode(const std::string &type)
: BaseNode(type, "Wait Delay")
{
SetBehavior(BaseNode::BEHAVIOR_EXECUTION);
SetupExecutionPorts(true, 1, true); // IN 0, OUT 0
AddInputPort(Port::Type::DATA_PORT, "Duration");
nlohmann::json j{{"duration_ms", m_durationMs}};
SetInternalData(j);
}
void WaitDelayNode::Initialize()
{
nlohmann::json j = GetInternalData();
if (j.contains("duration_ms")) {
m_durationMs = j["duration_ms"].get<uint32_t>();
}
}
void WaitDelayNode::SetDuration(uint32_t ms)
{
m_durationMs = ms;
nlohmann::json j{{"duration_ms", m_durationMs}};
SetInternalData(j);
}

View file

@ -0,0 +1,21 @@
// core/story-manager/src/nodes/wait_delay_node.h
#pragma once
#include <string>
#include "base_node.h"
#include "i_story_project.h"
class WaitDelayNode : public BaseNode
{
public:
WaitDelayNode(const std::string &type = "wait-delay-node");
void Initialize() override;
// Durée en millisecondes
uint32_t GetDuration() const { return m_durationMs; }
void SetDuration(uint32_t ms);
private:
uint32_t m_durationMs{1000};
};

View file

@ -0,0 +1,74 @@
// core/story-manager/src/nodes/wait_event_node.cpp
#include "wait_event_node.h"
WaitEventNode::WaitEventNode(const std::string &type)
: BaseNode(type, "Wait Event")
{
SetBehavior(BaseNode::BEHAVIOR_EXECUTION);
SetupExecutionPorts(true, 1, true); // IN 0 (exec), OUT 0 (exec)
AddInputPort(Port::Type::DATA_PORT, "Event Mask");
AddInputPort(Port::Type::DATA_PORT, "Timeout");
nlohmann::json j{
{"event_mask", m_eventMask},
{"timeout", m_timeout},
{"result_variable_uuid", m_resultVariableUuid}
};
SetInternalData(j);
}
void WaitEventNode::Initialize()
{
nlohmann::json j = GetInternalData();
if (j.contains("event_mask")) {
m_eventMask = j["event_mask"].get<uint32_t>();
}
if (j.contains("timeout")) {
m_timeout = j["timeout"].get<uint32_t>();
}
if (j.contains("result_variable_uuid")) {
m_resultVariableUuid = j["result_variable_uuid"].get<std::string>();
}
}
void WaitEventNode::SetEventMask(uint32_t mask)
{
m_eventMask = mask;
nlohmann::json j = GetInternalData();
j["event_mask"] = m_eventMask;
SetInternalData(j);
}
void WaitEventNode::SetTimeout(uint32_t ms)
{
m_timeout = ms;
nlohmann::json j = GetInternalData();
j["timeout"] = m_timeout;
SetInternalData(j);
}
void WaitEventNode::SetResultVariable(const std::string& varUuid)
{
m_resultVariableUuid = varUuid;
nlohmann::json j = GetInternalData();
j["result_variable_uuid"] = m_resultVariableUuid;
SetInternalData(j);
}
std::shared_ptr<Variable> WaitEventNode::ResolveResultVariable(
const std::vector<std::shared_ptr<Variable>>& variables) const
{
if (m_resultVariableUuid.empty()) {
return nullptr;
}
for (const auto& var : variables) {
if (var->GetUuid() == m_resultVariableUuid) {
return var;
}
}
return nullptr;
}

View file

@ -0,0 +1,35 @@
// core/story-manager/src/nodes/wait_event_node.h
#pragma once
#include <string>
#include "base_node.h"
#include "i_story_project.h"
#include "variable.h"
class WaitEventNode : public BaseNode
{
public:
WaitEventNode(const std::string &type = "wait-event-node");
void Initialize() override;
// Event mask (bits pour différents types d'événements)
uint32_t GetEventMask() const { return m_eventMask; }
void SetEventMask(uint32_t mask);
// Timeout en millisecondes (0 = infini)
uint32_t GetTimeout() const { return m_timeout; }
void SetTimeout(uint32_t ms);
// Variable de destination pour le code de retour
std::string GetResultVariableUuid() const { return m_resultVariableUuid; }
void SetResultVariable(const std::string& varUuid);
// Helper pour résoudre la variable (utilisé par TAC Generator)
std::shared_ptr<Variable> ResolveResultVariable(const std::vector<std::shared_ptr<Variable>>& variables) const;
private:
uint32_t m_eventMask{0b10000000000}; // Défaut: OK + Home + EndAudio
uint32_t m_timeout{0}; // 0 = infini
std::string m_resultVariableUuid;
};

View file

@ -12,19 +12,25 @@
#include "variable_node.h"
#include "operator_node.h"
#include "print_node.h"
#include "syscall_node.h"
#include "story_project.h"
#include "story_primitive.h"
#include "function_entry_node.h"
#include "branch_node.h"
#include "wait_delay_node.h"
#include "wait_event_node.h"
#include "play_media_node.h"
#include "send_signal_node.h"
static const std::string OperatorNodeUuid = "0226fdac-8f7a-47d7-8584-b23aceb712ec";
static const std::string CallFunctionNodeUuid = "02745f38-9b11-49fe-94b1-b2a6b78249fb";
static const std::string VariableNodeUuid = "020cca4e-9cdc-47e7-a6a5-53e4c9152ed0";
static const std::string PrintNodeUuid = "02ee27bc-ff1d-4f94-b700-eab55052ad1c";
static const std::string SyscallNodeUuid = "02225cff-4975-400e-8130-41524d8af773";
static const std::string FunctionEntryNodeUuid = "02fd145a-b3a6-43c2-83ce-6a187e6d4b5b";
static const std::string BranchNodeUuid = "027b723d-2327-4646-a17a-79ddc2e016e4";
static const std::string WaitEventNodeUuid = "02225cff-4975-400e-8130-41524d8af773";
static const std::string WaitDelayNodeUuid = "02455ef0-4975-4546-94de-720cae6baae3";
static const std::string PlayMediaNodeUuid = "0285e90a-2eb7-4605-baa9-b3712a14dff8";
static const std::string SendSignalNodeUuid = "02c2ce4b-8783-47cb-a55f-90056bebd64b";
typedef std::shared_ptr<BaseNode> (*GenericCreator)(const std::string &type);
@ -42,10 +48,12 @@ public:
registerNode<CallFunctionNode>(CallFunctionNodeUuid, std::make_shared<StoryPrimitive>("Call function"));
registerNode<VariableNode>(VariableNodeUuid, std::make_shared<StoryPrimitive>("Variable"));
registerNode<PrintNode>(PrintNodeUuid, std::make_shared<StoryPrimitive>("Print"));
registerNode<SyscallNode>(SyscallNodeUuid, std::make_shared<StoryPrimitive>("System call"));
registerNode<FunctionEntryNode>(FunctionEntryNodeUuid, std::make_shared<StoryPrimitive>("Function entry"));
registerNode<BranchNode>(BranchNodeUuid, std::make_shared<StoryPrimitive>("Branch"));
registerNode<WaitEventNode>(WaitEventNodeUuid, std::make_shared<StoryPrimitive>("Wait Event"));
registerNode<WaitDelayNode>(WaitDelayNodeUuid, std::make_shared<StoryPrimitive>("Wait Delay"));
registerNode<PlayMediaNode>(PlayMediaNodeUuid, std::make_shared<StoryPrimitive>("Play Media"));
registerNode<SendSignalNode>(SendSignalNodeUuid, std::make_shared<StoryPrimitive>("Send Signal"));
}
~NodesFactory() = default;

View file

@ -79,7 +79,7 @@ public:
m_uuid = uuid;
}
virtual void ScanVariable(const std::function<void(std::shared_ptr<Variable> element)>& operation) override {
virtual void ScanVariable(const std::function<bool(std::shared_ptr<Variable> element)>& operation) override {
}
virtual void AddVariable() override {

View file

@ -11,7 +11,6 @@
#include "variable_node.h"
#include "operator_node.h"
#include "print_node.h"
#include "syscall_node.h"
#include "sys_lib.h"
#include "assembly_generator_chip32_tac.h"
#include "nodes_factory.h"
@ -225,11 +224,13 @@ std::pair<std::list<std::shared_ptr<Connection>>::iterator, std::list<std::share
return std::pair<std::list<std::shared_ptr<Connection>>::iterator, std::list<std::shared_ptr<Connection>>::iterator>();
}
void StoryProject::ScanVariable(const std::function<void(std::shared_ptr<Variable> element)>& operation)
void StoryProject::ScanVariable(const std::function<bool(std::shared_ptr<Variable> element)>& operation)
{
for (auto &v : m_variables)
{
operation(v);
bool ret = operation(v);
if (!ret)
break;
}
}

View file

@ -104,7 +104,7 @@ public:
std::pair<std::list<std::shared_ptr<Connection>>::iterator, std::list<std::shared_ptr<Connection>>::iterator> Links(const std::string_view &page_uuid);
void ScanVariable(const std::function<void(std::shared_ptr<Variable> element)>& operation) override;
void ScanVariable(const std::function<bool(std::shared_ptr<Variable> element)>& operation) override;
void AddVariable() override;
void DeleteVariable(int i) override;

View file

@ -36,8 +36,12 @@ add_executable(${PROJECT_NAME}
../story-manager/src/nodes/branch_node.cpp
../story-manager/src/nodes/print_node.cpp
../story-manager/src/nodes/variable_node.cpp
../story-manager/src/nodes/syscall_node.cpp
../story-manager/src/nodes/connection.cpp
../story-manager/src/nodes/wait_event_node.cpp
../story-manager/src/nodes/wait_delay_node.cpp
../story-manager/src/nodes/play_media_node.cpp
../story-manager/src/nodes/send_signal_node.cpp
../chip32/chip32_assembler.cpp
../chip32/chip32_vm.c

View file

@ -147,8 +147,11 @@ set(SRCS
src/node_editor/variable_node_widget.cpp
src/node_editor/operator_node_widget.cpp
src/node_editor/print_node_widget.cpp
src/node_editor/syscall_node_widget.cpp
src/node_editor/branch_node_widget.cpp
src/node_editor/wait_event_node_widget.cpp
src/node_editor/wait_delay_node_widget.cpp
src/node_editor/play_media_node_widget.cpp
src/node_editor/send_signal_node_widget.cpp
src/gui.cpp
src/media_converter.cpp
@ -182,12 +185,15 @@ set(SRCS
../core/story-manager/src/nodes/base_node.cpp
../core/story-manager/src/nodes/compare_node.cpp
../core/story-manager/src/nodes/branch_node.cpp
../core/story-manager/src/nodes/variable_node.cpp
../core/story-manager/src/nodes/module_node.cpp
../core/story-manager/src/nodes/print_node.cpp
../core/story-manager/src/nodes/syscall_node.cpp
../core/story-manager/src/nodes/wait_event_node.cpp
../core/story-manager/src/nodes/wait_delay_node.cpp
../core/story-manager/src/nodes/play_media_node.cpp
../core/story-manager/src/nodes/send_signal_node.cpp
../core/story-manager/src/nodes/connection.cpp
../core/story-manager/src/story_db.cpp
../core/story-manager/src/sys_lib.cpp

View file

@ -1,6 +1,6 @@
[Window][WindowOverViewport_11111111]
Pos=60,26
Size=1429,832
Size=1220,694
Collapsed=0
[Window][Debug##Default]
@ -9,32 +9,32 @@ Size=400,400
Collapsed=0
[Window][Library Manager]
Pos=554,26
Size=935,607
Pos=710,26
Size=570,469
Collapsed=0
DockId=0x00000002,0
[Window][Console]
Pos=60,635
Size=618,223
Pos=60,497
Size=527,223
Collapsed=0
DockId=0x00000004,0
[Window][Emulator]
Pos=554,26
Size=935,607
Pos=710,26
Size=570,469
Collapsed=0
DockId=0x00000002,5
[Window][Code viewer]
Pos=554,26
Size=935,607
Pos=710,26
Size=570,469
Collapsed=0
DockId=0x00000002,4
[Window][Resources]
Pos=554,26
Size=935,607
Pos=710,26
Size=570,469
Collapsed=0
DockId=0x00000002,1
@ -50,32 +50,32 @@ Size=150,42
Collapsed=0
[Window][Variables]
Pos=680,635
Size=809,223
Pos=589,497
Size=691,223
Collapsed=0
DockId=0x00000005,0
[Window][CPU]
Pos=554,26
Size=935,607
Pos=710,26
Size=570,469
Collapsed=0
DockId=0x00000002,2
[Window][RAM view]
Pos=554,26
Size=935,607
Pos=710,26
Size=570,469
Collapsed=0
DockId=0x00000002,3
[Window][Properties]
Pos=680,635
Size=809,223
Pos=589,497
Size=691,223
Collapsed=0
DockId=0x00000005,1
[Window][ToolBar]
Pos=0,26
Size=60,832
Size=60,694
Collapsed=0
[Window][QuitConfirm]
@ -90,13 +90,13 @@ Collapsed=0
[Window][Module editor]
Pos=60,26
Size=492,607
Size=648,469
Collapsed=0
DockId=0x00000001,0
[Window][Story editor]
Pos=60,26
Size=492,607
Size=648,469
Collapsed=0
DockId=0x00000001,1
@ -106,8 +106,8 @@ Size=687,422
Collapsed=0
[Window][Error List]
Pos=60,635
Size=618,223
Pos=60,497
Size=527,223
Collapsed=0
DockId=0x00000004,1
@ -155,10 +155,10 @@ Column 2 Weight=1.0000
Column 3 Width=60
[Docking][Data]
DockSpace ID=0x08BD597D Window=0x1BBC0F80 Pos=60,26 Size=1429,832 Split=Y
DockSpace ID=0x08BD597D Window=0x1BBC0F80 Pos=60,26 Size=1220,694 Split=Y
DockNode ID=0x00000007 Parent=0x08BD597D SizeRef=1220,469 Split=X
DockNode ID=0x00000001 Parent=0x00000007 SizeRef=492,694 CentralNode=1 Selected=0x93ADCAAB
DockNode ID=0x00000002 Parent=0x00000007 SizeRef=935,694 Selected=0x63869CAF
DockNode ID=0x00000001 Parent=0x00000007 SizeRef=648,694 CentralNode=1 Selected=0x93ADCAAB
DockNode ID=0x00000002 Parent=0x00000007 SizeRef=570,694 Selected=0x63869CAF
DockNode ID=0x00000008 Parent=0x08BD597D SizeRef=1220,223 Split=X Selected=0xEA83D666
DockNode ID=0x00000004 Parent=0x00000008 SizeRef=621,192 Selected=0xEA83D666
DockNode ID=0x00000005 Parent=0x00000008 SizeRef=813,192 Selected=0x8C72BEA8

View file

@ -20,11 +20,11 @@
AppController::AppController(ILogger& logger, EventBus& eventBus)
: m_logger(logger)
, m_eventBus(eventBus) // m_eventBus pour les événements
, m_resources(logger) // m_resources a besoin d'un IStoryManager/IResourceSource
, m_nodesFactory(logger) // m_nodesFactory a besoin d'un IStoryManager/IResourceSource
, m_libraryManager(logger, m_nodesFactory) // m_libraryManager a besoin d'un IStoryManager/INodeFactory
, m_player(*this) // m_player a besoin d'un IAudioEvent
, m_eventBus(eventBus)
, m_resources(logger)
, m_nodesFactory(logger)
, m_libraryManager(logger, m_nodesFactory)
, m_player(*this)
, m_webServer(m_libraryManager)
{

View file

@ -32,9 +32,12 @@
#include "variable_node_widget.h"
#include "operator_node_widget.h"
#include "print_node_widget.h"
#include "syscall_node_widget.h"
#include "function_entry_widget.h"
#include "branch_node_widget.h"
#include "play_media_node_widget.h"
#include "send_signal_node_widget.h"
#include "wait_delay_node_widget.h"
#include "wait_event_node_widget.h"
MainWindow::MainWindow(ILogger& logger, EventBus& eventBus, AppController& appController)
: m_logger(logger)
@ -57,24 +60,18 @@ MainWindow::MainWindow(ILogger& logger, EventBus& eventBus, AppController& appCo
// define style for all files
ImGuiFileDialog::Instance()->SetFileStyle(IGFD_FileStyleByTypeFile, "", ImVec4(1.0f, 1.0f, 1.0f, 1.0f), ICON_MDI_FILE);
// g OperatorNodeUuid = "0226fdac-8f7a-47d7-8584-b23aceb712ec";
// static const std::string CallFunctionNodeUuid = "02745f38-9b11-49fe-94b1-b2a6b78249fb";
// static const std::string VariableNodeUuid = "020cca4e-9cdc-47e7-a6a5-53e4c9152ed0";
// static const std::string PrintNodeUuid = "02ee27bc-ff1d-4f94-b700-eab55052ad1c";
// static const std::string SyscallNodeUuid = "02225cff-4975-400e-8130-41524d8af773";
// static const std::string ModuleNodeUuid = "02e4c728-ef72-4003-b7c8-2bee8834a47e";
// registerNode<MediaNodeWidget>("media-node");
m_widgetFactory.registerNode<OperatorNodeWidget>(OperatorNodeUuid);
m_widgetFactory.registerNode<CallFunctionNodeWidget>(CallFunctionNodeUuid);
// m_widgetFactory.registerNode<ModuleNodeWidget>("module-node");
m_widgetFactory.registerNode<VariableNodeWidget>(VariableNodeUuid);
m_widgetFactory.registerNode<PrintNodeWidget>(PrintNodeUuid);
m_widgetFactory.registerNode<SyscallNodeWidget>(SyscallNodeUuid);
m_widgetFactory.registerNode<FunctionEntryWidget>(FunctionEntryNodeUuid);
m_widgetFactory.registerNode<BranchNodeWidget>(BranchNodeUuid);
m_widgetFactory.registerNode<WaitEventNodeWidget>(WaitEventNodeUuid);
m_widgetFactory.registerNode<WaitDelayNodeWidget>(WaitDelayNodeUuid);
m_widgetFactory.registerNode<PlayMediaNodeWidget>(PlayMediaNodeUuid);
m_widgetFactory.registerNode<SendSignalNodeWidget>(SendSignalNodeUuid);
m_eventBus.Subscribe<OpenProjectEvent>([this](const OpenProjectEvent &event) {
OpenProject(event.GetUuid());

View file

@ -130,6 +130,8 @@ public:
void SetTitle(const std::string& title) { m_title = title; }
std::string GetTitle() const { return m_title; }
IStoryManager &Manager() { return m_manager; }
private:
IStoryManager &m_manager;
std::shared_ptr<BaseNode> m_base;

View file

@ -0,0 +1,51 @@
// story-editor/src/node_editor/play_media_node_widget.cpp
#include "play_media_node_widget.h"
#include "IconsMaterialDesignIcons.h"
PlayMediaNodeWidget::PlayMediaNodeWidget(IStoryManager &manager, std::shared_ptr<BaseNode> node)
: BaseNodeWidget(manager, node)
{
m_playMediaNode = std::dynamic_pointer_cast<PlayMediaNode>(node);
}
void PlayMediaNodeWidget::Initialize()
{
BaseNodeWidget::Initialize();
}
void PlayMediaNodeWidget::DrawProperties(std::shared_ptr<IStoryProject> story)
{
ImGui::AlignTextToFramePadding();
ImGui::TextWrapped("This node plays media (image and/or sound) at runtime.");
ImGui::Spacing();
ImGui::TextColored(ImVec4(0.7f, 0.9f, 1.0f, 1.0f), "Data Inputs:");
ImGui::BulletText("Port 1: Image name (string)");
ImGui::Indent();
ImGui::TextDisabled("Variable or constant with filename");
ImGui::TextDisabled("Pass 0 or null for no image");
ImGui::Unindent();
ImGui::BulletText("Port 2: Sound name (string)");
ImGui::Indent();
ImGui::TextDisabled("Variable or constant with filename");
ImGui::TextDisabled("Pass 0 or null for no sound");
ImGui::Unindent();
ImGui::Spacing();
ImGui::Separator();
ImGui::Spacing();
ImGui::TextColored(ImVec4(1.0f, 0.8f, 0.4f, 1.0f), "Note:");
ImGui::TextWrapped("Connect string variables/constants to the data input ports. "
"The syscall expects filenames relative to the assets folder.");
}
void PlayMediaNodeWidget::Draw()
{
ImGui::Text(ICON_MDI_PLAY_CIRCLE " Play Media");
ImGui::TextDisabled("Data-driven");
ImGui::TextColored(ImVec4(0.6f, 0.9f, 1.0f, 1.0f), "Image: IN 1");
ImGui::TextColored(ImVec4(0.6f, 1.0f, 0.9f, 1.0f), "Sound: IN 2");
}

View file

@ -0,0 +1,21 @@
// story-editor/src/node_editor/play_media_node_widget.h
#pragma once
#include "base_node_widget.h"
#include "i_story_manager.h"
#include "i_story_project.h"
#include "play_media_node.h"
class PlayMediaNodeWidget : public BaseNodeWidget
{
public:
PlayMediaNodeWidget(IStoryManager &manager, std::shared_ptr<BaseNode> node);
void Draw() override;
void DrawProperties(std::shared_ptr<IStoryProject> story) override;
void Initialize() override;
private:
std::shared_ptr<PlayMediaNode> m_playMediaNode;
};

View file

@ -0,0 +1,39 @@
// story-editor/src/node_editor/send_signal_node_widget.cpp
#include "send_signal_node_widget.h"
#include "IconsMaterialDesignIcons.h"
SendSignalNodeWidget::SendSignalNodeWidget(IStoryManager &manager, std::shared_ptr<BaseNode> node)
: BaseNodeWidget(manager, node)
{
m_sendSignalNode = std::dynamic_pointer_cast<SendSignalNode>(node);
}
void SendSignalNodeWidget::Initialize()
{
BaseNodeWidget::Initialize();
}
void SendSignalNodeWidget::DrawProperties(std::shared_ptr<IStoryProject> story)
{
ImGui::AlignTextToFramePadding();
int signalId = static_cast<int>(m_sendSignalNode->GetSignalId());
if (ImGui::InputInt("Signal ID", &signalId, 1, 10))
{
if (signalId < 0) signalId = 0;
m_sendSignalNode->SetSignalId(static_cast<uint32_t>(signalId));
}
ImGui::Spacing();
ImGui::TextDisabled("Sends a signal to other processes");
ImGui::TextDisabled("Signal ID: 0x%08X", m_sendSignalNode->GetSignalId());
}
void SendSignalNodeWidget::Draw()
{
uint32_t signalId = m_sendSignalNode->GetSignalId();
ImGui::Text(ICON_MDI_SIGNAL " Signal");
ImGui::TextColored(ImVec4(1.0f, 0.8f, 0.4f, 1.0f),
"ID: 0x%X", signalId);
}

View file

@ -0,0 +1,20 @@
// story-editor/src/node_editor/send_signal_node_widget.h
#pragma once
#include "base_node_widget.h"
#include "i_story_manager.h"
#include "i_story_project.h"
#include "send_signal_node.h"
class SendSignalNodeWidget : public BaseNodeWidget
{
public:
SendSignalNodeWidget(IStoryManager &manager, std::shared_ptr<BaseNode> node);
void Draw() override;
void DrawProperties(std::shared_ptr<IStoryProject> story) override;
void Initialize() override;
private:
std::shared_ptr<SendSignalNode> m_sendSignalNode;
};

View file

@ -1,46 +0,0 @@
#include <sstream>
#include "syscall_node_widget.h"
#include "IconsMaterialDesignIcons.h"
#include "story_project.h"
#include "uuid.h"
SyscallNodeWidget::SyscallNodeWidget(IStoryManager &manager, std::shared_ptr<BaseNode> node)
: BaseNodeWidget(manager, node)
{
m_syscallNode = std::dynamic_pointer_cast<SyscallNode>(node);
}
void SyscallNodeWidget::Initialize()
{
BaseNodeWidget::Initialize();
}
void SyscallNodeWidget::DrawProperties(std::shared_ptr<IStoryProject> story)
{
ImGui::AlignTextToFramePadding();
static ImGuiComboFlags flags = 0;
int syscallNumber = m_syscallNode->GetSyscallNumber();
if (ImGui::InputInt("Syscall Number", &syscallNumber, 1, 1000))
{
m_syscallNode->SetSyscallNumber(syscallNumber);
}
}
void SyscallNodeWidget::Draw()
{
switch(m_syscallNode->GetSyscallNumber())
{
case SyscallNode::SYSCALL_PLAY_MEDIA:
ImGui::Text("Play Media");
break;
default:
ImGui::Text("Unknown syscall");
break;
}
}

View file

@ -1,27 +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 "gui.h"
#include "syscall_node.h"
#include "media_node.h"
class SyscallNodeWidget : public BaseNodeWidget
{
public:
SyscallNodeWidget(IStoryManager &manager, std::shared_ptr<BaseNode> node);
void Draw() override;
virtual void DrawProperties(std::shared_ptr<IStoryProject> story) override;
virtual void Initialize() override;
private:
std::shared_ptr<SyscallNode> m_syscallNode;
};

View file

@ -29,7 +29,9 @@ void VariableNodeWidget::DrawProperties(std::shared_ptr<IStoryProject> story)
if (var->GetUuid() == m_selectedVariableUuid)
{
m_selectedVariableName = var->GetVariableName();
return false;
}
return true;
});
}
@ -61,6 +63,7 @@ void VariableNodeWidget::DrawProperties(std::shared_ptr<IStoryProject> story)
}
i++;
return true;
});
ImGui::EndCombo();
}
@ -72,7 +75,9 @@ void VariableNodeWidget::DrawProperties(std::shared_ptr<IStoryProject> story)
if (var->GetUuid() == m_selectedVariableUuid) {
ImGui::Text("Type: %s", Variable::ValueTypeToString(var->GetValueType()).c_str());
ImGui::Text("Value: %s", var->GetValueAsString().c_str());
return false;
}
return true;
});
}
}

View file

@ -0,0 +1,44 @@
// story-editor/src/node_editor/wait_delay_node_widget.cpp
#include "wait_delay_node_widget.h"
#include "IconsMaterialDesignIcons.h"
WaitDelayNodeWidget::WaitDelayNodeWidget(IStoryManager &manager, std::shared_ptr<BaseNode> node)
: BaseNodeWidget(manager, node)
{
m_waitDelayNode = std::dynamic_pointer_cast<WaitDelayNode>(node);
}
void WaitDelayNodeWidget::Initialize()
{
BaseNodeWidget::Initialize();
}
void WaitDelayNodeWidget::DrawProperties(std::shared_ptr<IStoryProject> story)
{
ImGui::AlignTextToFramePadding();
int duration = static_cast<int>(m_waitDelayNode->GetDuration());
if (ImGui::InputInt("Duration (ms)", &duration, 10, 100))
{
if (duration < 0) duration = 0;
m_waitDelayNode->SetDuration(static_cast<uint32_t>(duration));
}
ImGui::Spacing();
ImGui::TextDisabled("Pauses execution for the specified duration");
}
void WaitDelayNodeWidget::Draw()
{
uint32_t duration = m_waitDelayNode->GetDuration();
ImGui::Text(ICON_MDI_TIMER_OUTLINE " Wait");
if (duration >= 1000) {
ImGui::TextColored(ImVec4(0.7f, 0.9f, 1.0f, 1.0f),
"%.1f sec", duration / 1000.0f);
} else {
ImGui::TextColored(ImVec4(0.7f, 0.9f, 1.0f, 1.0f),
"%u ms", duration);
}
}

View file

@ -0,0 +1,20 @@
// story-editor/src/node_editor/wait_delay_node_widget.h
#pragma once
#include "base_node_widget.h"
#include "i_story_manager.h"
#include "i_story_project.h"
#include "wait_delay_node.h"
class WaitDelayNodeWidget : public BaseNodeWidget
{
public:
WaitDelayNodeWidget(IStoryManager &manager, std::shared_ptr<BaseNode> node);
void Draw() override;
void DrawProperties(std::shared_ptr<IStoryProject> story) override;
void Initialize() override;
private:
std::shared_ptr<WaitDelayNode> m_waitDelayNode;
};

View file

@ -0,0 +1,224 @@
// story-editor/src/node_editor/wait_event_node_widget.cpp
#include "wait_event_node_widget.h"
#include "IconsMaterialDesignIcons.h"
WaitEventNodeWidget::WaitEventNodeWidget(IStoryManager &manager, std::shared_ptr<BaseNode> node)
: BaseNodeWidget(manager, node)
{
m_waitEventNode = std::dynamic_pointer_cast<WaitEventNode>(node);
}
void WaitEventNodeWidget::Initialize()
{
BaseNodeWidget::Initialize();
}
void WaitEventNodeWidget::DrawProperties(std::shared_ptr<IStoryProject> story)
{
ImGui::AlignTextToFramePadding();
// Event Mask Editor
ImGui::Text("Event Mask:");
DrawEventMaskEditor();
ImGui::Spacing();
ImGui::Separator();
ImGui::Spacing();
// Timeout
ImGui::Text("Timeout:");
int timeout = static_cast<int>(m_waitEventNode->GetTimeout());
if (ImGui::InputInt("ms##timeout", &timeout, 100, 1000))
{
if (timeout < 0) timeout = 0;
m_waitEventNode->SetTimeout(static_cast<uint32_t>(timeout));
}
ImGui::SameLine();
ImGui::TextDisabled("(0 = infinite)");
ImGui::Spacing();
ImGui::Separator();
ImGui::Spacing();
// Result Variable
ImGui::Text("Result Variable:");
std::string resultVarUuid = m_waitEventNode->GetResultVariableUuid();
std::string selectedVarName = "(none - use R0 directly)";
// Trouver le nom de la variable sélectionnée
story->ScanVariable([this, &resultVarUuid, &selectedVarName](std::shared_ptr<Variable> var) {
if (var->GetUuid() == resultVarUuid) {
selectedVarName = var->GetVariableName();
return false;
}
return true;
});
if (ImGui::BeginCombo("##resultvar", selectedVarName.c_str())) {
if (ImGui::Selectable("(none - use R0 directly)", resultVarUuid.empty())) {
m_waitEventNode->SetResultVariable("");
}
int i = 0;
story->ScanVariable([&i, &resultVarUuid, this](std::shared_ptr<Variable> var) {
if (var->GetValueType() == Variable::ValueType::INTEGER) {
bool isSelected = (var->GetUuid() == resultVarUuid);
if (ImGui::Selectable(var->GetVariableName().c_str(), isSelected)) {
m_waitEventNode->SetResultVariable(var->GetUuid());
}
if (isSelected) {
ImGui::SetItemDefaultFocus();
}
}
i++;
return true;
});
ImGui::EndCombo();
}
ImGui::Spacing();
ImGui::TextDisabled("The event code will be stored in this variable");
ImGui::TextDisabled("or in R0 if no variable is selected");
}
void WaitEventNodeWidget::DrawEventMaskEditor()
{
uint32_t mask = m_waitEventNode->GetEventMask();
bool changed = false;
// Affichage hexadécimal
ImGui::Text("Hex: 0x%08X", mask);
ImGui::Spacing();
// Bits individuels (exemple de masque d'événements communs)
// Bit 0-7: Boutons numériques
// Bit 8: OK button
// Bit 9: Home button
// Bit 10: End of audio
ImGui::BeginGroup();
bool bit0 = (mask & (1 << 0)) != 0;
if (ImGui::Checkbox("Bit 0 (Button 0)", &bit0)) {
mask = bit0 ? (mask | (1 << 0)) : (mask & ~(1 << 0));
changed = true;
}
bool bit1 = (mask & (1 << 1)) != 0;
if (ImGui::Checkbox("Bit 1 (Button 1)", &bit1)) {
mask = bit1 ? (mask | (1 << 1)) : (mask & ~(1 << 1));
changed = true;
}
bool bit2 = (mask & (1 << 2)) != 0;
if (ImGui::Checkbox("Bit 2 (Button 2)", &bit2)) {
mask = bit2 ? (mask | (1 << 2)) : (mask & ~(1 << 2));
changed = true;
}
bool bit3 = (mask & (1 << 3)) != 0;
if (ImGui::Checkbox("Bit 3 (Button 3)", &bit3)) {
mask = bit3 ? (mask | (1 << 3)) : (mask & ~(1 << 3));
changed = true;
}
ImGui::EndGroup();
ImGui::SameLine();
ImGui::BeginGroup();
bool bit8 = (mask & (1 << 8)) != 0;
if (ImGui::Checkbox("Bit 8 (OK Button)", &bit8)) {
mask = bit8 ? (mask | (1 << 8)) : (mask & ~(1 << 8));
changed = true;
}
bool bit9 = (mask & (1 << 9)) != 0;
if (ImGui::Checkbox("Bit 9 (Home Button)", &bit9)) {
mask = bit9 ? (mask | (1 << 9)) : (mask & ~(1 << 9));
changed = true;
}
bool bit10 = (mask & (1 << 10)) != 0;
if (ImGui::Checkbox("Bit 10 (End Audio)", &bit10)) {
mask = bit10 ? (mask | (1 << 10)) : (mask & ~(1 << 10));
changed = true;
}
ImGui::EndGroup();
ImGui::Spacing();
// Presets communs
if (ImGui::Button("Preset: All Events")) {
mask = 0xFFFFFFFF;
changed = true;
}
ImGui::SameLine();
if (ImGui::Button("Preset: Media End")) {
mask = 0b10000000000; // OK + Home + EndAudio
changed = true;
}
ImGui::SameLine();
if (ImGui::Button("Clear All")) {
mask = 0;
changed = true;
}
if (changed) {
m_waitEventNode->SetEventMask(mask);
}
}
void WaitEventNodeWidget::Draw()
{
uint32_t mask = m_waitEventNode->GetEventMask();
uint32_t timeout = m_waitEventNode->GetTimeout();
ImGui::Text(ICON_MDI_TIMER_SAND " Wait Event");
// Description du masque
std::string desc = GetEventMaskDescription(mask);
ImGui::TextColored(ImVec4(0.8f, 0.8f, 0.4f, 1.0f), "%s", desc.c_str());
// Timeout si défini
if (timeout > 0) {
ImGui::TextColored(ImVec4(0.7f, 0.7f, 0.7f, 1.0f),
"Timeout: %u ms", timeout);
}
}
std::string WaitEventNodeWidget::GetEventMaskDescription(uint32_t mask)
{
if (mask == 0) {
return "No events";
}
if (mask == 0xFFFFFFFF) {
return "All events";
}
// Compter les bits actifs
int bitCount = 0;
for (int i = 0; i < 32; i++) {
if (mask & (1 << i)) bitCount++;
}
if (bitCount == 1) {
// Un seul événement
for (int i = 0; i < 32; i++) {
if (mask & (1 << i)) {
if (i == 8) return "OK button";
if (i == 9) return "Home button";
if (i == 10) return "End audio";
return "Event bit " + std::to_string(i);
}
}
}
// Plusieurs événements
return std::to_string(bitCount) + " events";
}

View file

@ -0,0 +1,23 @@
// story-editor/src/node_editor/wait_event_node_widget.h
#pragma once
#include "base_node_widget.h"
#include "i_story_manager.h"
#include "i_story_project.h"
#include "wait_event_node.h"
class WaitEventNodeWidget : public BaseNodeWidget
{
public:
WaitEventNodeWidget(IStoryManager &manager, std::shared_ptr<BaseNode> node);
void Draw() override;
void DrawProperties(std::shared_ptr<IStoryProject> story) override;
void Initialize() override;
private:
std::shared_ptr<WaitEventNode> m_waitEventNode;
void DrawEventMaskEditor();
std::string GetEventMaskDescription(uint32_t mask);
};

View file

@ -100,7 +100,7 @@ void VariablesWindow::DrawVariableEditor(std::shared_ptr<IStoryProject> story)
}
ImGui::PopID();
i++;
return true;
});
}