TachyonUI 0.1.0
High-performance UI for building tools.
Loading...
Searching...
No Matches
Node view

Nodes, pins and links for the node graph editor. More...

Classes

struct  tachyon::PropertyEndpoint
 A property on a node. Default-constructed is invalid: in a socket it means "present, unwired". More...
struct  tachyon::NodeProperty
 One row of a node: an optional input socket, a body, and an optional output socket. More...
struct  tachyon::NodeModel
 One node of a node view. More...
struct  tachyon::PendingConnection
 A wire being dragged. Committed wires are the reciprocal endpoints on NodeProperty. More...
struct  tachyon::WireLane
 A wire's place among the wires between the same two nodes, so their default lanes nest instead of coinciding or crossing (ComputeWireLaneOffsets). More...
struct  tachyon::WireRouteOverrides
 User-pinned lanes of one wire (unset = default), in the route's space. More...
struct  tachyon::WireSegmentHandle
 Draggable interior segment; vertical segments drag horizontally and vice versa. More...
struct  tachyon::WireRoute
 Polyline plus its draggable interior segments (never the end stubs). More...
struct  tachyon::CachedWireHandle
 Last frame's draggable segment (node.pos space), for laying out its grab element. More...
struct  tachyon::NodeViewEdit
 One thing the user did in a node view, as values before and after, so a host can keep the undo history (NodeView::onEdit) and undo or redo it (ApplyNodeViewEdit). More...
struct  tachyon::DrawnWire
 A wire as drawn this frame, for hit-testing; points in node.pos space. More...
struct  tachyon::WireSegmentDrag
 Segment drag via mouse capture rather than DnD, so the resize cursor sticks. More...
struct  tachyon::NodeView
 All state of one node-view widget; no global state. More...

Enumerations

enum class  tachyon::WireHandle : uint8_t {
  tachyon::WireHandle::None , tachyon::WireHandle::LaneX , tachyon::WireHandle::ExitX , tachyon::WireHandle::EntryX ,
  tachyon::WireHandle::LaneY
}
 Interior lane a drag handle adjusts: the corridor route's vertical lane (LaneX), or the detour route's verticals (ExitX, EntryX) and horizontal return lane (LaneY). More...

Functions

float tachyon::NodeViewZoom (const NodeView &view)
 The node view's zoom (1 = 100%).
void tachyon::ZoomNodeView (NodeView &view, float factor, int2 pivot={})
 Zooms by factor around pivot (pixels from the canvas centre), within 10%..100%.
void tachyon::SetNodeViewCenter (NodeView &view, float2 center, float zoom)
 Centres the view on canvas point center at zoom (clamped to 10%..100%).
void tachyon::FrameAllNodes (NodeView &view)
 Centres and zooms the view on all nodes (Home, the Fit button).
void tachyon::ScrollNodeIntoView (NodeView &view, int nodeIdx, int32_t margin)
 Pans the view, at the same zoom, by as little as brings node nodeIdx inside it with margin pixels to spare; a node larger than the view shows its top-left.
void tachyon::RenderCanvasGrid (CustomDrawContext &ctx, int32_t baseGridSize, color4f dotColor, float dotSize, int2 originOffset={}, IntRect clipCurrent={})
 Infinite background dot grid for a pan/zoom canvas, drawn from a CustomDrawContext callback in the canvas's layout space (node.pos space): a dot on every grid point.
constexpr int32_t tachyon::FloorDiv (int32_t a, int32_t b)
 a / b rounded toward negative infinity.
constexpr int32_t tachyon::GridLineLE (int32_t v, int32_t origin, int32_t grid)
 The grid line (origin + k x grid) at or below v; grid must be > 0.
constexpr int32_t tachyon::GridLineGE (int32_t v, int32_t origin, int32_t grid)
 The grid line (origin + k x grid) at or above v; grid must be > 0.
constexpr int32_t tachyon::GridLineNearest (int32_t v, int32_t origin, int32_t grid)
 The grid line (origin + k x grid) nearest v, ties going down; grid must be > 0.
WireRoute tachyon::BuildWireRoute (int2 outPt, int2 inPt, IntRect srcRect, IntRect tgtRect, int32_t grid, int2 gridOrigin, const WireRouteOverrides &overrides={})
 Orthogonal route for a wire from an output socket (outPt, on srcRect's right edge) to an input socket (inPt, on tgtRect's left edge), with bends on the grid and clear of both bodies:
constexpr uint32_t tachyon::WireKey (int targetNode, int targetProp)
 Stable key for a wire, identified by its target (input) endpoint - each input carries at most one incoming wire.
constexpr PropertyEndpoint tachyon::WireInput (uint32_t wireKey)
 The input a WireKey names.
std::optional< uint32_t > tachyon::WireAt (std::span< const DrawnWire > wires, int2 p, float tolerance)
 The wire within tolerance of point p (the closest when several are); none when no wire is.
void tachyon::ApplyNodeViewEdit (NodeView &view, const NodeViewEdit &edit, bool undo=false)
 Redoes edit (its to values), or with undo restores its from values.
void tachyon::CommitNodeViewEdit (NodeView &view, const NodeViewEdit &edit)
 Applies edit and reports it to view.onEdit.
NodeViewEdit tachyon::ConnectEdit (const NodeView &view, PropertyEndpoint output, PropertyEndpoint input)
 An edit that wires output into Input; the input's old wire goes, the output keeps its others.
NodeViewEdit tachyon::DisconnectEdit (const NodeView &view, PropertyEndpoint input)
 An edit that removes the wire into Input, with its lane overrides.
NodeViewEdit tachyon::AddNodeEdit (const NodeView &view, NodeModel node, int index=-1)
 An edit that adds node at index (-1, or past the end: last), drawn in front of the others.
NodeViewEdit tachyon::RemoveNodesEdit (const NodeView &view, std::span< const int > indices)
 An edit that removes the nodes at indices (in any order; ones out of range and repeats are skipped), with every wire into or out of them and those wires' lanes.
NodeViewEdit tachyon::RerouteWireEdit (const NodeView &view, uint32_t wireKey, ID stableID, int2 pos)
 An edit that puts a reroute (NodeModel::reroute) on the wire wireKey (the WireKey of its input): the wire then runs from its output into the new reroute, and on from it into the input.
std::unordered_map< uint32_t, WireLane > tachyon::ComputeWireLaneOffsets (const NodeView &view, PropertyEndpoint pendingOut={}, PropertyEndpoint pendingIn={})
 Default lane offsets (grid steps) for wires between the same two nodes, so their lanes don't coincide: k wires, in input order, get (k-1)/2 counting down by one (one wire: 0; two: 0,-1; three: 1,0,-1; four: 1,0,-1,-2), so wires running down nest instead of crossing.
WireRoute tachyon::BuildPendingWireRoute (int2 outPt, IntRect srcRect, int2 cursor, std::optional< int2 > inPt, IntRect tgtRect, int32_t grid, int2 gridOrigin, WireLane lane={})
 A wire being dragged from an output: routed as the connection it would make when it is over an input that accepts it (inPt on tgtRect), else to cursor as if an input sat there.
WireRoute tachyon::BuildPendingWireRouteToInput (int2 inPt, IntRect tgtRect, int2 cursor, std::optional< int2 > outPt, IntRect srcRect, int32_t grid, int2 gridOrigin, WireLane lane={})
 A wire being dragged from an input: routed as the connection it would make when it is over an output that accepts it (outPt on srcRect), else from cursor as if an output sat there.
bool tachyon::ConnectionAllowed (const NodeView &view, PropertyEndpoint out, PropertyEndpoint in)
 Whether a wire from output out to input in is allowed: never a same-node loop, otherwise the view's canConnect delegate decides (none: allowed).
PropertyEndpoint tachyon::FirstInputAccepting (const NodeView &view, PropertyEndpoint output, int nodeIdx)
 The first input of node nodeIdx, top to bottom, that a wire from output may connect to; invalid when there is none.
PropertyEndpoint tachyon::FirstOutputAccepting (const NodeView &view, PropertyEndpoint input, int nodeIdx)
 The first output of node nodeIdx, top to bottom, that may feed Input; invalid when there is none.
int tachyon::NodeAtCanvasPos (const NodeView &view, float2 canvasPos)
 The node whose {pos, lastSize} rect holds canvasPos (node.pos space), the frontmost in view.ordering when several do; -1 when none does.
void tachyon::ConnectSockets (NodeView &view, PropertyEndpoint output, PropertyEndpoint input)
 Wires output into Input without reporting to view.onEdit.
void tachyon::BringNodeToFront (std::vector< int > &ordering, int n)
 Moves n to the front (last) of a z-order list, keeping the others' order.
float2 tachyon::NodeViewScreenToCanvas (const float3x2 &viewTransform, IntRect canvasInnerRectScreen, int2 screen)
 A screen point in node.pos space, for a canvas whose padding box is canvasInnerRectScreen (screen pixels) and whose pan/zoom is viewTransform (view.transform).
float2 tachyon::NodeViewScreenToCanvas (const NodeView &view, int2 screen)
 A screen point (as events have them) in node.pos space, through the pan/zoom and place the view was last drawn with.
float2 tachyon::NodeViewCanvasToScreen (const NodeView &view, float2 canvasPos)
 A point in node.pos space on the screen, where the view last drew it: the other way round from NodeViewScreenToCanvas.
std::unordered_set< ID > tachyon::ComputeNodesInMarquee (std::span< const NodeModel > nodes, IntRect canvasInnerRectScreen, const float3x2 &viewTransform, int2 marqueeStartScreen, int2 marqueeCurrentScreen)
 Stable IDs of nodes whose {pos, lastSize} rect lies fully inside the marquee, compared in node.pos space (canvas inner-rect relative, before the content transform).

Detailed Description

Nodes, pins and links for the node graph editor.

Calls (members of tachyon::GUIApplication): RenderNodeView, NodeText. Guide: Node view.

Enumeration Type Documentation

◆ WireHandle

enum class tachyon::WireHandle : uint8_t
strong

#include <gui_controls/gui_node_view_types.h>

Interior lane a drag handle adjusts: the corridor route's vertical lane (LaneX), or the detour route's verticals (ExitX, EntryX) and horizontal return lane (LaneY).

Enumerator
None 
LaneX 
ExitX 
EntryX 
LaneY 

Function Documentation

◆ NodeViewZoom()

float tachyon::NodeViewZoom ( const NodeView & view)

#include <gui_controls/gui_node_view_helpers.h>

The node view's zoom (1 = 100%).

◆ ZoomNodeView()

void tachyon::ZoomNodeView ( NodeView & view,
float factor,
int2 pivot = {} )

#include <gui_controls/gui_node_view_helpers.h>

Zooms by factor around pivot (pixels from the canvas centre), within 10%..100%.

◆ SetNodeViewCenter()

void tachyon::SetNodeViewCenter ( NodeView & view,
float2 center,
float zoom )

#include <gui_controls/gui_node_view_helpers.h>

Centres the view on canvas point center at zoom (clamped to 10%..100%).

◆ FrameAllNodes()

void tachyon::FrameAllNodes ( NodeView & view)

#include <gui_controls/gui_node_view_helpers.h>

Centres and zooms the view on all nodes (Home, the Fit button).

◆ ScrollNodeIntoView()

void tachyon::ScrollNodeIntoView ( NodeView & view,
int nodeIdx,
int32_t margin )

#include <gui_controls/gui_node_view_helpers.h>

Pans the view, at the same zoom, by as little as brings node nodeIdx inside it with margin pixels to spare; a node larger than the view shows its top-left.

◆ RenderCanvasGrid()

void tachyon::RenderCanvasGrid ( CustomDrawContext & ctx,
int32_t baseGridSize,
color4f dotColor,
float dotSize,
int2 originOffset = {},
IntRect clipCurrent = {} )

#include <gui_controls/gui_node_view_helpers.h>

Infinite background dot grid for a pan/zoom canvas, drawn from a CustomDrawContext callback in the canvas's layout space (node.pos space): a dot on every grid point.

dotSize is the dot's diameter; 2 gives one crisp pixel. The pitch doubles per zoom-out octave, so on-screen density stays roughly constant.

baseGridSize : pitch in layout pixels at 1:1 zoom. <= 0 draws nothing. originOffset : a point the lattice passes through. Pass ElementRect().position - ElementInnerRect().position to align with children positioned relative to the border box. clipCurrent : optional extra clip in the CURRENT space. The scissor is the border box, so pass ElementInnerRect() to keep out of the padding.

◆ FloorDiv()

int32_t tachyon::FloorDiv ( int32_t a,
int32_t b )
constexpr

#include <gui_controls/gui_node_view_helpers.h>

a / b rounded toward negative infinity.

◆ GridLineLE()

int32_t tachyon::GridLineLE ( int32_t v,
int32_t origin,
int32_t grid )
constexpr

#include <gui_controls/gui_node_view_helpers.h>

The grid line (origin + k x grid) at or below v; grid must be > 0.

◆ GridLineGE()

int32_t tachyon::GridLineGE ( int32_t v,
int32_t origin,
int32_t grid )
constexpr

#include <gui_controls/gui_node_view_helpers.h>

The grid line (origin + k x grid) at or above v; grid must be > 0.

◆ GridLineNearest()

int32_t tachyon::GridLineNearest ( int32_t v,
int32_t origin,
int32_t grid )
constexpr

#include <gui_controls/gui_node_view_helpers.h>

The grid line (origin + k x grid) nearest v, ties going down; grid must be > 0.

◆ BuildWireRoute()

WireRoute tachyon::BuildWireRoute ( int2 outPt,
int2 inPt,
IntRect srcRect,
IntRect tgtRect,
int32_t grid,
int2 gridOrigin,
const WireRouteOverrides & overrides = {} )

#include <gui_controls/gui_node_view_helpers.h>

Orthogonal route for a wire from an output socket (outPt, on srcRect's right edge) to an input socket (inPt, on tgtRect's left edge), with bends on the grid and clear of both bodies:

  • a horizontal corridor between the bodies -> one vertical lane in it;
  • else a vertical gap between them -> detour through the gap;
  • else (side-by-side) -> around the nearer outside edge. grid <= 0 or an empty rect gives a plain elbow. overrides pin interior lanes, clamped so they never cross a body; overrides.lane spreads the unpinned lanes of wires between the same two nodes so they nest. All coordinates share one space (node.pos space).

◆ WireKey()

uint32_t tachyon::WireKey ( int targetNode,
int targetProp )
constexpr

#include <gui_controls/gui_node_view_helpers.h>

Stable key for a wire, identified by its target (input) endpoint - each input carries at most one incoming wire.

Keys the per-wire lane overrides and drag handles.

◆ WireInput()

PropertyEndpoint tachyon::WireInput ( uint32_t wireKey)
constexpr

#include <gui_controls/gui_node_view_helpers.h>

The input a WireKey names.

◆ WireAt()

std::optional< uint32_t > tachyon::WireAt ( std::span< const DrawnWire > wires,
int2 p,
float tolerance )

#include <gui_controls/gui_node_view_helpers.h>

The wire within tolerance of point p (the closest when several are); none when no wire is.

Points and tolerance share the wires' space.

◆ ApplyNodeViewEdit()

void tachyon::ApplyNodeViewEdit ( NodeView & view,
const NodeViewEdit & edit,
bool undo = false )

#include <gui_controls/gui_node_view_helpers.h>

Redoes edit (its to values), or with undo restores its from values.

◆ CommitNodeViewEdit()

void tachyon::CommitNodeViewEdit ( NodeView & view,
const NodeViewEdit & edit )

#include <gui_controls/gui_node_view_helpers.h>

Applies edit and reports it to view.onEdit.

◆ ConnectEdit()

NodeViewEdit tachyon::ConnectEdit ( const NodeView & view,
PropertyEndpoint output,
PropertyEndpoint input )

#include <gui_controls/gui_node_view_helpers.h>

An edit that wires output into Input; the input's old wire goes, the output keeps its others.

◆ DisconnectEdit()

NodeViewEdit tachyon::DisconnectEdit ( const NodeView & view,
PropertyEndpoint input )

#include <gui_controls/gui_node_view_helpers.h>

An edit that removes the wire into Input, with its lane overrides.

◆ AddNodeEdit()

NodeViewEdit tachyon::AddNodeEdit ( const NodeView & view,
NodeModel node,
int index = -1 )

#include <gui_controls/gui_node_view_helpers.h>

An edit that adds node at index (-1, or past the end: last), drawn in front of the others.

The nodes from index on move up one, and the wires, lanes and z-order with them. Its own inputs name nodes as they're numbered once it's in. To wire it to another node in the same step, add that Rewire to the edit (the node is added first):

NodeViewEdit edit = AddNodeEdit(view, std::move(node));
edit.rewires.push_back({ .input = { added, 0 }, .from = {}, .to = output }); 

◆ RemoveNodesEdit()

NodeViewEdit tachyon::RemoveNodesEdit ( const NodeView & view,
std::span< const int > indices )

#include <gui_controls/gui_node_view_helpers.h>

An edit that removes the nodes at indices (in any order; ones out of range and repeats are skipped), with every wire into or out of them and those wires' lanes.

The nodes after each move down, and the wires, lanes and z-order with them; undone, all of it comes back. A removed node's stableID is the host's to keep while the edit can be undone.

◆ RerouteWireEdit()

NodeViewEdit tachyon::RerouteWireEdit ( const NodeView & view,
uint32_t wireKey,
ID stableID,
int2 pos )

#include <gui_controls/gui_node_view_helpers.h>

An edit that puts a reroute (NodeModel::reroute) on the wire wireKey (the WireKey of its input): the wire then runs from its output into the new reroute, and on from it into the input.

The reroute takes stableID, which the host keeps as for its other nodes, and pos (its square's top-left; a multiple of the grid puts the dot on a grid point). The wire's lane overrides go. Empty when there's no such wire.

◆ ComputeWireLaneOffsets()

std::unordered_map< uint32_t, WireLane > tachyon::ComputeWireLaneOffsets ( const NodeView & view,
PropertyEndpoint pendingOut = {},
PropertyEndpoint pendingIn = {} )

#include <gui_controls/gui_node_view_helpers.h>

Default lane offsets (grid steps) for wires between the same two nodes, so their lanes don't coincide: k wires, in input order, get (k-1)/2 counting down by one (one wire: 0; two: 0,-1; three: 1,0,-1; four: 1,0,-1,-2), so wires running down nest instead of crossing.

Wires running up (target node above the source) get them in reverse, for the same reason. Also each wire's index in its group and the group's size, for the detour routes. Keyed by WireKey. A dragged wire (pendingOut -> pendingIn, both valid) counts as connected, under pendingIn's key, replacing that input's wire.

◆ BuildPendingWireRoute()

WireRoute tachyon::BuildPendingWireRoute ( int2 outPt,
IntRect srcRect,
int2 cursor,
std::optional< int2 > inPt,
IntRect tgtRect,
int32_t grid,
int2 gridOrigin,
WireLane lane = {} )

#include <gui_controls/gui_node_view_helpers.h>

A wire being dragged from an output: routed as the connection it would make when it is over an input that accepts it (inPt on tgtRect), else to cursor as if an input sat there.

◆ BuildPendingWireRouteToInput()

WireRoute tachyon::BuildPendingWireRouteToInput ( int2 inPt,
IntRect tgtRect,
int2 cursor,
std::optional< int2 > outPt,
IntRect srcRect,
int32_t grid,
int2 gridOrigin,
WireLane lane = {} )

#include <gui_controls/gui_node_view_helpers.h>

A wire being dragged from an input: routed as the connection it would make when it is over an output that accepts it (outPt on srcRect), else from cursor as if an output sat there.

Points run output to input, as BuildWireRoute's.

◆ ConnectionAllowed()

bool tachyon::ConnectionAllowed ( const NodeView & view,
PropertyEndpoint out,
PropertyEndpoint in )

#include <gui_controls/gui_node_view_helpers.h>

Whether a wire from output out to input in is allowed: never a same-node loop, otherwise the view's canConnect delegate decides (none: allowed).

Endpoints are bounds-checked first, so the delegate can index view.nodes directly.

◆ FirstInputAccepting()

PropertyEndpoint tachyon::FirstInputAccepting ( const NodeView & view,
PropertyEndpoint output,
int nodeIdx )

#include <gui_controls/gui_node_view_helpers.h>

The first input of node nodeIdx, top to bottom, that a wire from output may connect to; invalid when there is none.

◆ FirstOutputAccepting()

PropertyEndpoint tachyon::FirstOutputAccepting ( const NodeView & view,
PropertyEndpoint input,
int nodeIdx )

#include <gui_controls/gui_node_view_helpers.h>

The first output of node nodeIdx, top to bottom, that may feed Input; invalid when there is none.

◆ NodeAtCanvasPos()

int tachyon::NodeAtCanvasPos ( const NodeView & view,
float2 canvasPos )

#include <gui_controls/gui_node_view_helpers.h>

The node whose {pos, lastSize} rect holds canvasPos (node.pos space), the frontmost in view.ordering when several do; -1 when none does.

Only nodes in view.ordering count, as the view keeps it after each frame.

◆ ConnectSockets()

void tachyon::ConnectSockets ( NodeView & view,
PropertyEndpoint output,
PropertyEndpoint input )

#include <gui_controls/gui_node_view_helpers.h>

Wires output into Input without reporting to view.onEdit.

An input has one source, so its previous wire is replaced; the output keeps its others.

◆ BringNodeToFront()

void tachyon::BringNodeToFront ( std::vector< int > & ordering,
int n )

#include <gui_controls/gui_node_view_helpers.h>

Moves n to the front (last) of a z-order list, keeping the others' order.

◆ NodeViewScreenToCanvas() [1/2]

float2 tachyon::NodeViewScreenToCanvas ( const float3x2 & viewTransform,
IntRect canvasInnerRectScreen,
int2 screen )

#include <gui_controls/gui_node_view_helpers.h>

A screen point in node.pos space, for a canvas whose padding box is canvasInnerRectScreen (screen pixels) and whose pan/zoom is viewTransform (view.transform).

◆ NodeViewScreenToCanvas() [2/2]

float2 tachyon::NodeViewScreenToCanvas ( const NodeView & view,
int2 screen )

#include <gui_controls/gui_node_view_helpers.h>

A screen point (as events have them) in node.pos space, through the pan/zoom and place the view was last drawn with.

◆ NodeViewCanvasToScreen()

float2 tachyon::NodeViewCanvasToScreen ( const NodeView & view,
float2 canvasPos )

#include <gui_controls/gui_node_view_helpers.h>

A point in node.pos space on the screen, where the view last drew it: the other way round from NodeViewScreenToCanvas.

◆ ComputeNodesInMarquee()

std::unordered_set< ID > tachyon::ComputeNodesInMarquee ( std::span< const NodeModel > nodes,
IntRect canvasInnerRectScreen,
const float3x2 & viewTransform,
int2 marqueeStartScreen,
int2 marqueeCurrentScreen )

#include <gui_controls/gui_node_view_helpers.h>

Stable IDs of nodes whose {pos, lastSize} rect lies fully inside the marquee, compared in node.pos space (canvas inner-rect relative, before the content transform).

Nodes not laid out yet (zero lastSize) are skipped.

canvasInnerRectScreen : canvas padding box, SCREEN pixels. viewTransform : the pan/zoom part of the canvas's contentTransform (after T(innerSize/2)). marqueeStartScreen, marqueeCurrentScreen : marquee corners, SCREEN pixels.