mirror of
https://github.com/arabine/open-story-teller.git
synced 2025-12-06 17:09:06 +01:00
Add function node with sub editor
This commit is contained in:
parent
cd26f407fc
commit
f0ffb62867
21 changed files with 662 additions and 218 deletions
6
.github/workflows/story_editor.yml
vendored
6
.github/workflows/story_editor.yml
vendored
|
|
@ -24,11 +24,13 @@ jobs:
|
|||
mkdir build
|
||||
cd build
|
||||
cmake -DCMAKE_BUILD_TYPE=Release ..
|
||||
make
|
||||
ls
|
||||
- name: package_setup
|
||||
working-directory: ./story-editor/build
|
||||
run : |
|
||||
make package
|
||||
cpack
|
||||
cpack -G DEB
|
||||
ls
|
||||
build_win32:
|
||||
runs-on: ubuntu-latest
|
||||
|
|
@ -39,4 +41,4 @@ jobs:
|
|||
- name: build
|
||||
working-directory: ./story-editor
|
||||
run : |
|
||||
./build_win32.sh
|
||||
./build_win32.sh
|
||||
|
|
|
|||
95
.vscode/settings.json
vendored
95
.vscode/settings.json
vendored
|
|
@ -6,11 +6,102 @@
|
|||
"${workspaceFolder}/software"
|
||||
],
|
||||
"files.associations": {
|
||||
"*.css": "tailwindcss",
|
||||
"**/frontmatter.json": "jsonc",
|
||||
"**/.frontmatter/config/*.json": "jsonc",
|
||||
"*.css": "tailwindcss",
|
||||
"pico_i2s.pio.h": "c",
|
||||
"pico_i2s.h": "c"
|
||||
"pico_i2s.h": "c",
|
||||
"cctype": "cpp",
|
||||
"cmath": "cpp",
|
||||
"cstddef": "cpp",
|
||||
"cstdio": "cpp",
|
||||
"cstdlib": "cpp",
|
||||
"cstring": "cpp",
|
||||
"ctime": "cpp",
|
||||
"array": "cpp",
|
||||
"atomic": "cpp",
|
||||
"*.tcc": "cpp",
|
||||
"chrono": "cpp",
|
||||
"cstdint": "cpp",
|
||||
"list": "cpp",
|
||||
"map": "cpp",
|
||||
"set": "cpp",
|
||||
"string": "cpp",
|
||||
"unordered_map": "cpp",
|
||||
"vector": "cpp",
|
||||
"exception": "cpp",
|
||||
"algorithm": "cpp",
|
||||
"functional": "cpp",
|
||||
"iterator": "cpp",
|
||||
"memory": "cpp",
|
||||
"memory_resource": "cpp",
|
||||
"numeric": "cpp",
|
||||
"optional": "cpp",
|
||||
"random": "cpp",
|
||||
"ratio": "cpp",
|
||||
"regex": "cpp",
|
||||
"string_view": "cpp",
|
||||
"tuple": "cpp",
|
||||
"type_traits": "cpp",
|
||||
"utility": "cpp",
|
||||
"fstream": "cpp",
|
||||
"future": "cpp",
|
||||
"iomanip": "cpp",
|
||||
"iosfwd": "cpp",
|
||||
"iostream": "cpp",
|
||||
"istream": "cpp",
|
||||
"limits": "cpp",
|
||||
"mutex": "cpp",
|
||||
"ostream": "cpp",
|
||||
"sstream": "cpp",
|
||||
"stdexcept": "cpp",
|
||||
"thread": "cpp",
|
||||
"variant": "cpp",
|
||||
"bitset": "cpp",
|
||||
"*.ipp": "cpp",
|
||||
"deque": "cpp",
|
||||
"forward_list": "cpp",
|
||||
"unordered_set": "cpp",
|
||||
"initializer_list": "cpp",
|
||||
"ranges": "cpp",
|
||||
"span": "cpp",
|
||||
"valarray": "cpp",
|
||||
"format": "cpp",
|
||||
"samd21.h": "c",
|
||||
"ost_hal.h": "c",
|
||||
"debug.h": "c",
|
||||
"numbers": "cpp",
|
||||
"qtconcurrentdepends": "cpp",
|
||||
"qtcoredepends": "cpp",
|
||||
"qtguidepends": "cpp",
|
||||
"qtnetworkdepends": "cpp",
|
||||
"qtopengldepends": "cpp",
|
||||
"qtqmldepends": "cpp",
|
||||
"qtwidgetsdepends": "cpp",
|
||||
"complex": "cpp",
|
||||
"system_error": "cpp",
|
||||
"typeindex": "cpp",
|
||||
"typeinfo": "cpp",
|
||||
"compare": "cpp",
|
||||
"any": "cpp",
|
||||
"filesystem": "cpp",
|
||||
"stdbool.h": "c",
|
||||
"bit": "cpp",
|
||||
"charconv": "cpp",
|
||||
"cinttypes": "cpp",
|
||||
"clocale": "cpp",
|
||||
"codecvt": "cpp",
|
||||
"concepts": "cpp",
|
||||
"condition_variable": "cpp",
|
||||
"cstdarg": "cpp",
|
||||
"cwchar": "cpp",
|
||||
"cwctype": "cpp",
|
||||
"new": "cpp",
|
||||
"semaphore": "cpp",
|
||||
"shared_mutex": "cpp",
|
||||
"stop_token": "cpp",
|
||||
"streambuf": "cpp",
|
||||
"cfenv": "cpp"
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -8,12 +8,14 @@
|
|||
#include "story_project.h"
|
||||
#include "json.hpp"
|
||||
#include "media_node.h"
|
||||
#include "function_node.h"
|
||||
#include "sys_lib.h"
|
||||
|
||||
StoryProject::StoryProject(ILogger &log)
|
||||
: m_log(log)
|
||||
{
|
||||
registerNode<MediaNode>("media-node");
|
||||
registerNode<FunctionNode>("function-node");
|
||||
}
|
||||
|
||||
StoryProject::~StoryProject()
|
||||
|
|
|
|||
|
|
@ -49,8 +49,6 @@ struct StoryProject : public IStoryProject
|
|||
{
|
||||
|
||||
public:
|
||||
|
||||
|
||||
StoryProject(ILogger &log);
|
||||
~StoryProject();
|
||||
|
||||
|
|
@ -142,6 +140,12 @@ public:
|
|||
void AddConnection(std::shared_ptr<Connection> c);
|
||||
void DeleteNode(const std::string &id);
|
||||
void DeleteLink(std::shared_ptr<Connection> c);
|
||||
|
||||
std::vector<std::string> GetNodeTypes() const {
|
||||
std::vector<std::string> l;
|
||||
for(auto const& imap: m_registry) l.push_back(imap.first);
|
||||
return l;
|
||||
}
|
||||
|
||||
private:
|
||||
ILogger &m_log;
|
||||
|
|
|
|||
|
|
@ -157,7 +157,7 @@ FetchContent_Declare(
|
|||
|
||||
|
||||
set(SDL3IMAGE_INSTALL OFF)
|
||||
set(BUILD_SHARED_LIBS FALSE)
|
||||
set(BUILD_SHARED_LIBS TRUE)
|
||||
FetchContent_MakeAvailable(sdl_image)
|
||||
include_directories(${sdl_image_SOURCE_DIR}/include)
|
||||
|
||||
|
|
@ -191,6 +191,8 @@ set(SRCS
|
|||
src/node_engine/base_node.cpp
|
||||
src/node_engine/media_node.h
|
||||
src/node_engine/media_node.cpp
|
||||
src/node_engine/function_node.h
|
||||
src/node_engine/function_node.cpp
|
||||
src/node_engine/connection.cpp
|
||||
src/node_engine/connection.h
|
||||
|
||||
|
|
@ -200,6 +202,8 @@ set(SRCS
|
|||
src/node_editor/base_node_widget.cpp
|
||||
src/node_editor/node_editor_window.h
|
||||
src/node_editor/node_editor_window.cpp
|
||||
src/node_editor/function_node_widget.h
|
||||
src/node_editor/function_node_widget.cpp
|
||||
|
||||
src/resources_window.cpp
|
||||
src/resources_window.h
|
||||
|
|
@ -340,6 +344,7 @@ target_link_directories(${STORY_EDITOR_PROJECT} PUBLIC ${sdl3_BINARY_DIR} ${curl
|
|||
# certaines informations à CPACK
|
||||
set(SDL_BIN_DIR ${sdl3_BINARY_DIR})
|
||||
set(SDL_IMAGE_BIN_DIR ${sdl_image_BINARY_DIR})
|
||||
set(SDL_MIXER_BIN_DIR ${sdl3_mixer_BINARY_DIR})
|
||||
|
||||
if(UNIX)
|
||||
target_link_libraries(${STORY_EDITOR_PROJECT}
|
||||
|
|
@ -357,6 +362,7 @@ elseif(WIN32)
|
|||
OpenGL::GL
|
||||
SDL3::SDL3
|
||||
SDL3_image::SDL3_image
|
||||
SDL3_mixer::SDL3_mixer
|
||||
libcurl_static
|
||||
ws2_32.lib psapi.lib setupapi.lib cfgmgr32.lib advapi32.lib
|
||||
)
|
||||
|
|
@ -369,6 +375,7 @@ install(TARGETS ${STORY_EDITOR_PROJECT} RUNTIME DESTINATION ".")
|
|||
|
||||
# Personnaliser les options d'installation
|
||||
set(CPACK_PACKAGE_NAME "Open-Story-Editor")
|
||||
set(CPACK_DEBIAN_PACKAGE_MAINTAINER "Anthony Rabine")
|
||||
set(CPACK_PACKAGE_DESCRIPTION "Open Story Teller - Node based editor")
|
||||
set(CPACK_PACKAGE_VENDOR "D8S")
|
||||
set(CPACK_PACKAGE_VERSION_MAJOR "${PROJECT_VERSION_MAJOR}")
|
||||
|
|
@ -384,6 +391,8 @@ install_files("." FILES "${CMAKE_SOURCE_DIR}/tools/imgui.ini")
|
|||
|
||||
if(WIN32)
|
||||
install_files("." FILES "${SDL_BIN_DIR}/SDL3.dll")
|
||||
install_files("." FILES "${SDL_IMAGE_BIN_DIR}/SDL3_image.dll")
|
||||
install_files("." FILES "${SDL_MIXER_BIN_DIR}/SDL3_mixer.dll")
|
||||
install_files("." FILES "/usr/lib/gcc/x86_64-w64-mingw32/10-posix/libstdc++-6.dll")
|
||||
install_files("." FILES "/usr/x86_64-w64-mingw32/lib/libwinpthread-1.dll")
|
||||
install_files("." FILES "/usr/lib/gcc/x86_64-w64-mingw32/10-posix/libgcc_s_seh-1.dll")
|
||||
|
|
@ -393,9 +402,10 @@ if(WIN32)
|
|||
endif()
|
||||
|
||||
if(LINUX)
|
||||
install_files("." FILES "${SDL_BIN_DIR}/SDL3.so")
|
||||
install_files("." FILES "${SDL_IMAGE_BIN_DIR}/SDL3_image.so")
|
||||
|
||||
|
||||
install_files("." FILES "${SDL_BIN_DIR}/libSDL3.so")
|
||||
install_files("." FILES "${SDL_IMAGE_BIN_DIR}/libSDL3_image.so")
|
||||
install_files("." FILES "${SDL_MIXER_BIN_DIR}/libSDL3_mixer.so")
|
||||
endif()
|
||||
|
||||
if (APPLE)
|
||||
|
|
|
|||
|
|
@ -36,6 +36,7 @@ public:
|
|||
virtual void Log(const std::string &txt, bool critical = false) = 0;
|
||||
virtual void PlaySoundFile(const std::string &fileName) = 0;
|
||||
virtual std::string BuildFullAssetsPath(const std::string_view fileName) const = 0;
|
||||
virtual void OpenFunction(const std::string &uuid, const std::string &name) = 0;
|
||||
|
||||
// Resources management
|
||||
virtual std::pair<FilterIterator, FilterIterator> Images() = 0;
|
||||
|
|
|
|||
|
|
@ -822,7 +822,7 @@ void MainWindow::CloseProject()
|
|||
|
||||
m_resources.Clear();
|
||||
|
||||
m_nodeEditorWindow.Clear();
|
||||
m_nodeEditorWindow.Initialize();
|
||||
m_emulatorWindow.ClearImage();
|
||||
m_consoleWindow.ClearLog();
|
||||
m_codeEditorWindow.ClearErrors();
|
||||
|
|
@ -980,6 +980,11 @@ std::pair<FilterIterator, FilterIterator> MainWindow::Sounds()
|
|||
return m_resources.Sounds();
|
||||
}
|
||||
|
||||
void MainWindow::OpenFunction(const std::string &uuid, const std::string &name)
|
||||
{
|
||||
m_nodeEditorWindow.OpenFunction(uuid, name);
|
||||
}
|
||||
|
||||
void MainWindow::AddResource(std::shared_ptr<Resource> res)
|
||||
{
|
||||
m_resources.Add(res);
|
||||
|
|
|
|||
|
|
@ -130,6 +130,7 @@ private:
|
|||
virtual std::string BuildFullAssetsPath(const std::string_view fileName) const override;
|
||||
virtual std::pair<FilterIterator, FilterIterator> Images() override;
|
||||
virtual std::pair<FilterIterator, FilterIterator> Sounds() override;
|
||||
virtual void OpenFunction(const std::string &uuid, const std::string &name) override;
|
||||
|
||||
virtual void AddResource(std::shared_ptr<Resource> res) override;
|
||||
virtual void ClearResources() override;
|
||||
|
|
|
|||
|
|
@ -17,6 +17,7 @@
|
|||
#define DR_MP3_IMPLEMENTATION
|
||||
#include "dr_mp3.h"
|
||||
|
||||
#define QOI_IMPLEMENTATION
|
||||
#include "qoi.h"
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@ BaseNodeWidget::BaseNodeWidget(IStoryManager &manager, std::shared_ptr<BaseNode
|
|||
: m_manager(manager)
|
||||
, m_base(base)
|
||||
{
|
||||
// A node is specific to the Node Gfx library
|
||||
m_node = std::make_unique<Node>(GetNextId(), ""); // ImGui internal ID
|
||||
std::cout << " --> Created node widget: " << (int)m_node->ID.Get() << std::endl;
|
||||
}
|
||||
|
|
@ -58,6 +59,13 @@ void BaseNodeWidget::Initialize()
|
|||
|
||||
}
|
||||
|
||||
void BaseNodeWidget::SetOutPinName(int pinIndex, const std::string &name)
|
||||
{
|
||||
if (pinIndex < m_node->Outputs.size())
|
||||
{
|
||||
m_node->Outputs[pinIndex].Name = name;
|
||||
}
|
||||
}
|
||||
|
||||
void BaseNodeWidget::FrameStart()
|
||||
{
|
||||
|
|
@ -107,7 +115,14 @@ void BaseNodeWidget::DrawPins()
|
|||
ImGui::Dummy(ImVec2(320 - textWidth * 2, 0)); // Hacky magic number to space out the output pin.
|
||||
ImGui::SameLine();
|
||||
ed::BeginPin(output.ID, ed::PinKind::Output);
|
||||
ImGui::Text( "#%d " ICON_MDI_OCTAGON_OUTLINE, i++);
|
||||
if (output.Name.empty())
|
||||
{
|
||||
ImGui::Text( "#%d " ICON_MDI_OCTAGON_OUTLINE, i++);
|
||||
}
|
||||
else
|
||||
{
|
||||
ImGui::Text( "%s" ICON_MDI_OCTAGON_OUTLINE, output.Name.c_str() );
|
||||
}
|
||||
ed::EndPin();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -106,6 +106,7 @@ public:
|
|||
virtual void Draw() = 0;
|
||||
virtual void DrawProperties() = 0;
|
||||
|
||||
void SetOutPinName(int pinIndex, const std::string &name);
|
||||
|
||||
void FrameStart();
|
||||
void FrameEnd();
|
||||
|
|
|
|||
51
story-editor/src/node_editor/function_node_widget.cpp
Normal file
51
story-editor/src/node_editor/function_node_widget.cpp
Normal file
|
|
@ -0,0 +1,51 @@
|
|||
|
||||
#include <sstream>
|
||||
#include "function_node_widget.h"
|
||||
|
||||
namespace ed = ax::NodeEditor;
|
||||
#include "IconsMaterialDesignIcons.h"
|
||||
#include "story_project.h"
|
||||
#include "uuid.h"
|
||||
|
||||
FunctionNodeWidget::FunctionNodeWidget(IStoryManager &manager, std::shared_ptr<BaseNode> node)
|
||||
: BaseNodeWidget(manager, node)
|
||||
, m_manager(manager)
|
||||
{
|
||||
// Create defaut one input and one output
|
||||
AddInput();
|
||||
AddOutputs(2);
|
||||
SetOutPinName(0, "Success");
|
||||
SetOutPinName(1, "Failure");
|
||||
m_functionUuid = Uuid().String();
|
||||
}
|
||||
|
||||
void FunctionNodeWidget::Draw()
|
||||
{
|
||||
BaseNodeWidget::FrameStart();
|
||||
|
||||
ImGui::TextUnformatted(m_functionName.c_str());
|
||||
if (ImGui::Button("> Open function"))
|
||||
{
|
||||
m_manager.OpenFunction(m_functionUuid, m_functionName);
|
||||
}
|
||||
|
||||
DrawPins();
|
||||
|
||||
BaseNodeWidget::FrameEnd();
|
||||
|
||||
}
|
||||
|
||||
void FunctionNodeWidget::Initialize()
|
||||
{
|
||||
BaseNodeWidget::Initialize();
|
||||
m_functionName = "Function";
|
||||
}
|
||||
|
||||
void FunctionNodeWidget::DrawProperties()
|
||||
{
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
29
story-editor/src/node_editor/function_node_widget.h
Normal file
29
story-editor/src/node_editor/function_node_widget.h
Normal file
|
|
@ -0,0 +1,29 @@
|
|||
#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 <imgui_node_editor.h>
|
||||
#include "media_node.h"
|
||||
|
||||
class FunctionNodeWidget : public BaseNodeWidget
|
||||
{
|
||||
public:
|
||||
FunctionNodeWidget(IStoryManager &manager, std::shared_ptr<BaseNode> node);
|
||||
|
||||
void Draw() override;
|
||||
|
||||
virtual void DrawProperties() override;
|
||||
virtual void Initialize() override;
|
||||
|
||||
private:
|
||||
IStoryManager &m_manager;
|
||||
std::string m_functionName;
|
||||
std::string m_functionUuid;
|
||||
};
|
||||
222
story-editor/src/node_editor/node_editor_page.h
Normal file
222
story-editor/src/node_editor/node_editor_page.h
Normal file
|
|
@ -0,0 +1,222 @@
|
|||
#pragma once
|
||||
|
||||
#include <map>
|
||||
#include <set>
|
||||
#include <list>
|
||||
#include <utility>
|
||||
|
||||
#include <imgui_node_editor.h>
|
||||
#include "base_node_widget.h"
|
||||
|
||||
namespace ed = ax::NodeEditor;
|
||||
|
||||
struct EditorLink {
|
||||
ed::LinkId Id;
|
||||
ed::PinId InputId;
|
||||
ed::PinId OutputId;
|
||||
};
|
||||
|
||||
// Stuff from ImGuiNodeEditor, each element has a unique ID within one editor
|
||||
struct LinkInfo
|
||||
{
|
||||
|
||||
LinkInfo()
|
||||
{
|
||||
ed_link = std::make_shared<EditorLink>();
|
||||
model = std::make_shared<Connection>();
|
||||
}
|
||||
|
||||
std::shared_ptr<EditorLink> ed_link;
|
||||
std::shared_ptr<Connection> model;
|
||||
};
|
||||
|
||||
|
||||
struct NodeEditorPage {
|
||||
ed::Config config;
|
||||
ed::EditorContext* EditorContext;
|
||||
std::list<std::shared_ptr<BaseNodeWidget>> m_nodes;
|
||||
std::list<std::shared_ptr<LinkInfo>> m_links; // List of live links. It is dynamic unless you want to create read-only view over nodes.
|
||||
|
||||
NodeEditorPage(const std::string &uuid, const std::string &name)
|
||||
: m_uuid(uuid)
|
||||
, m_name(name)
|
||||
{
|
||||
config.SettingsFile = nullptr;
|
||||
config.SaveSettings = nullptr;
|
||||
config.LoadSettings = nullptr;
|
||||
EditorContext = ed::CreateEditor(&config);
|
||||
}
|
||||
|
||||
std::string_view Name() const {
|
||||
return m_name;
|
||||
}
|
||||
|
||||
std::string_view Uuid() const {
|
||||
return m_uuid;
|
||||
}
|
||||
|
||||
~NodeEditorPage() {
|
||||
ed::DestroyEditor(EditorContext);
|
||||
Clear();
|
||||
}
|
||||
|
||||
void Select()
|
||||
{
|
||||
ed::SetCurrentEditor(EditorContext);
|
||||
}
|
||||
|
||||
void Draw() {
|
||||
for (const auto & n : m_nodes)
|
||||
{
|
||||
ImGui::PushID(n->GetInternalId());
|
||||
n->Draw();
|
||||
ImGui::PopID();
|
||||
}
|
||||
|
||||
for (const auto& linkInfo : m_links)
|
||||
{
|
||||
ed::Link(linkInfo->ed_link->Id, linkInfo->ed_link->OutputId, linkInfo->ed_link->InputId);
|
||||
}
|
||||
}
|
||||
|
||||
bool GetNode(const ed::NodeId &nodeId, std::shared_ptr<BaseNodeWidget> &node) {
|
||||
for (const auto & n : m_nodes)
|
||||
{
|
||||
if (n->GetInternalId() == nodeId.Get())
|
||||
{
|
||||
node = n;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void DeleteNode(const ed::NodeId &nodeId) {
|
||||
m_nodes.remove_if([nodeId](const std::shared_ptr<BaseNodeWidget>& node) {
|
||||
return node->GetInternalId() == nodeId.Get();
|
||||
});
|
||||
}
|
||||
|
||||
std::shared_ptr<BaseNodeWidget> GetSelectedNode() {
|
||||
|
||||
std::shared_ptr<BaseNodeWidget> selected;
|
||||
|
||||
if (ed::GetSelectedObjectCount() > 0)
|
||||
{
|
||||
ed::NodeId nId;
|
||||
int nodeCount = ed::GetSelectedNodes(&nId, 1);
|
||||
|
||||
if (nodeCount > 0)
|
||||
{
|
||||
for (auto & n : m_nodes)
|
||||
{
|
||||
if (n->GetInternalId() == nId.Get())
|
||||
{
|
||||
selected = n;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return selected;
|
||||
}
|
||||
|
||||
void AddNode(std::shared_ptr<BaseNodeWidget> node) {
|
||||
m_nodes.push_back(node);
|
||||
}
|
||||
|
||||
void Clear() {
|
||||
m_nodes.clear();
|
||||
m_links.clear();
|
||||
}
|
||||
|
||||
bool GetModel(ed::LinkId linkId, std::shared_ptr<Connection> &model) {
|
||||
for (const auto& linkInfo : m_links)
|
||||
{
|
||||
if (linkInfo->ed_link->Id == linkId)
|
||||
{
|
||||
model = linkInfo->model;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void EraseLink(ed::LinkId linkId) {
|
||||
m_links.remove_if([linkId](const std::shared_ptr<LinkInfo>& linkInfo) {
|
||||
return linkInfo->ed_link->Id == linkId;
|
||||
});
|
||||
}
|
||||
|
||||
// retourne 1 si c'est une sortie, 2 une entrée, 0 pas trouvé
|
||||
int FindNodeAndPin(ed::PinId pinId, int &foundIndex, std::string &foundNodeId)
|
||||
{
|
||||
int success = 0;
|
||||
for (const auto & n : m_nodes)
|
||||
{
|
||||
// std::cout << "---> Node: " << n->Base()->GetId() << std::endl;
|
||||
|
||||
if (n->HasOnputPinId(pinId, foundIndex))
|
||||
{
|
||||
foundNodeId = n->Base()->GetId();
|
||||
success = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
if (n->HasInputPinId(pinId, foundIndex))
|
||||
{
|
||||
foundNodeId = n->Base()->GetId();
|
||||
success = 2;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
ed::PinId GetInputPin(const std::string &modelNodeId, int pinIndex)
|
||||
{
|
||||
ed::PinId id = 0;
|
||||
|
||||
for (auto & n : m_nodes)
|
||||
{
|
||||
if (n->Base()->GetId() == modelNodeId)
|
||||
{
|
||||
id = n->GetInputPinAt(pinIndex);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (id.Get() == 0)
|
||||
{
|
||||
std::cout << "Invalid Id: " << modelNodeId << " input pin: " << pinIndex <<" not found" << std::endl;
|
||||
}
|
||||
|
||||
return id;
|
||||
}
|
||||
|
||||
ed::PinId GetOutputPin(const std::string &modelNodeId, int pinIndex)
|
||||
{
|
||||
ed::PinId id = 0;
|
||||
|
||||
for (auto & n : m_nodes)
|
||||
{
|
||||
if (n->Base()->GetId() == modelNodeId)
|
||||
{
|
||||
id = n->GetOutputPinAt(pinIndex);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (id.Get() == 0)
|
||||
{
|
||||
std::cout << "Invalid Id: " << modelNodeId << " output pin: " << pinIndex <<" not found" << std::endl;
|
||||
}
|
||||
|
||||
return id;
|
||||
}
|
||||
|
||||
private:
|
||||
std::string m_uuid;
|
||||
std::string m_name;
|
||||
|
||||
};
|
||||
|
|
@ -10,6 +10,7 @@
|
|||
#include "IconsFontAwesome5_c.h"
|
||||
|
||||
#include "media_node_widget.h"
|
||||
#include "function_node_widget.h"
|
||||
#include "gui.h"
|
||||
#include "uuid.h"
|
||||
|
||||
|
|
@ -27,71 +28,62 @@ NodeEditorWindow::NodeEditorWindow(IStoryManager &manager)
|
|||
{
|
||||
|
||||
registerNode<MediaNodeWidget>("media-node");
|
||||
registerNode<FunctionNodeWidget>("function-node");
|
||||
}
|
||||
|
||||
NodeEditorWindow::~NodeEditorWindow()
|
||||
{
|
||||
ed::DestroyEditor(m_context);
|
||||
m_pages.clear();
|
||||
m_story.reset();
|
||||
}
|
||||
|
||||
static const std::string gMainUuid = "490745ab-df4d-476d-ae27-027e94b8ee0a";
|
||||
|
||||
void NodeEditorWindow::Initialize()
|
||||
{
|
||||
ed::Config config;
|
||||
config.SettingsFile = nullptr;
|
||||
config.SaveSettings = nullptr;
|
||||
config.LoadSettings = nullptr;
|
||||
m_context = ed::CreateEditor(&config);
|
||||
m_pages.clear();
|
||||
m_callStack.clear();
|
||||
|
||||
ed::SetCurrentEditor(m_context);
|
||||
m_currentPage = std::make_shared<NodeEditorPage>(gMainUuid, "Main");
|
||||
m_pages.emplace_back(m_currentPage);
|
||||
|
||||
m_currentPage->Select();
|
||||
}
|
||||
|
||||
void NodeEditorWindow::Clear()
|
||||
void NodeEditorWindow::LoadPage(const std::string &uuid, const std::string &name)
|
||||
{
|
||||
m_nodes.clear();
|
||||
m_links.clear();
|
||||
m_story.reset();
|
||||
// On cherche la page correspondante dans la std::list
|
||||
// Si elle n'existe pas, c'est une nouvelle fonction
|
||||
auto it = std::find_if(m_pages.begin(), m_pages.end(), [uuid](std::shared_ptr<NodeEditorPage> p) { return p->Uuid() == uuid; });
|
||||
|
||||
std::shared_ptr<NodeEditorPage> page;
|
||||
|
||||
if (it == m_pages.end())
|
||||
{
|
||||
// New page
|
||||
page = std::make_shared<NodeEditorPage>(uuid, name);
|
||||
}
|
||||
else
|
||||
{
|
||||
page = *it;
|
||||
}
|
||||
|
||||
if (m_currentPage->Uuid() != uuid)
|
||||
{
|
||||
m_callStack.push_back(m_currentPage); // save where we are
|
||||
m_currentPage = page;
|
||||
m_currentPage->Select();
|
||||
}
|
||||
}
|
||||
|
||||
ed::PinId NodeEditorWindow::GetInputPin(const std::string &modelNodeId, int pinIndex)
|
||||
{
|
||||
ed::PinId id = 0;
|
||||
|
||||
for (auto & n : m_nodes)
|
||||
{
|
||||
if (n->Base()->GetId() == modelNodeId)
|
||||
{
|
||||
id = n->GetInputPinAt(pinIndex);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (id.Get() == 0)
|
||||
{
|
||||
std::cout << "Invalid Id: " << modelNodeId << " input pin: " << pinIndex <<" not found" << std::endl;
|
||||
}
|
||||
|
||||
return id;
|
||||
return m_currentPage->GetInputPin(modelNodeId, pinIndex);
|
||||
}
|
||||
|
||||
ed::PinId NodeEditorWindow::GetOutputPin(const std::string &modelNodeId, int pinIndex)
|
||||
{
|
||||
ed::PinId id = 0;
|
||||
|
||||
for (auto & n : m_nodes)
|
||||
{
|
||||
if (n->Base()->GetId() == modelNodeId)
|
||||
{
|
||||
id = n->GetOutputPinAt(pinIndex);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (id.Get() == 0)
|
||||
{
|
||||
std::cout << "Invalid Id: " << modelNodeId << " output pin: " << pinIndex <<" not found" << std::endl;
|
||||
}
|
||||
|
||||
return id;
|
||||
return m_currentPage->GetOutputPin(modelNodeId, pinIndex);
|
||||
}
|
||||
|
||||
void NodeEditorWindow::Load(std::shared_ptr<StoryProject> story)
|
||||
|
|
@ -103,8 +95,7 @@ void NodeEditorWindow::Load(std::shared_ptr<StoryProject> story)
|
|||
try {
|
||||
|
||||
BaseNodeWidget::InitId();
|
||||
m_nodes.clear();
|
||||
m_links.clear();
|
||||
Initialize();
|
||||
|
||||
auto [node_begin, node_end] = m_story->Nodes();
|
||||
|
||||
|
|
@ -117,7 +108,7 @@ void NodeEditorWindow::Load(std::shared_ptr<StoryProject> story)
|
|||
{
|
||||
n->Initialize();
|
||||
n->SetOutputs(m_story->OutputsCount((*it)->GetId())); // il faut que les noeuds aient une bonne taille de outputs avant de créer les liens
|
||||
m_nodes.push_back(n);
|
||||
m_currentPage->AddNode(n);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -143,7 +134,7 @@ void NodeEditorWindow::Load(std::shared_ptr<StoryProject> story)
|
|||
}
|
||||
}
|
||||
|
||||
std::cout << "Loaded " << m_nodes.size() << " nodes, " << m_links.size() << " links" << std::endl;
|
||||
std::cout << "Loaded " << m_currentPage->m_nodes.size() << " nodes, " << m_currentPage->m_links.size() << " links" << std::endl;
|
||||
|
||||
}
|
||||
|
||||
|
|
@ -152,6 +143,12 @@ void NodeEditorWindow::SaveNodePositions()
|
|||
|
||||
}
|
||||
|
||||
void NodeEditorWindow::OpenFunction(const std::string &uuid, const std::string &name)
|
||||
{
|
||||
m_newPageUuid = uuid;
|
||||
m_newPageName = name;
|
||||
}
|
||||
|
||||
void NodeEditorWindow::CreateLink(std::shared_ptr<Connection> model, ed::PinId inId, ed::PinId outId)
|
||||
{
|
||||
auto conn = std::make_shared<LinkInfo>();
|
||||
|
|
@ -164,41 +161,16 @@ void NodeEditorWindow::CreateLink(std::shared_ptr<Connection> model, ed::PinId i
|
|||
conn->ed_link->OutputId = outId;
|
||||
|
||||
// Since we accepted new link, lets add one to our list of links.
|
||||
m_links.push_back(conn);
|
||||
m_currentPage->m_links.push_back(conn);
|
||||
}
|
||||
|
||||
// retourne 1 si c'est une sortie, 2 une entrée, 0 pas trouvé
|
||||
int NodeEditorWindow::FindNodeAndPin(ed::PinId pinId, int &foundIndex, std::string &foundNodeId)
|
||||
{
|
||||
int success = 0;
|
||||
for (const auto & n : m_nodes)
|
||||
{
|
||||
// std::cout << "---> Node: " << n->Base()->GetId() << std::endl;
|
||||
|
||||
if (n->HasOnputPinId(pinId, foundIndex))
|
||||
{
|
||||
foundNodeId = n->Base()->GetId();
|
||||
success = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
if (n->HasInputPinId(pinId, foundIndex))
|
||||
{
|
||||
foundNodeId = n->Base()->GetId();
|
||||
success = 2;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
bool NodeEditorWindow::FillConnection(std::shared_ptr<Connection> c, ed::PinId pinId)
|
||||
{
|
||||
bool success = false;
|
||||
std::string nodeId;
|
||||
int nodeIndex;
|
||||
int ret = FindNodeAndPin(pinId, nodeIndex, nodeId);
|
||||
int ret = m_currentPage->FindNodeAndPin(pinId, nodeIndex, nodeId);
|
||||
if (ret > 0)
|
||||
{
|
||||
if (ret == 1)
|
||||
|
|
@ -216,53 +188,13 @@ bool NodeEditorWindow::FillConnection(std::shared_ptr<Connection> c, ed::PinId p
|
|||
return success;
|
||||
}
|
||||
|
||||
/*
|
||||
std::shared_ptr<Connection> NodeEditorWindow::LinkToModel(ed::PinId InputId, ed::PinId OutputId)
|
||||
{
|
||||
auto c = std::make_shared<Connection>();
|
||||
int foundIndex = -1;
|
||||
for (const auto & n : m_nodes)
|
||||
{
|
||||
// std::cout << "---> Node: " << n->Base()->GetId() << std::endl;
|
||||
|
||||
if (n->HasOnputPinId(OutputId, foundIndex))
|
||||
{
|
||||
c->outNodeId = n->Base()->GetId();
|
||||
c->outPortIndex = foundIndex;
|
||||
}
|
||||
|
||||
if (n->HasInputPinId(InputId, foundIndex))
|
||||
{
|
||||
c->inNodeId = n->Base()->GetId();
|
||||
c->inPortIndex = foundIndex;
|
||||
}
|
||||
}
|
||||
|
||||
return c;
|
||||
}*/
|
||||
|
||||
|
||||
std::shared_ptr<BaseNodeWidget> NodeEditorWindow::GetSelectedNode()
|
||||
{
|
||||
std::shared_ptr<BaseNodeWidget> selected;
|
||||
|
||||
ed::SetCurrentEditor(m_context);
|
||||
if (ed::GetSelectedObjectCount() > 0)
|
||||
{
|
||||
ed::NodeId nId;
|
||||
int nodeCount = ed::GetSelectedNodes(&nId, 1);
|
||||
|
||||
if (nodeCount > 0)
|
||||
{
|
||||
for (auto & n : m_nodes)
|
||||
{
|
||||
if (n->GetInternalId() == nId.Get())
|
||||
{
|
||||
selected = n;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
m_currentPage->Select();
|
||||
selected = m_currentPage->GetSelectedNode();
|
||||
ed::SetCurrentEditor(nullptr);
|
||||
|
||||
return selected;
|
||||
|
|
@ -271,24 +203,23 @@ std::shared_ptr<BaseNodeWidget> NodeEditorWindow::GetSelectedNode()
|
|||
|
||||
void NodeEditorWindow::Draw()
|
||||
{
|
||||
if (!m_newPageUuid.empty())
|
||||
{
|
||||
LoadPage(m_newPageUuid, m_newPageName);
|
||||
m_newPageUuid.clear();
|
||||
}
|
||||
|
||||
if (WindowBase::BeginDraw())
|
||||
{
|
||||
m_currentPage->Select();
|
||||
|
||||
ed::SetCurrentEditor(m_context);
|
||||
ed::Begin("My Editor", ImVec2(0.0, 0.0f));
|
||||
ToolbarUI();
|
||||
|
||||
ed::Begin(m_currentPage->Uuid().data(), ImVec2(0.0, 0.0f));
|
||||
|
||||
|
||||
for (const auto & n : m_nodes)
|
||||
{
|
||||
ImGui::PushID(n->GetInternalId());
|
||||
n->Draw();
|
||||
ImGui::PopID();
|
||||
}
|
||||
|
||||
for (const auto& linkInfo : m_links)
|
||||
{
|
||||
ed::Link(linkInfo->ed_link->Id, linkInfo->ed_link->OutputId, linkInfo->ed_link->InputId);
|
||||
}
|
||||
// Draw our nodes
|
||||
m_currentPage->Draw();
|
||||
|
||||
// Handle creation action, returns true if editor want to create new object (node or link)
|
||||
if (ed::BeginCreate())
|
||||
|
|
@ -325,7 +256,7 @@ void NodeEditorWindow::Draw()
|
|||
CreateLink(c, startId, endId);
|
||||
|
||||
// Draw new link.
|
||||
ed::Link(m_links.back()->ed_link->Id, startId, endId);
|
||||
ed::Link(m_currentPage->m_links.back()->ed_link->Id, startId, endId);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -347,17 +278,16 @@ void NodeEditorWindow::Draw()
|
|||
{
|
||||
if (ed::AcceptDeletedItem())
|
||||
{
|
||||
auto it = std::find_if(m_nodes.begin(), m_nodes.end(), [nodeId](std::shared_ptr<BaseNodeWidget> node) { return node->GetInternalId() == nodeId.Get(); });
|
||||
if (it != m_nodes.end())
|
||||
std::shared_ptr<BaseNodeWidget> node;
|
||||
if (m_currentPage->GetNode(nodeId, node))
|
||||
{
|
||||
// First delete model, then current entry
|
||||
m_manager.DeleteNode((*it)->Base()->GetId());
|
||||
m_nodes.erase(it);
|
||||
m_manager.DeleteNode(node->Base()->GetId());
|
||||
m_currentPage->DeleteNode(nodeId);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// There may be many links marked for deletion, let's loop over them.
|
||||
ed::LinkId deletedLinkId;
|
||||
while (ed::QueryDeletedLink(&deletedLinkId))
|
||||
|
|
@ -365,13 +295,11 @@ void NodeEditorWindow::Draw()
|
|||
// If you agree that link can be deleted, accept deletion.
|
||||
if (ed::AcceptDeletedItem())
|
||||
{
|
||||
|
||||
auto it = std::find_if(m_links.begin(), m_links.end(), [deletedLinkId](std::shared_ptr<LinkInfo> inf) { return inf->ed_link->Id == deletedLinkId; });
|
||||
if (it != m_links.end())
|
||||
std::shared_ptr<Connection> model;
|
||||
if (m_currentPage->GetModel(deletedLinkId, model))
|
||||
{
|
||||
// First delete model, then current entry
|
||||
m_manager.DeleteLink((*it)->model);
|
||||
m_links.erase(it);
|
||||
m_manager.DeleteLink(model);
|
||||
m_currentPage->EraseLink(deletedLinkId);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -393,18 +321,23 @@ void NodeEditorWindow::Draw()
|
|||
if (ImGui::BeginPopup("Create New Node"))
|
||||
{
|
||||
auto newNodePostion = openPopupPosition;
|
||||
Node* node = nullptr;
|
||||
if (ImGui::MenuItem("Media Node"))
|
||||
std::shared_ptr<BaseNode> base;
|
||||
auto nodeTypes = m_story->GetNodeTypes();
|
||||
|
||||
for (auto &type : nodeTypes)
|
||||
{
|
||||
auto base = m_manager.CreateNode("media-node");
|
||||
if (base)
|
||||
if (ImGui::MenuItem(type.c_str()))
|
||||
{
|
||||
auto n = CreateNodeWidget(base->GetType(), m_manager, base);
|
||||
if (n)
|
||||
base = m_manager.CreateNode(type);
|
||||
if (base)
|
||||
{
|
||||
n->Base()->SetPosition(newNodePostion.x, newNodePostion.y);
|
||||
n->Initialize();
|
||||
m_nodes.push_back(n);
|
||||
auto n = CreateNodeWidget(type, m_manager, base);
|
||||
if (n)
|
||||
{
|
||||
n->Base()->SetPosition(newNodePostion.x, newNodePostion.y);
|
||||
n->Initialize();
|
||||
m_currentPage->AddNode(n);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -420,7 +353,7 @@ void NodeEditorWindow::Draw()
|
|||
|
||||
ed::Resume();
|
||||
|
||||
|
||||
|
||||
ed::End();
|
||||
ed::SetCurrentEditor(nullptr);
|
||||
|
||||
|
|
@ -431,30 +364,49 @@ void NodeEditorWindow::Draw()
|
|||
|
||||
void NodeEditorWindow::ToolbarUI()
|
||||
{
|
||||
ImGui::SetNextWindowPos(ImVec2(0, 0));
|
||||
ImGui::SetNextWindowSize(ImVec2(42, Gui::GetWindowSize().h));
|
||||
auto& io = ImGui::GetIO();
|
||||
ImVec2 window_pos = ImGui::GetWindowPos();
|
||||
ImVec2 window_size = ImGui::GetWindowSize();
|
||||
ImGuiWindowFlags window_flags = ImGuiWindowFlags_NoDecoration | ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoFocusOnAppearing | ImGuiWindowFlags_NoNav | ImGuiWindowFlags_NoDocking;
|
||||
// if (io.ConfigFlags & ImGuiConfigFlags_ViewportsEnable)
|
||||
// {
|
||||
// const ImGuiViewport* viewport = ImGui::GetWindowViewport();
|
||||
// window_flags |= ImGuiWindowFlags_NoDocking;
|
||||
// io.ConfigViewportsNoDecoration = true;
|
||||
// ImGui::SetNextWindowViewport(viewport->ID);
|
||||
// }
|
||||
ImGui::SetNextWindowBgAlpha(0.35f); // Transparent background
|
||||
// ImGui::PushStyleColor(ImGuiCol_Button, m_StyleColors[BluePrintStyleColor_ToolButton]);
|
||||
// ImGui::PushStyleColor(ImGuiCol_ButtonHovered, m_StyleColors[BluePrintStyleColor_ToolButtonHovered]);
|
||||
// ImGui::PushStyleColor(ImGuiCol_ButtonActive, m_StyleColors[BluePrintStyleColor_ToolButtonActive]);
|
||||
// ImGui::PushStyleColor(ImGuiCol_TexGlyphShadow, ImVec4(0.1, 0.1, 0.1, 0.8));
|
||||
// ImGui::PushStyleVar(ImGuiStyleVar_TexGlyphShadowOffset, ImVec2(2.0, 2.0));
|
||||
|
||||
ImGuiWindowFlags window_flags = 0
|
||||
| ImGuiWindowFlags_NoTitleBar
|
||||
| ImGuiWindowFlags_NoResize
|
||||
| ImGuiWindowFlags_NoMove
|
||||
| ImGuiWindowFlags_NoScrollbar
|
||||
| ImGuiWindowFlags_NoSavedSettings
|
||||
;
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_WindowBorderSize, 0);
|
||||
ImGui::Begin("TOOLBAR", NULL, window_flags);
|
||||
ImGui::PopStyleVar();
|
||||
// ImGui::PopStyleVar();
|
||||
|
||||
if (ImGui::Button(ICON_FA_COG))
|
||||
// Draw call stack, each function is a button
|
||||
for (auto page : m_callStack)
|
||||
{
|
||||
ImGui::OpenPopup("Options");
|
||||
}
|
||||
if (ImGui::Button(page->Name().data()))
|
||||
{
|
||||
// Erase all pages after this iterator
|
||||
auto it = std::find(m_callStack.begin(), m_callStack.end(), page);
|
||||
m_callStack.erase(it, m_callStack.end());
|
||||
|
||||
if (ImGui::Button(ICON_FA_SIGN_OUT_ALT))
|
||||
{
|
||||
// mEvent.ExitGame();
|
||||
LoadPage(page->Uuid().data(), page->Name().data());
|
||||
break;
|
||||
}
|
||||
ImGui::SameLine();
|
||||
ImGui::Text(">");
|
||||
ImGui::SameLine();
|
||||
}
|
||||
|
||||
|
||||
ImGui::End();
|
||||
// ImGui::PopStyleVar();
|
||||
// ImGui::PopStyleColor(4);
|
||||
if (io.ConfigFlags & ImGuiConfigFlags_ViewportsEnable)
|
||||
{
|
||||
io.ConfigViewportsNoDecoration = false;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
#include <map>
|
||||
#include <set>
|
||||
#include <set>
|
||||
#include <utility>
|
||||
|
||||
#include <imgui_node_editor.h>
|
||||
#include "base_node_widget.h"
|
||||
|
|
@ -10,12 +10,10 @@
|
|||
#include "i_story_manager.h"
|
||||
#include "json.hpp"
|
||||
#include "story_project.h"
|
||||
|
||||
#include "node_editor_page.h"
|
||||
|
||||
namespace ed = ax::NodeEditor;
|
||||
|
||||
|
||||
|
||||
# ifdef _MSC_VER
|
||||
# define portable_strcpy strcpy_s
|
||||
# define portable_sprintf sprintf_s
|
||||
|
|
@ -26,35 +24,15 @@ namespace ed = ax::NodeEditor;
|
|||
|
||||
class NodeEditorWindow : public WindowBase
|
||||
{
|
||||
public:
|
||||
struct EditorLink {
|
||||
ed::LinkId Id;
|
||||
ed::PinId InputId;
|
||||
ed::PinId OutputId;
|
||||
};
|
||||
|
||||
// Stuff from ImGuiNodeEditor, each element has a unique ID within one editor
|
||||
struct LinkInfo
|
||||
{
|
||||
|
||||
LinkInfo()
|
||||
{
|
||||
ed_link = std::make_shared<EditorLink>();
|
||||
model = std::make_shared<Connection>();
|
||||
}
|
||||
|
||||
std::shared_ptr<EditorLink> ed_link;
|
||||
std::shared_ptr<Connection> model;
|
||||
};
|
||||
|
||||
public:
|
||||
NodeEditorWindow(IStoryManager &manager);
|
||||
~NodeEditorWindow();
|
||||
virtual void Draw() override;
|
||||
|
||||
void Initialize();
|
||||
void Clear();
|
||||
void Load(std::shared_ptr<StoryProject> story);
|
||||
void SaveNodePositions();
|
||||
void OpenFunction(const std::string &uuid, const std::string &name);
|
||||
|
||||
std::shared_ptr<BaseNodeWidget> GetSelectedNode();
|
||||
|
||||
|
|
@ -63,11 +41,16 @@ private:
|
|||
|
||||
bool m_loaded{false};
|
||||
|
||||
ed::EditorContext* m_context = nullptr;
|
||||
|
||||
// "main" is the entry point editor context. You always need to create one.
|
||||
// Then each function can have its own editor context, for example if you want to create multiple graphs.
|
||||
// the key is main, or the UUID of the function
|
||||
std::list<std::shared_ptr<NodeEditorPage>> m_pages;
|
||||
std::shared_ptr<NodeEditorPage> m_currentPage;
|
||||
std::string m_newPageUuid;
|
||||
std::string m_newPageName;
|
||||
std::shared_ptr<StoryProject> m_story;
|
||||
std::list<std::shared_ptr<BaseNodeWidget>> m_nodes;
|
||||
std::list<std::shared_ptr<LinkInfo>> m_links; // List of live links. It is dynamic unless you want to create read-only view over nodes.
|
||||
std::list<std::shared_ptr<NodeEditorPage>> m_callStack;
|
||||
|
||||
void ToolbarUI();
|
||||
|
||||
void BuildNode(Node* node)
|
||||
|
|
@ -113,11 +96,10 @@ private:
|
|||
}
|
||||
}
|
||||
|
||||
void LoadPage(const std::string &uuid, const std::string &name);
|
||||
ed::PinId GetInputPin(const std::string &modelNodeId, int pinIndex);
|
||||
ed::PinId GetOutputPin(const std::string &modelNodeId, int pinIndex);
|
||||
void CreateLink(std::shared_ptr<Connection> model, ed::PinId inId, ed::PinId outId);
|
||||
// std::shared_ptr<Connection> LinkToModel(ed::PinId InputId, ed::PinId OutputId);
|
||||
int FindNodeAndPin(ed::PinId pinId, int &foundIndex, std::string &foundNodeId);
|
||||
bool FillConnection(std::shared_ptr<Connection> c, ed::PinId pinId);
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -2,9 +2,10 @@
|
|||
#include "uuid.h"
|
||||
#include <iostream>
|
||||
|
||||
BaseNode::BaseNode(const std::string &type)
|
||||
BaseNode::BaseNode(const std::string &type, const std::string &typeName)
|
||||
{
|
||||
m_type = type;
|
||||
m_typeName = typeName;
|
||||
m_uuid = Uuid().String();
|
||||
|
||||
nlohmann::json obj{};
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@ public:
|
|||
float y;
|
||||
};
|
||||
|
||||
BaseNode(const std::string &type);
|
||||
BaseNode(const std::string &type, const std::string &typeName);
|
||||
virtual ~BaseNode();
|
||||
|
||||
static std::string GetEntryLabel(const std::string &id);
|
||||
|
|
@ -32,11 +32,18 @@ public:
|
|||
virtual float GetX() const;
|
||||
virtual float GetY() const;
|
||||
|
||||
// Coded type, internal use
|
||||
std::string GetType() const
|
||||
{
|
||||
return m_type;
|
||||
}
|
||||
|
||||
// Human readable type
|
||||
std::string GetTypeName() const
|
||||
{
|
||||
return m_typeName;
|
||||
}
|
||||
|
||||
void SetId(const std::string &id) { m_uuid = id; }
|
||||
std::string GetId() const { return m_uuid; }
|
||||
|
||||
|
|
@ -54,6 +61,7 @@ public:
|
|||
private:
|
||||
std::string m_title{"Default title"};
|
||||
std::string m_type;
|
||||
std::string m_typeName;
|
||||
std::string m_uuid;
|
||||
NodePosition m_pos;
|
||||
|
||||
|
|
|
|||
43
story-editor/src/node_engine/function_node.cpp
Normal file
43
story-editor/src/node_engine/function_node.cpp
Normal file
|
|
@ -0,0 +1,43 @@
|
|||
#include "function_node.h"
|
||||
#include "story_project.h"
|
||||
#include "connection.h"
|
||||
#include "sys_lib.h"
|
||||
|
||||
|
||||
FunctionNode::FunctionNode(const std::string &type)
|
||||
: BaseNode(type, "Function Node")
|
||||
{
|
||||
nlohmann::json j{ {"function", ""} };
|
||||
SetInternalData(j);
|
||||
}
|
||||
|
||||
void FunctionNode::StoreInternalData()
|
||||
{
|
||||
nlohmann::json j;
|
||||
// j["image"] = m_image;
|
||||
// j["sound"] = m_sound;
|
||||
|
||||
SetInternalData(j);
|
||||
}
|
||||
|
||||
void FunctionNode::Initialize()
|
||||
{
|
||||
nlohmann::json j = GetInternalData();
|
||||
// m_image = j["image"].get<std::string>();
|
||||
// m_sound = j["sound"].get<std::string>();
|
||||
}
|
||||
|
||||
std::string FunctionNode::Build(IStoryProject &story, int nb_out_conns)
|
||||
{
|
||||
return std::string();
|
||||
}
|
||||
|
||||
std::string FunctionNode::GenerateConstants(IStoryProject &story, int nb_out_conns)
|
||||
{
|
||||
std::string s;
|
||||
|
||||
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
23
story-editor/src/node_engine/function_node.h
Normal file
23
story-editor/src/node_engine/function_node.h
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
#pragma once
|
||||
|
||||
#include <string>
|
||||
#include "i_story_manager.h"
|
||||
#include "base_node.h"
|
||||
#include "i_script_node.h"
|
||||
#include "i_story_project.h"
|
||||
|
||||
class FunctionNode : public BaseNode
|
||||
{
|
||||
public:
|
||||
FunctionNode(const std::string &type);
|
||||
|
||||
virtual void Initialize() override;
|
||||
virtual std::string Build(IStoryProject &story, int nb_out_conns) override;
|
||||
virtual std::string GenerateConstants(IStoryProject &story, int nb_out_conns) override;
|
||||
|
||||
void StoreInternalData();
|
||||
|
||||
private:
|
||||
|
||||
};
|
||||
|
||||
|
|
@ -11,7 +11,7 @@ static std::string ChoiceLabel(const std::string &id)
|
|||
}
|
||||
|
||||
MediaNode::MediaNode(const std::string &type)
|
||||
: BaseNode(type)
|
||||
: BaseNode(type, "Media Node")
|
||||
{
|
||||
nlohmann::json j{ {"image", ""}, {"sound", ""}};
|
||||
SetInternalData(j);
|
||||
|
|
|
|||
Loading…
Reference in a new issue