17#include <imgui_node_editor.h> 
   46bool unsavedChanges = 
false;
 
   48constexpr int loadingFramesToWait = 2;
 
   50std::string currentFilename;
 
   51std::filesystem::path programRootPath;
 
   54size_t currentRotatedParentFolderNumber;
 
 
   65    if (currentFilename.empty())
 
 
   77    std::ofstream filestream(filepath);
 
   79    if (!filestream.good())
 
   81        std::cerr << 
"Save Flow error: Could not open file: " << filepath;
 
   88        j[
"nodes"][
"node-" + std::to_string(
size_t(node->id))] = *node;
 
   89        j[
"nodes"][
"node-" + std::to_string(
size_t(node->id))][
"data"] = node->save();
 
   91        for (
const auto& outputPin : node->outputPins)
 
   93            for (
const auto& link : outputPin.links)
 
   95                auto& jLink = j[
"links"][
"link-" + std::to_string(
size_t(link.linkId))];
 
   96                jLink[
"id"] = size_t(link.linkId);
 
   97                jLink[
"startPinId"] = size_t(outputPin.id);
 
   98                jLink[
"endPinId"] = size_t(link.connectedPinId);
 
  104        j[
"implot"][
"style"] = ImPlot::GetStyle();
 
  108    j[
"fonts"][
"useBigDefaultFont"] = gui::NodeEditorApplication::isUsingBigDefaultFont();
 
  109    j[
"fonts"][
"useBigWindowFont"] = gui::NodeEditorApplication::isUsingBigWindowFont();
 
  110    j[
"fonts"][
"useBigPanelFont"] = gui::NodeEditorApplication::isUsingBigPanelFont();
 
  111    j[
"fonts"][
"useBigMonoFont"] = gui::NodeEditorApplication::isUsingBigMonoFont();
 
  118    j[
"gridLinesEnabled"] = ed::GetStyle().Colors[ed::StyleColor_Grid].w;
 
  119    j[
"transparentWindows"] = ImGui::GetStyle().Colors[ImGuiCol_WindowBg].w;
 
  130    filestream << std::setw(4) << j << std::endl; 
 
  132    unsavedChanges = 
false;
 
 
  137    LOG_TRACE(
"called for path {}", filepath);
 
  138    bool loadSuccessful = 
true;
 
  142        std::ifstream filestream(filepath);
 
  144        if (!filestream.good())
 
  146            LOG_ERROR(
"Load Flow error: Could not open file: {}", filepath);
 
  163        nm::CallPreInitCallback();
 
  172                    loadSuccessful = 
false;
 
  185        unsavedChanges = 
false;
 
  187        currentFilename = filepath;
 
  195        std::string path = filepath;
 
  199            if (path.starts_with(
'\\') || path.starts_with(
'/')) { path = path.substr(1); }
 
  202        LOG_INFO(
"Loaded flow file: {}", path);
 
  204    catch (
const std::exception& e)
 
  206        LOG_ERROR(
"Loading flow file failed with error: {}", e.what());
 
  207        loadSuccessful = 
false;
 
  210    return loadSuccessful;
 
 
  215    bool loadSuccessful = 
true;
 
  217    if (j.contains(
"implot"))
 
  221        if (j.at(
"implot").contains(
"prefereFlowOverGlobal"))
 
  228            inputPath.is_relative())
 
  230            filepath /= inputPath;
 
  234            filepath = inputPath;
 
  241                if (j.at(
"implot").contains(
"style"))
 
  243                    j.at(
"implot").at(
"style").get_to(ImPlot::GetStyle());
 
  253    if (j.contains(
"colormaps"))
 
  265        if (j.contains(
"fonts"))
 
  267            if (j.at(
"fonts").contains(
"useBigDefaultFont"))
 
  269                gui::NodeEditorApplication::swapDefaultFont(j.at(
"fonts").at(
"useBigDefaultFont").get<
bool>());
 
  271            if (j.at(
"fonts").contains(
"useBigWindowFont"))
 
  273                gui::NodeEditorApplication::swapWindowFont(j.at(
"fonts").at(
"useBigWindowFont").get<
bool>());
 
  275            if (j.at(
"fonts").contains(
"useBigPanelFont"))
 
  277                gui::NodeEditorApplication::swapPanelFont(j.at(
"fonts").at(
"useBigPanelFont").get<
bool>());
 
  279            if (j.at(
"fonts").contains(
"useBigMonoFont"))
 
  281                gui::NodeEditorApplication::swapMonoFont(j.at(
"fonts").at(
"useBigMonoFont").get<
bool>());
 
  284        if (j.contains(
"leftPane"))
 
  292        if (j.contains(
"lightMode"))
 
  297        if (j.contains(
"gridLinesEnabled")) { j.at(
"gridLinesEnabled").get_to(ed::GetStyle().Colors[ed::StyleColor_Grid].w); }
 
  298        if (j.contains(
"transparentWindows")) { j.at(
"transparentWindows").get_to(ImGui::GetStyle().Colors[ImGuiCol_WindowBg].w); }
 
  301    if (j.contains(
"nodes"))
 
  303        for (
const auto& nodeJson : j.at(
"nodes"))
 
  305            if (!nodeJson.contains(
"type"))
 
  307                LOG_ERROR(
"Node does not contain a type");
 
  310            Node* node = 
