mirror of
https://github.com/arabine/open-story-teller.git
synced 2025-12-06 17:09:06 +01:00
Build splitted to allow multi pages compilation, more widgets
This commit is contained in:
parent
51eac85360
commit
d6df8b65ab
24 changed files with 515 additions and 325 deletions
|
|
@ -1,17 +0,0 @@
|
||||||
# StoryTeller core components
|
|
||||||
|
|
||||||
Each component is organized as follow:
|
|
||||||
|
|
||||||
Directories:
|
|
||||||
- interfaces: contains only pure virtual C++ interface classes
|
|
||||||
- lib: shared static classes utilities
|
|
||||||
- src: core implementation (private files)
|
|
||||||
|
|
||||||
|
|
||||||
# story-manager
|
|
||||||
|
|
||||||
GUI agnostic implementation of the editor engine.
|
|
||||||
|
|
||||||
# story-vm
|
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -20,7 +20,14 @@
|
||||||
|
|
||||||
class AssemblyGenerator : public IVariableVisitor {
|
class AssemblyGenerator : public IVariableVisitor {
|
||||||
public:
|
public:
|
||||||
struct GeneratorContext {
|
enum class Section {
|
||||||
|
NONE,
|
||||||
|
DATA,
|
||||||
|
TEXT
|
||||||
|
};
|
||||||
|
|
||||||
|
struct GeneratorContext
|
||||||
|
{
|
||||||
std::string timestamp;
|
std::string timestamp;
|
||||||
std::string username;
|
std::string username;
|
||||||
bool debugOutput;
|
bool debugOutput;
|
||||||
|
|
@ -56,36 +63,68 @@ public:
|
||||||
m_currentSection = Section::NONE;
|
m_currentSection = Section::NONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string GenerateAssembly(std::vector<std::shared_ptr<BaseNode>> &nodes, const std::vector<std::shared_ptr<ASTNode>>& order, const std::vector<std::shared_ptr<Variable>> &variables)
|
void GenerateHeader() {
|
||||||
|
AddComment("Assembly generated by Visual Node Editor");
|
||||||
|
AddComment("Generation time: " + m_context.timestamp);
|
||||||
|
AddComment("Generated by: " + m_context.username);
|
||||||
|
AddComment("Optimization: " + m_context.optimizeCode ? "enabled" : "disabled");
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void GenerateExit() = 0;
|
||||||
|
|
||||||
|
void StartSection(Section section) {
|
||||||
|
if (m_currentSection == section) return;
|
||||||
|
|
||||||
|
m_currentSection = section;
|
||||||
|
switch (section) {
|
||||||
|
case Section::DATA:
|
||||||
|
AddComment("======================= DATA =======================");
|
||||||
|
break;
|
||||||
|
case Section::TEXT:
|
||||||
|
AddComment("======================= CODE =======================");
|
||||||
|
GenerateMain();
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void GenerateNodesVariables(const std::vector<std::shared_ptr<BaseNode>> &nodes)
|
||||||
{
|
{
|
||||||
Reset();
|
// Generate all constants
|
||||||
|
for (const auto& n : nodes) {
|
||||||
|
n->Accept(*this);
|
||||||
|
}
|
||||||
|
|
||||||
// Generate header comments
|
m_assembly << "\n\n";
|
||||||
GenerateHeader();
|
}
|
||||||
|
|
||||||
// Generate data section
|
void GenerateGlobalVariables(const std::vector<std::shared_ptr<Variable>> &variables)
|
||||||
StartSection(Section::DATA);
|
{
|
||||||
GenerateDataSection(nodes, variables);
|
for (const auto& v : variables) {
|
||||||
|
GenerateVariable(v);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Generate text section
|
void GenerateTextSection(const std::vector<std::shared_ptr<ASTNode>>& orderedNodes)
|
||||||
StartSection(Section::TEXT);
|
{
|
||||||
GenerateTextSection(order);
|
for (const auto& node : orderedNodes)
|
||||||
|
{
|
||||||
|
GenerateNodeCode(node);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string GetAssembly() const {
|
||||||
return m_assembly.str();
|
return m_assembly.str();
|
||||||
}
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
enum class Section {
|
|
||||||
NONE,
|
|
||||||
DATA,
|
|
||||||
TEXT
|
|
||||||
};
|
|
||||||
|
|
||||||
virtual void GenerateNodeCode(std::shared_ptr<ASTNode> node, bool isDataPath = false) = 0;
|
virtual void GenerateNodeCode(std::shared_ptr<ASTNode> node, bool isDataPath = false) = 0;
|
||||||
|
|
||||||
virtual void AddComment(const std::string& comment) = 0;
|
virtual void AddComment(const std::string& comment) = 0;
|
||||||
|
|
||||||
virtual void GenerateExit() = 0;
|
virtual void GenerateMain() = 0;
|
||||||
|
|
||||||
virtual void GenerateVariable(const std::shared_ptr<Variable> v) = 0;
|
virtual void GenerateVariable(const std::shared_ptr<Variable> v) = 0;
|
||||||
|
|
||||||
|
|
@ -102,6 +141,8 @@ protected:
|
||||||
return prefix + "_" + std::to_string(m_labelCounter++);
|
return prefix + "_" + std::to_string(m_labelCounter++);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
GeneratorContext m_context;
|
GeneratorContext m_context;
|
||||||
std::stringstream m_assembly;
|
std::stringstream m_assembly;
|
||||||
|
|
@ -115,83 +156,5 @@ protected:
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
void GenerateHeader() {
|
|
||||||
AddComment("Assembly generated by Visual Node Editor");
|
|
||||||
AddComment("Generation time: " + m_context.timestamp);
|
|
||||||
AddComment("Generated by: " + m_context.username);
|
|
||||||
AddComment("Optimization: " + m_context.optimizeCode ? "enabled" : "disabled");
|
|
||||||
}
|
|
||||||
|
|
||||||
void StartSection(Section section) {
|
|
||||||
if (m_currentSection == section) return;
|
|
||||||
|
|
||||||
m_currentSection = section;
|
|
||||||
switch (section) {
|
|
||||||
case Section::DATA:
|
|
||||||
AddComment("======================= DATA =======================");
|
|
||||||
break;
|
|
||||||
case Section::TEXT:
|
|
||||||
AddComment("======================= CODE =======================");
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void GenerateDataSection(const std::vector<std::shared_ptr<BaseNode>> &nodes, const std::vector<std::shared_ptr<Variable>> &variables)
|
|
||||||
{
|
|
||||||
// Generate all constants
|
|
||||||
for (const auto& n : nodes) {
|
|
||||||
n->Accept(*this);
|
|
||||||
}
|
|
||||||
|
|
||||||
// generate all variables in RAM
|
|
||||||
for (auto & v : variables)
|
|
||||||
{
|
|
||||||
GenerateVariable(v);
|
|
||||||
}
|
|
||||||
|
|
||||||
m_assembly << "\n\n";
|
|
||||||
}
|
|
||||||
|
|
||||||
void GenerateTextSection(const std::vector<std::shared_ptr<ASTNode>>& orderedNodes) {
|
|
||||||
// Program entry point
|
|
||||||
m_assembly << ".main:\n";
|
|
||||||
|
|
||||||
for (const auto& node : orderedNodes) {
|
|
||||||
GenerateNodeCode(node);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Program exit
|
|
||||||
GenerateExit();
|
|
||||||
}
|
|
||||||
|
|
||||||
void CollectVariables(std::shared_ptr<ASTNode> node)
|
|
||||||
{
|
|
||||||
if (!node) return;
|
|
||||||
|
|
||||||
if (node->IsType<VariableNode>()) {
|
|
||||||
auto* varNode = node->GetAs<VariableNode>();
|
|
||||||
/*
|
|
||||||
std::string varName = varNode->GetN();
|
|
||||||
if (m_variableAddresses.find(varName) == m_variableAddresses.end()) {
|
|
||||||
m_variableAddresses[varName] = varName;
|
|
||||||
m_assembly << varName << ":\n" << varNode->GenerateAssembly();
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
}
|
|
||||||
|
|
||||||
// Traverse children
|
|
||||||
for (auto& child : node->children) {
|
|
||||||
CollectVariables(child);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Traverse data inputs
|
|
||||||
for (const auto& [port, inputNode] : node->dataInputs) {
|
|
||||||
CollectVariables(inputNode);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
@ -37,28 +37,30 @@ public:
|
||||||
GeneratePrintNode(node);
|
GeneratePrintNode(node);
|
||||||
}
|
}
|
||||||
|
|
||||||
// // If we're processing a data path, traverse data outputs
|
// // If there is no any children, put an halt
|
||||||
// if (isDataPath) {
|
if (node->GetChildCount() == 0)
|
||||||
// for (const auto& [port, outputs] : node->dataOutputs) {
|
{
|
||||||
// for (const auto& target : outputs) {
|
AddComment("Program exit");
|
||||||
// GenerateNodeCode(target.node, true);
|
m_assembly << " halt\n";
|
||||||
// }
|
}
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void AddComment(const std::string& comment) {
|
virtual void AddComment(const std::string& comment) {
|
||||||
m_assembly << std::string(m_depth * 4, ' ') << "; " << comment << "\n";
|
m_assembly << std::string(m_depth * 4, ' ') << "; " << comment << "\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void GenerateExit() {
|
virtual void GenerateExit() override {
|
||||||
AddComment("Program exit");
|
AddComment("Program exit");
|
||||||
m_assembly << " halt\n";
|
m_assembly << " halt\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
|
virtual void GenerateMain() override {
|
||||||
|
// Program entry point
|
||||||
|
m_assembly << ".main:\n";
|
||||||
|
}
|
||||||
|
|
||||||
void GenerateFunctionEntry(std::shared_ptr<ASTNode> node) {
|
void GenerateFunctionEntry(std::shared_ptr<ASTNode> node) {
|
||||||
AddComment("Function Entry");
|
AddComment("Function Entry");
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,7 @@
|
||||||
#include "base_node.h"
|
#include "base_node.h"
|
||||||
#include "connection.h"
|
#include "connection.h"
|
||||||
#include "function_entry_node.h"
|
#include "function_entry_node.h"
|
||||||
|
#include "variable_node.h"
|
||||||
|
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
#include <unordered_set>
|
#include <unordered_set>
|
||||||
|
|
@ -32,6 +33,10 @@ public:
|
||||||
// Data outputs: output_port_index -> vector of (target node, target port)
|
// Data outputs: output_port_index -> vector of (target node, target port)
|
||||||
std::unordered_map<unsigned int, std::vector<DataTarget>> dataOutputs;
|
std::unordered_map<unsigned int, std::vector<DataTarget>> dataOutputs;
|
||||||
|
|
||||||
|
bool HasChildren(std::shared_ptr<ASTNode> c) const {
|
||||||
|
return std::find(children.begin(), children.end(), c) != children.end();
|
||||||
|
}
|
||||||
|
|
||||||
bool IsExecutionNode() const {
|
bool IsExecutionNode() const {
|
||||||
return node->GetBehavior() == BaseNode::Behavior::BEHAVIOR_EXECUTION;
|
return node->GetBehavior() == BaseNode::Behavior::BEHAVIOR_EXECUTION;
|
||||||
}
|
}
|
||||||
|
|
@ -201,15 +206,18 @@ private:
|
||||||
|
|
||||||
void BuildExecutionPath(std::vector<std::shared_ptr<ASTNode>>& tree,
|
void BuildExecutionPath(std::vector<std::shared_ptr<ASTNode>>& tree,
|
||||||
const std::unordered_map<std::string, std::shared_ptr<ASTNode>>& nodeMap)
|
const std::unordered_map<std::string, std::shared_ptr<ASTNode>>& nodeMap)
|
||||||
|
{
|
||||||
|
// For each node in the tree, find its children based on the connections
|
||||||
|
for (const auto& node : tree)
|
||||||
{
|
{
|
||||||
std::queue<std::shared_ptr<ASTNode>> queue;
|
std::queue<std::shared_ptr<ASTNode>> queue;
|
||||||
queue.push(tree.front());
|
queue.push(node);
|
||||||
|
|
||||||
while (!queue.empty()) {
|
while (!queue.empty()) {
|
||||||
auto current = queue.front();
|
auto current = queue.front();
|
||||||
queue.pop();
|
queue.pop();
|
||||||
|
|
||||||
// Find execution connections from this node
|
// Find connections from this node
|
||||||
for (const auto& conn : m_connections)
|
for (const auto& conn : m_connections)
|
||||||
{
|
{
|
||||||
if (conn->outNodeId == current->node->GetId())
|
if (conn->outNodeId == current->node->GetId())
|
||||||
|
|
@ -218,6 +226,10 @@ private:
|
||||||
if (targetNode != nodeMap.end())
|
if (targetNode != nodeMap.end())
|
||||||
{
|
{
|
||||||
auto childNode = targetNode->second;
|
auto childNode = targetNode->second;
|
||||||
|
|
||||||
|
// Si le noeud n'a pas déjà cet enfant, on l'ajoute
|
||||||
|
if (!current->HasChildren(childNode))
|
||||||
|
{
|
||||||
current->children.push_back(childNode);
|
current->children.push_back(childNode);
|
||||||
queue.push(childNode);
|
queue.push(childNode);
|
||||||
}
|
}
|
||||||
|
|
@ -225,6 +237,8 @@ private:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
std::vector<std::shared_ptr<ASTNode>> ApplyKahnAlgorithm(const std::unordered_map<std::string, std::shared_ptr<ASTNode>> &nodeMap)
|
std::vector<std::shared_ptr<ASTNode>> ApplyKahnAlgorithm(const std::unordered_map<std::string, std::shared_ptr<ASTNode>> &nodeMap)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -61,6 +61,10 @@ protected:
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
virtual void GenerateMain() override {
|
||||||
|
// Program entry point
|
||||||
|
FlowVisualizer::PrintNodeExecution("Main Entry", m_depth);
|
||||||
|
}
|
||||||
|
|
||||||
virtual void Visit(const std::shared_ptr<Variable> v) {
|
virtual void Visit(const std::shared_ptr<Variable> v) {
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -17,11 +17,6 @@ public:
|
||||||
// Par exemple, préparer les entrées nécessaires pour la fonction
|
// Par exemple, préparer les entrées nécessaires pour la fonction
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string Build(IStoryPage &page, const StoryOptions &options, int nb_out_conns) override {
|
|
||||||
// Logique de construction pour FunctionEntryNode
|
|
||||||
return GetMyEntryLabel() + ":\n";
|
|
||||||
}
|
|
||||||
|
|
||||||
// Ajoutez des méthodes spécifiques pour gérer l'entrée de la fonction
|
// Ajoutez des méthodes spécifiques pour gérer l'entrée de la fonction
|
||||||
void PrepareFunctionEntry() {
|
void PrepareFunctionEntry() {
|
||||||
// Logique pour préparer l'entrée de la fonction
|
// Logique pour préparer l'entrée de la fonction
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,5 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "base_node.h"
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include "base_node.h"
|
#include "base_node.h"
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
|
|
@ -36,6 +32,39 @@ public:
|
||||||
RIGHT_SHIFT // Right shift (>>)
|
RIGHT_SHIFT // Right shift (>>)
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct OperatorDesc {
|
||||||
|
std::string name;
|
||||||
|
std::string symbol;
|
||||||
|
};
|
||||||
|
|
||||||
|
const std::unordered_map<OperationType, OperatorDesc>& GetOperators() const
|
||||||
|
{
|
||||||
|
static const std::unordered_map<OperationType, OperatorDesc> Operators = {
|
||||||
|
{OperationType::ADD, {"Addition", "+"}},
|
||||||
|
{OperationType::SUBTRACT, {"Subtraction", "-"}},
|
||||||
|
{OperationType::MULTIPLY, {"Multiplication", "*"}},
|
||||||
|
{OperationType::DIVIDE, {"Division", "/"}},
|
||||||
|
{OperationType::MODULO, {"Modulo", "%"}},
|
||||||
|
{OperationType::AND, {"Logical AND", "&&"}},
|
||||||
|
{OperationType::OR, {"Logical OR", "||"}},
|
||||||
|
{OperationType::NOT, {"Logical NOT", "!"}},
|
||||||
|
{OperationType::XOR, {"Logical XOR", "^"}},
|
||||||
|
{OperationType::EQUAL, {"Equal to", "=="}},
|
||||||
|
{OperationType::NOT_EQUAL, {"Not equal to", "!="}},
|
||||||
|
{OperationType::GREATER_THAN, {"Greater than", ">"}},
|
||||||
|
{OperationType::LESS_THAN, {"Less than", "<"}},
|
||||||
|
{OperationType::GREATER_EQUAL, {"Greater than or equal to", ">="}},
|
||||||
|
{OperationType::LESS_EQUAL, {"Less than or equal to", "<="}},
|
||||||
|
{OperationType::BITWISE_AND, {"Bitwise AND", "&"}},
|
||||||
|
{OperationType::BITWISE_OR, {"Bitwise OR", "|"}},
|
||||||
|
{OperationType::BITWISE_XOR, {"Bitwise XOR", "^"}},
|
||||||
|
{OperationType::BITWISE_NOT, {"Bitwise NOT", "~"}},
|
||||||
|
{OperationType::LEFT_SHIFT, {"Left shift", "<<"}},
|
||||||
|
{OperationType::RIGHT_SHIFT, {"Right shift", ">>"}}
|
||||||
|
};
|
||||||
|
return Operators;
|
||||||
|
}
|
||||||
|
|
||||||
OperatorNode(const std::string& type = "operator-node",
|
OperatorNode(const std::string& type = "operator-node",
|
||||||
const std::string& typeName = "Operator")
|
const std::string& typeName = "Operator")
|
||||||
: BaseNode(type, typeName, BaseNode::Behavior::BEHAVIOR_DATA)
|
: BaseNode(type, typeName, BaseNode::Behavior::BEHAVIOR_DATA)
|
||||||
|
|
@ -61,51 +90,11 @@ public:
|
||||||
|
|
||||||
// Get the symbol representation of the operator
|
// Get the symbol representation of the operator
|
||||||
std::string GetOperatorSymbol() const {
|
std::string GetOperatorSymbol() const {
|
||||||
static const std::unordered_map<OperationType, std::string> symbolMap = {
|
auto symbolMap = GetOperators();
|
||||||
{OperationType::ADD, "+"},
|
|
||||||
{OperationType::SUBTRACT, "-"},
|
|
||||||
{OperationType::MULTIPLY, "*"},
|
|
||||||
{OperationType::DIVIDE, "/"},
|
|
||||||
{OperationType::MODULO, "%"},
|
|
||||||
{OperationType::AND, "&&"},
|
|
||||||
{OperationType::OR, "||"},
|
|
||||||
{OperationType::NOT, "!"},
|
|
||||||
{OperationType::XOR, "^"},
|
|
||||||
{OperationType::EQUAL, "=="},
|
|
||||||
{OperationType::NOT_EQUAL, "!="},
|
|
||||||
{OperationType::GREATER_THAN, ">"},
|
|
||||||
{OperationType::LESS_THAN, "<"},
|
|
||||||
{OperationType::GREATER_EQUAL, ">="},
|
|
||||||
{OperationType::LESS_EQUAL, "<="},
|
|
||||||
{OperationType::BITWISE_AND, "&"},
|
|
||||||
{OperationType::BITWISE_OR, "|"},
|
|
||||||
{OperationType::BITWISE_XOR, "^"},
|
|
||||||
{OperationType::BITWISE_NOT, "~"},
|
|
||||||
{OperationType::LEFT_SHIFT, "<<"},
|
|
||||||
{OperationType::RIGHT_SHIFT, ">>"}
|
|
||||||
};
|
|
||||||
|
|
||||||
auto it = symbolMap.find(m_operationType);
|
auto it = symbolMap.find(m_operationType);
|
||||||
return it != symbolMap.end() ? it->second : "?";
|
return it != symbolMap.end() ? it->second.symbol : "?";
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string Build(IStoryPage& page, const StoryOptions& options, int nb_out_conns) override {
|
|
||||||
std::stringstream ss;
|
|
||||||
ss << "// Operator: " << GetOperatorSymbol() << "\n";
|
|
||||||
|
|
||||||
// For unary operators
|
|
||||||
if (IsUnaryOperator()) {
|
|
||||||
ss << GetOperatorSymbol() << "operand";
|
|
||||||
}
|
|
||||||
// For binary operators
|
|
||||||
else {
|
|
||||||
ss << "operand1 " << GetOperatorSymbol() << " operand2";
|
|
||||||
}
|
|
||||||
|
|
||||||
return ss.str();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
OperationType m_operationType;
|
OperationType m_operationType;
|
||||||
|
|
||||||
|
|
@ -130,61 +119,20 @@ private:
|
||||||
AddOutputPort(Port::DATA_PORT, "out");
|
AddOutputPort(Port::DATA_PORT, "out");
|
||||||
}
|
}
|
||||||
|
|
||||||
static std::string OperatorTypeToString(OperationType type) {
|
std::string OperatorTypeName(OperationType type) const {
|
||||||
static const std::unordered_map<OperationType, std::string> typeMap = {
|
auto symbolMap = GetOperators();
|
||||||
{OperationType::ADD, "add"},
|
auto it = symbolMap.find(type);
|
||||||
{OperationType::SUBTRACT, "subtract"},
|
return it != symbolMap.end() ? it->second.name : "Unknown";
|
||||||
{OperationType::MULTIPLY, "multiply"},
|
|
||||||
{OperationType::DIVIDE, "divide"},
|
|
||||||
{OperationType::MODULO, "modulo"},
|
|
||||||
{OperationType::AND, "and"},
|
|
||||||
{OperationType::OR, "or"},
|
|
||||||
{OperationType::NOT, "not"},
|
|
||||||
{OperationType::XOR, "xor"},
|
|
||||||
{OperationType::EQUAL, "equal"},
|
|
||||||
{OperationType::NOT_EQUAL, "not_equal"},
|
|
||||||
{OperationType::GREATER_THAN, "greater_than"},
|
|
||||||
{OperationType::LESS_THAN, "less_than"},
|
|
||||||
{OperationType::GREATER_EQUAL, "greater_equal"},
|
|
||||||
{OperationType::LESS_EQUAL, "less_equal"},
|
|
||||||
{OperationType::BITWISE_AND, "bitwise_and"},
|
|
||||||
{OperationType::BITWISE_OR, "bitwise_or"},
|
|
||||||
{OperationType::BITWISE_XOR, "bitwise_xor"},
|
|
||||||
{OperationType::BITWISE_NOT, "bitwise_not"},
|
|
||||||
{OperationType::LEFT_SHIFT, "left_shift"},
|
|
||||||
{OperationType::RIGHT_SHIFT, "right_shift"}
|
|
||||||
};
|
|
||||||
|
|
||||||
auto it = typeMap.find(type);
|
|
||||||
return it != typeMap.end() ? it->second : "unknown";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static OperationType StringToOperationType(const std::string& str) {
|
OperationType SymbolToOperationType(const std::string& str) const {
|
||||||
static const std::unordered_map<std::string, OperationType> typeMap = {
|
auto symbolMap = GetOperators();
|
||||||
{"add", OperationType::ADD},
|
|
||||||
{"subtract", OperationType::SUBTRACT},
|
|
||||||
{"multiply", OperationType::MULTIPLY},
|
|
||||||
{"divide", OperationType::DIVIDE},
|
|
||||||
{"modulo", OperationType::MODULO},
|
|
||||||
{"and", OperationType::AND},
|
|
||||||
{"or", OperationType::OR},
|
|
||||||
{"not", OperationType::NOT},
|
|
||||||
{"xor", OperationType::XOR},
|
|
||||||
{"equal", OperationType::EQUAL},
|
|
||||||
{"not_equal", OperationType::NOT_EQUAL},
|
|
||||||
{"greater_than", OperationType::GREATER_THAN},
|
|
||||||
{"less_than", OperationType::LESS_THAN},
|
|
||||||
{"greater_equal", OperationType::GREATER_EQUAL},
|
|
||||||
{"less_equal", OperationType::LESS_EQUAL},
|
|
||||||
{"bitwise_and", OperationType::BITWISE_AND},
|
|
||||||
{"bitwise_or", OperationType::BITWISE_OR},
|
|
||||||
{"bitwise_xor", OperationType::BITWISE_XOR},
|
|
||||||
{"bitwise_not", OperationType::BITWISE_NOT},
|
|
||||||
{"left_shift", OperationType::LEFT_SHIFT},
|
|
||||||
{"right_shift", OperationType::RIGHT_SHIFT}
|
|
||||||
};
|
|
||||||
|
|
||||||
auto it = typeMap.find(str);
|
for (const auto& pair : symbolMap) {
|
||||||
return it != typeMap.end() ? it->second : OperationType::ADD;
|
if (pair.second.symbol == str) {
|
||||||
|
return pair.first;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return OperationType::ADD; // Default to ADD if not found
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -19,10 +19,3 @@ void PrintNode::Initialize()
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string PrintNode::Build(IStoryPage &page, const StoryOptions &options, int nb_out_conns)
|
|
||||||
{
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -12,7 +12,6 @@ public:
|
||||||
PrintNode(const std::string &type);
|
PrintNode(const std::string &type);
|
||||||
|
|
||||||
virtual void Initialize() override;
|
virtual void Initialize() override;
|
||||||
virtual std::string Build(IStoryPage &page, const StoryOptions &options, int nb_out_conns) override;
|
|
||||||
|
|
||||||
void SetText(const std::string &text) {
|
void SetText(const std::string &text) {
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -8,6 +8,7 @@
|
||||||
#include "i_story_project.h"
|
#include "i_story_project.h"
|
||||||
#include "base_node.h"
|
#include "base_node.h"
|
||||||
#include "connection.h"
|
#include "connection.h"
|
||||||
|
#include "assembly_generator.h"
|
||||||
|
|
||||||
class StoryPage : public IStoryPage
|
class StoryPage : public IStoryPage
|
||||||
{
|
{
|
||||||
|
|
@ -50,18 +51,20 @@ public:
|
||||||
m_nodes.clear();
|
m_nodes.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Build(std::stringstream &code, IStoryProject &project)
|
void BuildNodesVariables(AssemblyGenerator &generator)
|
||||||
{
|
{
|
||||||
// // First generate all constants
|
std::vector<std::shared_ptr<BaseNode>> nodes(m_nodes.begin(), m_nodes.end());
|
||||||
// for (const auto & n : m_nodes)
|
generator.GenerateNodesVariables(nodes);
|
||||||
// {
|
}
|
||||||
// code << n->GenerateConstants(*this, project, OutputsCount(n->GetId())) << "\n";
|
|
||||||
// }
|
|
||||||
|
|
||||||
// for (const auto & n : m_nodes)
|
void BuildNodes(AssemblyGenerator &generator)
|
||||||
// {
|
{
|
||||||
// code << n->Build(*this, project.GetOptions(), OutputsCount(n->GetId())) << "\n";
|
std::vector<std::shared_ptr<BaseNode>> nodes(m_nodes.begin(), m_nodes.end());
|
||||||
// }
|
std::vector<std::shared_ptr<Connection>> links(m_links.begin(), m_links.end());
|
||||||
|
ASTBuilder builder(nodes, links);
|
||||||
|
auto pathTree = builder.BuildAST();
|
||||||
|
|
||||||
|
generator.GenerateTextSection(pathTree);
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void GetNodeConnections(std::list<std::shared_ptr<Connection>> &c, const std::string &nodeId) override
|
virtual void GetNodeConnections(std::list<std::shared_ptr<Connection>> &c, const std::string &nodeId) override
|
||||||
|
|
|
||||||
|
|
@ -10,14 +10,19 @@
|
||||||
// #include "media_node.h"
|
// #include "media_node.h"
|
||||||
#include "function_node.h"
|
#include "function_node.h"
|
||||||
#include "variable_node.h"
|
#include "variable_node.h"
|
||||||
|
#include "operator_node.h"
|
||||||
|
#include "print_node.h"
|
||||||
#include "sys_lib.h"
|
#include "sys_lib.h"
|
||||||
|
#include "assembly_generator_chip32.h"
|
||||||
|
|
||||||
StoryProject::StoryProject(ILogger &log)
|
StoryProject::StoryProject(ILogger &log)
|
||||||
: m_log(log)
|
: m_log(log)
|
||||||
{
|
{
|
||||||
// registerNode<MediaNode>("media-node");
|
// registerNode<MediaNode>("media-node");
|
||||||
|
registerNode<FunctionNode>("operator-node");
|
||||||
registerNode<FunctionNode>("function-node");
|
registerNode<FunctionNode>("function-node");
|
||||||
registerNode<VariableNode>("variable-node");
|
registerNode<VariableNode>("variable-node");
|
||||||
|
registerNode<PrintNode>("print-node");
|
||||||
}
|
}
|
||||||
|
|
||||||
StoryProject::~StoryProject()
|
StoryProject::~StoryProject()
|
||||||
|
|
@ -380,42 +385,59 @@ bool StoryProject::UseResource(const std::string &label)
|
||||||
bool StoryProject::GenerateScript(std::string &codeStr)
|
bool StoryProject::GenerateScript(std::string &codeStr)
|
||||||
{
|
{
|
||||||
std::stringstream code;
|
std::stringstream code;
|
||||||
std::stringstream chip32;
|
|
||||||
std::string firstNode;
|
|
||||||
|
|
||||||
for (const auto & p : m_pages)
|
|
||||||
{
|
|
||||||
firstNode = p->FindFirstNode();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (firstNode == "")
|
|
||||||
{
|
|
||||||
m_log.Log("First node not found, there must be only one node with a free input.");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
code << "\tjump " << BaseNode::GetEntryLabel(firstNode) << "\r\n";
|
|
||||||
|
|
||||||
// Empty resources usage
|
// Empty resources usage
|
||||||
m_usedLabels.clear();
|
m_usedLabels.clear();
|
||||||
|
|
||||||
// On build toutes les pages
|
|
||||||
|
|
||||||
|
// Create generator context with current time and user
|
||||||
|
AssemblyGenerator::GeneratorContext context(
|
||||||
|
"2025-04-08 12:09:01", // Current UTC time
|
||||||
|
"story-editor", // Current user
|
||||||
|
true, // Enable debug output
|
||||||
|
true, // Enable optimizations
|
||||||
|
1024 // Stack size
|
||||||
|
);
|
||||||
|
|
||||||
|
// Create generator
|
||||||
|
AssemblyGeneratorChip32 generator(context);
|
||||||
|
|
||||||
|
|
||||||
|
generator.Reset();
|
||||||
|
|
||||||
|
// Generate header comments
|
||||||
|
generator.GenerateHeader();
|
||||||
|
|
||||||
|
// Generate data section
|
||||||
|
generator.StartSection(AssemblyGenerator::Section::DATA);
|
||||||
for (const auto & p : m_pages)
|
for (const auto & p : m_pages)
|
||||||
{
|
{
|
||||||
p->Build(code, *this);
|
p->BuildNodesVariables(generator);
|
||||||
|
}
|
||||||
|
generator.GenerateGlobalVariables(m_variables);
|
||||||
|
|
||||||
|
// Generate text section
|
||||||
|
generator.StartSection(AssemblyGenerator::Section::TEXT);
|
||||||
|
|
||||||
|
for (const auto & p : m_pages)
|
||||||
|
{
|
||||||
|
p->BuildNodes(generator);
|
||||||
}
|
}
|
||||||
|
|
||||||
codeStr = code.str();
|
generator.GenerateExit();
|
||||||
|
|
||||||
|
codeStr = generator.GetAssembly();
|
||||||
|
|
||||||
// Add our utility functions
|
// Add our utility functions
|
||||||
std::string buffer;
|
// std::string buffer;
|
||||||
|
|
||||||
std::ifstream f("scripts/media.chip32");
|
// std::ifstream f("scripts/media.chip32");
|
||||||
f.seekg(0, std::ios::end);
|
// f.seekg(0, std::ios::end);
|
||||||
buffer.resize(f.tellg());
|
// buffer.resize(f.tellg());
|
||||||
f.seekg(0);
|
// f.seekg(0);
|
||||||
f.read(buffer.data(), buffer.size());
|
// f.read(buffer.data(), buffer.size());
|
||||||
codeStr += buffer;
|
// codeStr += buffer;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -216,7 +216,7 @@ TEST_CASE( "Check various indentations and typos" ) {
|
||||||
// Create generator context with current time and user
|
// Create generator context with current time and user
|
||||||
AssemblyGenerator::GeneratorContext context(
|
AssemblyGenerator::GeneratorContext context(
|
||||||
"2025-04-08 12:09:01", // Current UTC time
|
"2025-04-08 12:09:01", // Current UTC time
|
||||||
"arabine", // Current user
|
"unit-test-ast", // Current user
|
||||||
true, // Enable debug output
|
true, // Enable debug output
|
||||||
true, // Enable optimizations
|
true, // Enable optimizations
|
||||||
1024 // Stack size
|
1024 // Stack size
|
||||||
|
|
@ -232,13 +232,28 @@ TEST_CASE( "Check various indentations and typos" ) {
|
||||||
// Generate flow in the console
|
// Generate flow in the console
|
||||||
VisualFlowGenerator flowGenerator(context);
|
VisualFlowGenerator flowGenerator(context);
|
||||||
FlowVisualizer::PrintHeader("arabine", "2025-04-08 12:03:01");
|
FlowVisualizer::PrintHeader("arabine", "2025-04-08 12:03:01");
|
||||||
std::string flow = flowGenerator.GenerateAssembly(nodes, pathTree, variables);
|
flowGenerator.GenerateTextSection(pathTree);
|
||||||
|
|
||||||
|
std::string flow = flowGenerator.GetAssembly();
|
||||||
|
|
||||||
std::cout << "\nGenerated flow:\n" << flow << std::endl;
|
std::cout << "\nGenerated flow:\n" << flow << std::endl;
|
||||||
|
|
||||||
// Generate assembly
|
//------------------------------------ Generate assembly ------------------------------------
|
||||||
std::string assembly = generator.GenerateAssembly(nodes, pathTree, variables);
|
|
||||||
|
generator.Reset();
|
||||||
|
|
||||||
|
// Generate header comments
|
||||||
|
generator.GenerateHeader();
|
||||||
|
|
||||||
|
// Generate data section
|
||||||
|
generator.StartSection(AssemblyGenerator::Section::DATA);
|
||||||
|
generator.GenerateNodesVariables(nodes);
|
||||||
|
generator.GenerateGlobalVariables(variables);
|
||||||
|
generator.StartSection(AssemblyGenerator::Section::TEXT);
|
||||||
|
generator.GenerateTextSection(pathTree);
|
||||||
|
generator.GenerateExit();
|
||||||
|
|
||||||
|
std::string assembly = generator.GetAssembly();
|
||||||
|
|
||||||
std::cout << "\nGenerated assembly:\n" << assembly << std::endl;
|
std::cout << "\nGenerated assembly:\n" << assembly << std::endl;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -135,6 +135,8 @@ set(SRCS
|
||||||
src/node_editor/node_editor_window.cpp
|
src/node_editor/node_editor_window.cpp
|
||||||
src/node_editor/function_node_widget.cpp
|
src/node_editor/function_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/print_node_widget.cpp
|
||||||
|
|
||||||
src/gui.cpp
|
src/gui.cpp
|
||||||
src/media_converter.cpp
|
src/media_converter.cpp
|
||||||
|
|
@ -177,6 +179,7 @@ set(SRCS
|
||||||
../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/function_node.cpp
|
../core/story-manager/src/nodes/function_node.cpp
|
||||||
|
../core/story-manager/src/nodes/print_node.cpp
|
||||||
../core/story-manager/src/nodes/connection.cpp
|
../core/story-manager/src/nodes/connection.cpp
|
||||||
|
|
||||||
../core/story-manager/lib/sys_lib.cpp
|
../core/story-manager/lib/sys_lib.cpp
|
||||||
|
|
|
||||||
|
|
@ -9,63 +9,69 @@ Size=400,400
|
||||||
Collapsed=0
|
Collapsed=0
|
||||||
|
|
||||||
[Window][Library Manager]
|
[Window][Library Manager]
|
||||||
Pos=672,26
|
Pos=900,26
|
||||||
Size=608,694
|
Size=380,322
|
||||||
Collapsed=0
|
Collapsed=0
|
||||||
DockId=0x00000002,0
|
DockId=0x00000003,0
|
||||||
|
|
||||||
[Window][Console]
|
[Window][Console]
|
||||||
Pos=386,659
|
Pos=60,545
|
||||||
Size=1152,344
|
Size=1220,175
|
||||||
Collapsed=0
|
Collapsed=0
|
||||||
|
DockId=0x00000008,0
|
||||||
|
|
||||||
[Window][Emulator]
|
[Window][Emulator]
|
||||||
Pos=269,26
|
Pos=398,26
|
||||||
Size=401,694
|
Size=500,517
|
||||||
Collapsed=0
|
Collapsed=0
|
||||||
DockId=0x00000005,1
|
DockId=0x00000005,1
|
||||||
|
|
||||||
[Window][Code viewer]
|
[Window][Code viewer]
|
||||||
Pos=269,26
|
Pos=398,26
|
||||||
Size=401,694
|
Size=500,517
|
||||||
Collapsed=0
|
Collapsed=0
|
||||||
DockId=0x00000005,0
|
DockId=0x00000005,0
|
||||||
|
|
||||||
[Window][Resources]
|
[Window][Resources]
|
||||||
Pos=672,26
|
Pos=900,26
|
||||||
Size=608,694
|
Size=380,322
|
||||||
Collapsed=0
|
Collapsed=0
|
||||||
DockId=0x00000002,1
|
DockId=0x00000003,1
|
||||||
|
|
||||||
[Window][Node editor]
|
[Window][Node editor]
|
||||||
Pos=96,129
|
Pos=60,26
|
||||||
Size=394,407
|
Size=336,517
|
||||||
Collapsed=0
|
Collapsed=0
|
||||||
|
DockId=0x00000004,0
|
||||||
|
|
||||||
[Window][TOOLBAR]
|
[Window][TOOLBAR]
|
||||||
Pos=96,105
|
Pos=92,208
|
||||||
Size=79,42
|
Size=79,42
|
||||||
Collapsed=0
|
Collapsed=0
|
||||||
|
|
||||||
[Window][Variables]
|
[Window][Variables]
|
||||||
Pos=199,187
|
Pos=398,26
|
||||||
Size=121,72
|
Size=500,517
|
||||||
Collapsed=0
|
Collapsed=0
|
||||||
|
DockId=0x00000005,2
|
||||||
|
|
||||||
[Window][CPU]
|
[Window][CPU]
|
||||||
Pos=515,59
|
Pos=900,26
|
||||||
Size=626,744
|
Size=380,322
|
||||||
Collapsed=0
|
Collapsed=0
|
||||||
|
DockId=0x00000003,2
|
||||||
|
|
||||||
[Window][RAM view]
|
[Window][RAM view]
|
||||||
Pos=378,79
|
Pos=900,26
|
||||||
Size=738,442
|
Size=380,322
|
||||||
Collapsed=0
|
Collapsed=0
|
||||||
|
DockId=0x00000003,3
|
||||||
|
|
||||||
[Window][Properties]
|
[Window][Properties]
|
||||||
Pos=754,344
|
Pos=900,350
|
||||||
Size=626,744
|
Size=380,193
|
||||||
Collapsed=0
|
Collapsed=0
|
||||||
|
DockId=0x00000006,0
|
||||||
|
|
||||||
[Window][ToolBar]
|
[Window][ToolBar]
|
||||||
Pos=0,26
|
Pos=0,26
|
||||||
|
|
@ -97,9 +103,13 @@ Column 1 Width=88
|
||||||
Column 2 Width=124
|
Column 2 Width=124
|
||||||
|
|
||||||
[Docking][Data]
|
[Docking][Data]
|
||||||
DockSpace ID=0x08BD597D Window=0x1BBC0F80 Pos=60,26 Size=1220,694 Split=X
|
DockSpace ID=0x08BD597D Window=0x1BBC0F80 Pos=60,26 Size=1220,694 Split=Y
|
||||||
DockNode ID=0x00000001 Parent=0x08BD597D SizeRef=610,694 Split=X
|
DockNode ID=0x00000007 Parent=0x08BD597D SizeRef=1220,517 Split=X
|
||||||
DockNode ID=0x00000004 Parent=0x00000001 SizeRef=397,600 CentralNode=1 Selected=0x63869CAF
|
DockNode ID=0x00000001 Parent=0x00000007 SizeRef=838,694 Split=X
|
||||||
DockNode ID=0x00000005 Parent=0x00000001 SizeRef=401,600 Selected=0x4B07C626
|
DockNode ID=0x00000004 Parent=0x00000001 SizeRef=336,600 CentralNode=1 Selected=0xBB79A587
|
||||||
DockNode ID=0x00000002 Parent=0x08BD597D SizeRef=608,694 Selected=0x30401527
|
DockNode ID=0x00000005 Parent=0x00000001 SizeRef=500,600 Selected=0x52EB28B5
|
||||||
|
DockNode ID=0x00000002 Parent=0x00000007 SizeRef=380,694 Split=Y Selected=0xE5897A33
|
||||||
|
DockNode ID=0x00000003 Parent=0x00000002 SizeRef=608,322 Selected=0x63869CAF
|
||||||
|
DockNode ID=0x00000006 Parent=0x00000002 SizeRef=608,193 Selected=0x8C72BEA8
|
||||||
|
DockNode ID=0x00000008 Parent=0x08BD597D SizeRef=1220,175 Selected=0xEA83D666
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -19,10 +19,13 @@ BaseNodeWidget::~BaseNodeWidget()
|
||||||
std::cout << " <-- Deleted node widget: " << (int)m_node->ID.Get() << std::endl;
|
std::cout << " <-- Deleted node widget: " << (int)m_node->ID.Get() << std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
void BaseNodeWidget::AddInput()
|
void BaseNodeWidget::AddInputs(int num)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < num; i++)
|
||||||
{
|
{
|
||||||
m_node->Inputs.emplace_back(GetNextId(), "", PinType::Flow);
|
m_node->Inputs.emplace_back(GetNextId(), "", PinType::Flow);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void BaseNodeWidget::AddOutputs(int num)
|
void BaseNodeWidget::AddOutputs(int num)
|
||||||
{
|
{
|
||||||
|
|
@ -32,6 +35,21 @@ void BaseNodeWidget::AddOutputs(int num)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void BaseNodeWidget::SetInputs(uint32_t num)
|
||||||
|
{
|
||||||
|
if (num > Inputs())
|
||||||
|
{
|
||||||
|
AddInputs(num - Inputs());
|
||||||
|
}
|
||||||
|
else if (num < Inputs())
|
||||||
|
{
|
||||||
|
for (unsigned int i = 0; i < (Inputs() - num); i++)
|
||||||
|
{
|
||||||
|
m_node->Inputs.pop_back();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void BaseNodeWidget::SetOutputs(uint32_t num)
|
void BaseNodeWidget::SetOutputs(uint32_t num)
|
||||||
{
|
{
|
||||||
if (num > Outputs())
|
if (num > Outputs())
|
||||||
|
|
@ -59,6 +77,15 @@ void BaseNodeWidget::Initialize()
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void BaseNodeWidget::SetInputPinName(int pinIndex, const std::string &name)
|
||||||
|
{
|
||||||
|
if (pinIndex < m_node->Inputs.size())
|
||||||
|
{
|
||||||
|
m_node->Inputs[pinIndex].Name = name;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void BaseNodeWidget::SetOutPinName(int pinIndex, const std::string &name)
|
void BaseNodeWidget::SetOutPinName(int pinIndex, const std::string &name)
|
||||||
{
|
{
|
||||||
if (pinIndex < m_node->Outputs.size())
|
if (pinIndex < m_node->Outputs.size())
|
||||||
|
|
|
||||||
|
|
@ -106,6 +106,7 @@ public:
|
||||||
virtual void Draw() = 0;
|
virtual void Draw() = 0;
|
||||||
virtual void DrawProperties() = 0;
|
virtual void DrawProperties() = 0;
|
||||||
|
|
||||||
|
void SetInputPinName(int pinIndex, const std::string &name);
|
||||||
void SetOutPinName(int pinIndex, const std::string &name);
|
void SetOutPinName(int pinIndex, const std::string &name);
|
||||||
|
|
||||||
void FrameStart();
|
void FrameStart();
|
||||||
|
|
@ -190,9 +191,9 @@ public:
|
||||||
return found;
|
return found;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void AddInputs(int num = 1);
|
||||||
void AddInput();
|
|
||||||
void AddOutputs(int num = 1);
|
void AddOutputs(int num = 1);
|
||||||
|
void SetInputs(uint32_t num);
|
||||||
void SetOutputs(uint32_t num);
|
void SetOutputs(uint32_t num);
|
||||||
void DeleteOutput();
|
void DeleteOutput();
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -12,7 +12,7 @@ FunctionNodeWidget::FunctionNodeWidget(IStoryManager &manager, std::shared_ptr<B
|
||||||
, m_manager(manager)
|
, m_manager(manager)
|
||||||
{
|
{
|
||||||
// Create defaut one input and one output
|
// Create defaut one input and one output
|
||||||
AddInput();
|
AddInputs(1);
|
||||||
AddOutputs(2);
|
AddOutputs(2);
|
||||||
SetOutPinName(0, "Success");
|
SetOutPinName(0, "Success");
|
||||||
SetOutPinName(1, "Failure");
|
SetOutPinName(1, "Failure");
|
||||||
|
|
|
||||||
|
|
@ -12,6 +12,8 @@
|
||||||
#include "media_node_widget.h"
|
#include "media_node_widget.h"
|
||||||
#include "function_node_widget.h"
|
#include "function_node_widget.h"
|
||||||
#include "variable_node_widget.h"
|
#include "variable_node_widget.h"
|
||||||
|
#include "operator_node_widget.h"
|
||||||
|
#include "print_node_widget.h"
|
||||||
#include "gui.h"
|
#include "gui.h"
|
||||||
#include "uuid.h"
|
#include "uuid.h"
|
||||||
|
|
||||||
|
|
@ -29,8 +31,10 @@ NodeEditorWindow::NodeEditorWindow(IStoryManager &manager)
|
||||||
{
|
{
|
||||||
|
|
||||||
// registerNode<MediaNodeWidget>("media-node");
|
// registerNode<MediaNodeWidget>("media-node");
|
||||||
|
registerNode<OperatorNodeWidget>("operator-node");
|
||||||
registerNode<FunctionNodeWidget>("function-node");
|
registerNode<FunctionNodeWidget>("function-node");
|
||||||
registerNode<VariableNodeWidget>("variable-node");
|
registerNode<VariableNodeWidget>("variable-node");
|
||||||
|
registerNode<PrintNodeWidget>("print-node");
|
||||||
}
|
}
|
||||||
|
|
||||||
NodeEditorWindow::~NodeEditorWindow()
|
NodeEditorWindow::~NodeEditorWindow()
|
||||||
|
|
|
||||||
81
story-editor/src/node_editor/operator_node_widget.cpp
Normal file
81
story-editor/src/node_editor/operator_node_widget.cpp
Normal file
|
|
@ -0,0 +1,81 @@
|
||||||
|
|
||||||
|
#include <sstream>
|
||||||
|
#include "operator_node_widget.h"
|
||||||
|
|
||||||
|
namespace ed = ax::NodeEditor;
|
||||||
|
#include "IconsMaterialDesignIcons.h"
|
||||||
|
#include "story_project.h"
|
||||||
|
#include "uuid.h"
|
||||||
|
|
||||||
|
OperatorNodeWidget::OperatorNodeWidget(IStoryManager &manager, std::shared_ptr<BaseNode> node)
|
||||||
|
: BaseNodeWidget(manager, node)
|
||||||
|
, m_manager(manager)
|
||||||
|
{
|
||||||
|
m_opNode = std::dynamic_pointer_cast<OperatorNode>(node);
|
||||||
|
|
||||||
|
// Create defaut one input and one output
|
||||||
|
AddInputs(2);
|
||||||
|
SetInputPinName(0, "A");
|
||||||
|
SetInputPinName(1, "B");
|
||||||
|
AddOutputs(1);
|
||||||
|
SetOutPinName(0, "=");
|
||||||
|
}
|
||||||
|
|
||||||
|
void OperatorNodeWidget::Initialize()
|
||||||
|
{
|
||||||
|
BaseNodeWidget::Initialize();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void OperatorNodeWidget::DrawProperties()
|
||||||
|
{
|
||||||
|
ImGui::AlignTextToFramePadding();
|
||||||
|
static ImGuiComboFlags flags = 0;
|
||||||
|
|
||||||
|
if (ImGui::BeginCombo("Operators", m_selectedOperatorSymbol.c_str(), flags))
|
||||||
|
{
|
||||||
|
int i = 0;
|
||||||
|
|
||||||
|
for (auto& op : m_opNode->GetOperators())
|
||||||
|
{
|
||||||
|
// ImGui::PushID(static_cast<int>(i)); // Assure l'unicité des widgets
|
||||||
|
if (op.first == m_selectedOperatorType)
|
||||||
|
{
|
||||||
|
m_selectedIndex = i;
|
||||||
|
}
|
||||||
|
|
||||||
|
const bool is_selected = (m_selectedIndex == i);
|
||||||
|
|
||||||
|
if (ImGui::Selectable(op.second.symbol.c_str(), is_selected))
|
||||||
|
{
|
||||||
|
m_selectedIndex = i;
|
||||||
|
m_selectedOperatorSymbol = op.second.symbol;
|
||||||
|
m_opNode->SetOperationType(op.first);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set the initial focus when opening the combo (scrolling + keyboard navigation focus)
|
||||||
|
if (is_selected)
|
||||||
|
{
|
||||||
|
ImGui::SetItemDefaultFocus();
|
||||||
|
}
|
||||||
|
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
ImGui::EndCombo();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void OperatorNodeWidget::Draw()
|
||||||
|
{
|
||||||
|
BaseNodeWidget::FrameStart();
|
||||||
|
|
||||||
|
ImGui::TextUnformatted(m_selectedOperatorSymbol.c_str());
|
||||||
|
|
||||||
|
DrawPins();
|
||||||
|
|
||||||
|
BaseNodeWidget::FrameEnd();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
32
story-editor/src/node_editor/operator_node_widget.h
Normal file
32
story-editor/src/node_editor/operator_node_widget.h
Normal file
|
|
@ -0,0 +1,32 @@
|
||||||
|
#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 "operator_node.h"
|
||||||
|
#include <imgui_node_editor.h>
|
||||||
|
#include "media_node.h"
|
||||||
|
|
||||||
|
class OperatorNodeWidget : public BaseNodeWidget
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
OperatorNodeWidget(IStoryManager &manager, std::shared_ptr<BaseNode> node);
|
||||||
|
|
||||||
|
void Draw() override;
|
||||||
|
|
||||||
|
virtual void DrawProperties() override;
|
||||||
|
virtual void Initialize() override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
IStoryManager &m_manager;
|
||||||
|
std::shared_ptr<OperatorNode> m_opNode;
|
||||||
|
int m_selectedIndex{-1};
|
||||||
|
OperatorNode::OperationType m_selectedOperatorType{OperatorNode::OperationType::ADD};
|
||||||
|
std::string m_selectedOperatorSymbol{"+"};
|
||||||
|
};
|
||||||
56
story-editor/src/node_editor/print_node_widget.cpp
Normal file
56
story-editor/src/node_editor/print_node_widget.cpp
Normal file
|
|
@ -0,0 +1,56 @@
|
||||||
|
|
||||||
|
#include <sstream>
|
||||||
|
#include "print_node_widget.h"
|
||||||
|
|
||||||
|
namespace ed = ax::NodeEditor;
|
||||||
|
#include "IconsMaterialDesignIcons.h"
|
||||||
|
#include "story_project.h"
|
||||||
|
#include "uuid.h"
|
||||||
|
|
||||||
|
char PrintNodeWidget::m_buffer[PrintNodeWidget::MAX_PRINT_SIZE] = {0};
|
||||||
|
|
||||||
|
PrintNodeWidget::PrintNodeWidget(IStoryManager &manager, std::shared_ptr<BaseNode> node)
|
||||||
|
: BaseNodeWidget(manager, node)
|
||||||
|
, m_manager(manager)
|
||||||
|
{
|
||||||
|
m_printNode = std::dynamic_pointer_cast<PrintNode>(node);
|
||||||
|
// Create defaut one input and one output
|
||||||
|
AddInputs(1);
|
||||||
|
SetInputPinName(0, "");
|
||||||
|
AddOutputs(1);
|
||||||
|
SetOutPinName(0, "");
|
||||||
|
}
|
||||||
|
|
||||||
|
void PrintNodeWidget::Initialize()
|
||||||
|
{
|
||||||
|
BaseNodeWidget::Initialize();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void PrintNodeWidget::DrawProperties()
|
||||||
|
{
|
||||||
|
ImGui::AlignTextToFramePadding();
|
||||||
|
|
||||||
|
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)
|
||||||
|
{
|
||||||
|
m_printNode->SetText(m_buffer);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void PrintNodeWidget::Draw()
|
||||||
|
{
|
||||||
|
BaseNodeWidget::FrameStart();
|
||||||
|
|
||||||
|
DrawPins();
|
||||||
|
|
||||||
|
BaseNodeWidget::FrameEnd();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
33
story-editor/src/node_editor/print_node_widget.h
Normal file
33
story-editor/src/node_editor/print_node_widget.h
Normal file
|
|
@ -0,0 +1,33 @@
|
||||||
|
#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 "print_node.h"
|
||||||
|
#include <imgui_node_editor.h>
|
||||||
|
#include "media_node.h"
|
||||||
|
|
||||||
|
class PrintNodeWidget : public BaseNodeWidget
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
static const int MAX_PRINT_SIZE = 128;
|
||||||
|
PrintNodeWidget(IStoryManager &manager, std::shared_ptr<BaseNode> node);
|
||||||
|
|
||||||
|
void Draw() override;
|
||||||
|
|
||||||
|
virtual void DrawProperties() override;
|
||||||
|
virtual void Initialize() override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
IStoryManager &m_manager;
|
||||||
|
std::shared_ptr<PrintNode> m_printNode;
|
||||||
|
|
||||||
|
static char m_buffer[MAX_PRINT_SIZE];
|
||||||
|
};
|
||||||
|
|
@ -11,6 +11,7 @@ VariableNodeWidget::VariableNodeWidget(IStoryManager &manager, std::shared_ptr<B
|
||||||
: BaseNodeWidget(manager, node)
|
: BaseNodeWidget(manager, node)
|
||||||
, m_manager(manager)
|
, m_manager(manager)
|
||||||
{
|
{
|
||||||
|
m_variableNode = std::dynamic_pointer_cast<VariableNode>(node);
|
||||||
// Create defaut one input and one output
|
// Create defaut one input and one output
|
||||||
//AddInput();
|
//AddInput();
|
||||||
AddOutputs(1);
|
AddOutputs(1);
|
||||||
|
|
@ -42,6 +43,7 @@ void VariableNodeWidget::DrawProperties()
|
||||||
{
|
{
|
||||||
m_selectedIndex = i;
|
m_selectedIndex = i;
|
||||||
m_selectedVariable = l;
|
m_selectedVariable = l;
|
||||||
|
m_variableNode->SetVariable(var);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set the initial focus when opening the combo (scrolling + keyboard navigation focus)
|
// Set the initial focus when opening the combo (scrolling + keyboard navigation focus)
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue