Skip to content

Releases: Azzinoth/VisualNodeSystem

0.2.0: Sub-Area and Link Nodes

Choose a tag to compare

@Azzinoth Azzinoth released this 17 Jul 12:03

0.2.0: Sub-Area and Link Nodes

The main focus of this update was more mature interaction between node areas, and better integration and management of those areas by the node system manager. Along the way its scope grew to include several additional features and many bug fixes, all covered below.

Main Changes

Sub-area nodes

A sub-area node contains its own, fully self-contained node graph (NodeArea), exposed to the parent graph through dedicated input and output boundary nodes. This lets user collapse a complex portion of a graph into a single, reusable, nestable sub-area node, improving readability and letting user build graphs hierarchically.

Link nodes

Sub-area owns and encapsulates its inner (NodeArea), a link node connects two separate node areas by reference, so several places can share and reference the same graph or to be connected to some node in referenced (NodeArea).

Boundary nodes with mirrored sockets

Sub-area and link nodes share a common boundary (mirror) node base. You can add your own sockets to a boundary node, and each one is automatically mirrored to the matching side of the area boundary, so data and execution signals pass through it between the two node areas. Renaming or changing the type of a socket updates its mirrored counterpart as well, keeping both sides consistent.

NodeSystem is now the central owner of all node areas

Because node areas can now reference one another (through link nodes) and nest inside one another (through sub-areas), an individual node area can still be saved on its own, but doing so drops any connections it had to other areas. To preserve those cross-area connections, NodeSystem is therefore now the single owner and manager of every node area, and the entire system, all areas together with their interconnections, can be saved to and loaded from a single JSON file.

Explicit socket direction and multiple types

Previously, whether a socket was an input or an output was defined by a bool, which was ambiguous and easy to misinterpret at call sites. It is now expressed explicitly through the NodeSocket::SocketFlow enum. Sockets can also hold multiple allowed types.

Dynamic socket types

A socket's allowed types can now be changed at runtime through NodeSocket::SetAllowedTypes. Existing connections are automatically re-validated after the change, and link nodes react appropriately to keep their mirrored sockets consistent.

Expanded test coverage

A large number of additional test cases were added to cover the new sub-area and link functionality, along with regression tests for the bugs fixed in this release.

Changes

Breaking Changes:

Compatibility:

  • Saves produced by previous versions are not compatible with this release and there is currently no automatic migration. If enough feedback indicates it is needed, a migration tool may be added later.
  • The library now also depends on imgui_stdlib.h (Dear ImGui's standard-library helpers from misc/cpp/). Ensure misc/cpp/imgui_stdlib.cpp from your Dear ImGui copy is compiled as part of your project.

Behavioral changes:

  • std::string NodeSocket::GetType() const was replaced with std::vector NodeSocket::GetAllowedTypes() const.
  • Right-clicking a socket now opens a socket context menu instead of immediately breaking all of that socket's connections. (A “break all connections to/from node” option was added to the context menu.)
  • NodeArea::GetLastExecutedNodes() now returns nodes in execution order (previously it returned them in reverse execution order).
  • NodeArea::RunOnEachConnectedNode no longer invokes the callback on the starting node itself.
  • Node::CanConnect no longer allows duplicate connections.
  • NodeArea::TryToConnect now rejects connections when a node has no parent area, when the two nodes belong to different areas, or when the call is made on an area that does not own the nodes.
  • NodeArea::AddNode and NodeArea::AddGroupComment now reject objects that already belong to an area.
  • NodeSocket now silently ignores an empty ("") socket type.
  • Static socket-count checks were removed from deserialization, custom nodes should validate their own socket counts on load.
  • The base Node copy constructor no longer copies socket data-getters (they typically capture the source node), each custom node type must reinstall its own getters in its copy constructor.

Lifecycle / ownership:

  • NodeArea's destructor is now private, and its copy constructor and copy-assignment operator were deleted, areas are managed exclusively through NODE_SYSTEM.
  • NodeSocket's destructor is now private, delete sockets via NodeSystem::DeleteSocket or Node::DeleteSocket, not directly.
  • The static area-management functions (CreateNodeArea, CopyNodesTo, MoveNodesTo, and similar) were moved off NodeArea (where they previously created unregistered, leaking areas) onto NODE_SYSTEM.

Renames:

  • Renamed NodeArea::SetMainContextMenuFunc to NodeArea::SetMainContextMenuFunction.
  • Build flag VISUAL_NODE_SYSTEM_BUILD_STANDARD_NODES was renamed to VISUAL_NODE_SYSTEM_BUILD_EXECUTION_FLOW_NODES.
  • Flag NODE_WITH_PER_SOCKET was renamed to NODE_HEIGHT_PER_SOCKET.
  • NodeArea::GetNodesByType(std::string) was renamed to NodeArea::GetNodesByStringType(std::string) (the name GetNodesByType is now a template overload).
  • NodeArea::DeleteNode(const Node*) was renamed to NodeArea::Delete(const Node*).
  • NodeArea::Delete(RerouteNode*) was replaced by NodeArea::DeleteRerouteNodeByID(std::string).
  • Redundant NodeArea::DeleteGroupComment(GroupComment*) was removed in favor of NodeArea::Delete(GroupComment*).
  • NodeArea::SetExecutionEntryNode(std::string) was renamed to NodeArea::SetExecutionEntryNodeByID(std::string).
  • NodeSystem::CopyNodesTo was renamed to NodeSystem::CopyElementsTo (it copies both nodes and group comments).
  • The Node flag bCouldBeDestroyed was renamed to bCouldBeDestroyedByUser.
  • Node::SetSocketAllowedTypes was moved to NodeSocket::SetAllowedTypes.
  • SubAreaInputNode::GetParentArea (which shadowed Node::GetParentArea) was renamed to SubAreaInputNode::GetOwningParentArea.

Removals:

  • The VISUAL_NODE_SYSTEM_VERSION macro was removed, use NODE_SYSTEM.GetVersion() instead.
  • Node::GetSocketByIDInternal was removed, use Node::GetSocketByID.

Signature / return-type changes:

  • The signature of Node::FromJson has changed from virtual void FromJson(Json::Value Json) to virtual bool FromJson(Json::Value Json), any classes inheriting from Node and overriding FromJson must update their signature and return true on success or false on failure (e.g., validation failure).
  • Socket-direction bool parameters were replaced by the NodeSocket::SocketFlow enum across the whole system.
  • Node::AddSocket is now virtual and returns bool (was void).
  • NodeArea::AddNode now returns bool (was void).
  • NodeArea::SaveToFile now returns bool (was void).
  • NodeArea::Delete(Connection*) now returns bool (was void).
  • NodeSystem::MoveNodesTo now returns bool (was void).
  • GroupComment::FromJson now returns bool and validates its input (was void).
  • NodeArea::AddRerouteNodeToConnection now returns RerouteNode* (was bool).
  • NodeArea callbacks now take std::function instead of raw function pointers (for better lambda support).

Bug Fixes (selected):

  • GroupComment::SetPosition now correctly moves attached nodes, previously, only non-programmatic(mouse-drag) movement worked as expected.
  • Loading a saved graph could crash or silently drop nodes and group comments (they were read by position rather than by name). Loading now reads members by their real names, validates the JSON, and clears any existing data first; many invalid-JSON edge cases were hardened.
  • Fixed numerous crashes and memory leaks around copy, paste, cut, delete, and moving nodes between areas, including a double-free triggered by the ...
Read more

v0.1.0

Choose a tag to compare

@Azzinoth Azzinoth released this 16 Jun 18:23

0.1.0: Test Branch and Various Small Refactorings

In this update, I mainly focused on creating a base for continuous integration. I decided not to include the gtest library and tests themselves in the master branch to keep it lightweight. Instead, I created a tests branch to house all the necessary code and used GitHub Actions to ensure CI is properly utilized. The test cases included do not provide full coverage, but they helped me spot a few bugs.

Changes

Bug Fixes:

  • NodeArea::Clear() was not clearing GroupComments.
  • std::vector<Node*> Node::GetNodesConnectedToOutput() was returning multiple copies of the same node if that node was connected through multiple sockets.

Breaking Changes:

  • Renamed function size_t Node::InputSocketCount to size_t Node::GetInputSocketCount to better describe its functionality.
  • Renamed function size_t Node::OutSocketCount to size_t Node::GetOutputSocketCount to better describe its functionality.
  • Made static void NodeArea::CopyNodesInternal, static bool NodeArea::IsAlreadyConnected, and static void NodeArea::ProcessConnections functions private.
  • Renamed static bool NodeArea::EmptyOrFilledByNulls to static bool NodeArea::IsEmptyOrFilledByNulls and made it private.
  • Renamed and moved static bool NodeArea::IsNodeIDInList to static bool Node::IsNodeWithIDInList.
  • Transformed static NodeArea* NodeArea::FromJson(std::string JsonText) to void NodeArea::LoadFromJson(std::string JsonText) to make it more clear when to use the function. This also helped to rewrite loading from a file to avoid node copying, as the previous implementation was inefficient due to legacy issues.
  • Renamed NodeArea::SetNodeEventCallback to NodeArea::AddNodeEventCallback to better reflect its functionality and shifted from accepting raw function pointers to accepting std::function for better support of lambdas.

Other Changes:

  • Added size_t NodeArea::GetGroupCommentCount function.
  • Changed the return type of the NodeArea::GetNodeCount function from int to size_t.
  • Added bool Node::CouldBeDestroyed function.
  • Added Node* NodeArea::GetNodeByID function.
  • Added GroupComment* NodeArea::GetGroupCommentByID(std::string GroupCommentID) and std::vector<GroupComment*> NodeArea::GetGroupCommentsByName(std::string GroupCommentName) functions.
  • Added std::vector<Node*> NodeArea::GetNodesInGroupComment(GroupComment* GroupCommentToCheck), std::vector<RerouteNode*> NodeArea::GetRerouteNodesInGroupComment(GroupComment* GroupCommentToCheck), and std::vector<GroupComment*> NodeArea::GetGroupCommentsInGroupComment(GroupComment* GroupCommentToCheck) functions.
  • Added bool NodeArea::TryToDisconnect(const Node* OutNode, size_t OutNodeSocketIndex, const Node* InNode, size_t InNodeSocketIndex), bool NodeArea::TryToDisconnect(const Node* OutNode, std::string OutSocketID, const Node* InNode, std::string InSocketID), bool NodeArea::IsConnected(const Node* OutNode, size_t OutNodeSocketIndex, const Node* InNode, size_t InNodeSocketIndex), and bool NodeArea::IsConnected(const Node* OutNode, std::string OutSocketID, const Node* InNode, std::string InSocketID) functions to improve work with connections.