nullptr;
 
  313                for (
const auto& nodeInfo : registeredNode.second)
 
  315                    if (nodeInfo.type == nodeJson.at(
"type").get<std::string>())
 
  317                        node = nodeInfo.constructor();
 
  328                LOG_ERROR(
"Node type ({}) is not a valid type.", nodeJson.at(
"type").get<std::string>());
 
  329                loadSuccessful = 
false;
 
  334            auto newNodeId = node->
id;
 
  336            nodeJson.get_to<
Node>(*node);
 
  337            if (nodeJson.contains(
"data"))
 
  339                node->
restore(nodeJson.at(
"data"));
 
  342            nodeJson.get_to<
Node>(*node);
 
  346                node->
id = newNodeId;
 
  361                ed::SetNodePosition(node->
id, nodeJson.at(
"pos").get<ImVec2>());
 
  365                    ed::SetGroupSize(node->
id, node->
getSize());
 
  372    std::set<Node*> newlyLinkedNodes;
 
  374    if (j.contains(
"links"))
 
  376        for (
size_t i = 0; i < 2; i++) 
 
  378            for (
const auto& linkJson : j.at(
"links"))
 
  380                auto linkId = linkJson.at(
"id").get<
size_t>();
 
  381                auto startPinId = linkJson.at(
"startPinId").get<
size_t>();
 
  382                auto endPinId = linkJson.at(
"endPinId").get<
size_t>();
 
  390                        for (
auto& inputPin : node->inputPins)
 
  392                            if (endPinId == 
size_t(inputPin.id)) { endPin = &inputPin; }
 
  397                        for (
auto& outputPin : node->outputPins)
 
  399                            if (startPinId == 
size_t(outputPin.id)) { startPin = &outputPin; }
 
  402                    if (startPin && endPin) { 
break; }
 
  404                if (startPin && endPin)
 
  408                        loadSuccessful = 
false;
 
  411                    newlyLinkedNodes.insert(startPin->
parentNode);
 
  412                    newlyLinkedNodes.insert(endPin->parentNode);
 
  417    if (j.contains(
"nodes"))
 
  419        for (
auto* node : newlyLinkedNodes)
 
  421            if (j.at(
"nodes").contains(
"node-" + std::to_string(
size_t(node->id))))
 
  423                LOG_DEBUG(
"Calling restoreAtferLink() for new node '{}'", node->nameId());
 
  425                const auto& nodeJson = j.at(
"nodes").at(
"node-" + std::to_string(
size_t(node->id)));
 
  426                if (nodeJson.contains(
"data"))
 
  428                    node->restoreAtferLink(nodeJson.at(
"data"));
 
  434    return loadSuccessful;
 
 
  439    return unsavedChanges;
 
 
  445    if (ImGui::GetCurrentContext() && ImGui::GetFrameCount() - 
loadingFrameCount >= loadingFramesToWait)
 
  447        unsavedChanges = 
true;
 
 
  457    unsavedChanges = 
false;
 
 
  462    return currentFilename;
 
 
  467    currentFilename = newFilename;
 
 
  472    return programRootPath;
 
 
  477    LOG_DEBUG(
"Program root path set to {}", newRootPath);
 
  478    programRootPath = newRootPath;
 
 
  486        outputPath.is_relative())
 
  488        filepath /= outputPath;
 
  492        filepath = outputPath;
 
  497        filepath /= fmt::format(
"{:04d}", currentRotatedParentFolderNumber);
 
 
  505    currentRotatedParentFolderNumber = 0;
 
  506    for (
int i = 10000; i >= 0; --i)
 
  508        std::filesystem::path outputDir{ programRootPath };
 
  511            outputPath.is_relative())
 
  513            outputDir /= outputPath;
 
  517            outputDir = outputPath;
 
  519        outputDir /= fmt::format(
"{:04d}", i);
 
  520        if (std::filesystem::exists(outputDir))
 
  522            currentRotatedParentFolderNumber = 
static_cast<size_t>(i + 1); 
 
 
  534        inputPath.is_relative())
 
  536        filepath /= inputPath;
 
  540        filepath = inputPath;
 
 
  551        inputPath.is_relative())
 
  553        filepath /= inputPath;
 
  557        filepath = inputPath;
 
 
Common logging variables like time into run and local positions.
Config management for the Project.
nlohmann::json json
json namespace
GlobalActions
Possible Global Actions to perform in the GUI.
@ SaveAs
Save the flow as filename.
ImPlot style editor window.
Defines how to save certain datatypes to json.
#define LOG_DEBUG
Debug information. Should not be called on functions which receive observations (spamming)
#define LOG_ERROR
Error occurred, which stops part of the program to work, but not everything.
#define LOG_INFO
Info to the user on the state of the program.
#define LOG_TRACE
Detailled info to trace the execution of the program. Should not be called on functions which receive...
Utility class which specifies available nodes.
static void restore(const json &j)
Read info from a json object.
static json save()
Returns a json object of the common log.
Abstract parent class for all nodes.
virtual void restore(const json &j)
Restores the node from a json object.
const ImVec2 & getSize() const
Get the size of the node.
std::vector< OutputPin > outputPins
List of output pins.
std::vector< InputPin > inputPins
List of input pins.
ax::NodeEditor::NodeId id
Unique Id of the Node.
bool createLink(InputPin &endPin, ax::NodeEditor::LinkId linkId=0)
Creates a link from this pin to another, calling all node specific callbacks.
Node * parentNode
Reference to the parent node.
static float bottomViewHeight
Height of the log viewer.
static float leftPaneWidth
Width of the left pane.
static std::vector< ImVec4 > m_colors
Color settings.
static bool hideLeftPane
Hide left pane.
static float rightPaneWidth
Width of the right pane.
static bool hideFPS
Hide FPS counter.
const T & Get(const std::string &key, const T &&defaultValue)
Retrieves the value of a corresponding key from the configuration, if one exists.
bool isRunning() noexcept
Checks if the thread is running.
void stop()
Stops the Thread.
void InitializeAllNodesAsync()
Initializes all nodes in a separate thread.
void UpdateNode(Node *node)
Update the provided node object.
bool InitializeAllNodes()
Initializes all nodes.
void DeleteAllNodes()
Delete all nodes.
const std::vector< Node * > & m_Nodes()
List of all registered Nodes.
void AddNode(Node *node)
Add the provided node object to the list of nodes.
ax::NodeEditor::PinId GetNextPinId()
Generates a new pin id.
const std::map< std::string, std::vector< NodeInfo > > & RegisteredNodes()
Reference to List of all registered Nodes.
bool saveLastActions
Whether actions should be saved to the last actions list.
void SetProgramRootPath(const std::filesystem::path &newRootPath)
Set the program root path.
bool LoadJson(const json &j, bool requestNewIds=false)
Loads the nodes and links from the specified json object.
void SetCurrentFilename(const std::string &newFilename)
Set the current filename of the open flow.
bool LoadFlow(const std::string &filepath)
Loads the flow from the specified file.
int loadingFrameCount
Frame Count when changes were loaded to prevent nodes moving from triggering unsaved changes.
std::filesystem::path GetConfigPath()
Get the path where config files are searched.
std::filesystem::path GetOutputPath()
Get the path where logs and outputs are stored.
void SaveFlowAs(const std::string &filepath)
Saves the current flow into the specified file.
std::filesystem::path GetInputPath()
Get the path where data files are searched.
void DiscardChanges()
Discards the unsaved changes flag. Does not really discard the changes.
std::string GetCurrentFilename()
Get the current filename of the open flow.
void ApplyChanges()
Signals that there have been changes to the flow.
std::filesystem::path GetFlowPath()
Get the path where flow files are searched.
std::filesystem::path GetProgramRootPath()
Get the program root path.
bool HasUnsavedChanges()
Checks if the currently open flow has unsaved changes.
void SaveFlow(GlobalActions &globalAction)
Saves the current flow into a file.
void SetOutputPath()
Set the path where logs and outputs are stored.
void ApplyDarkLightMode(std::vector< ImVec4 > &colors)
bool prefereFlowOverGlobal
If true, the ImPlot config from the flow file will be preferred over the global settings file.
bool nodeEditorLightMode
If true, light mode is selected.
bool saveConfigInFlow
If true, the ImPlot config will be saved into the flow file.
void clearLastActionList()
Clears the list of last actions.
void saveLastAction()
Saves the last action to the action list.
std::vector< Colormap > ColormapsFlow
Flow colormaps.