Vixen
dd8b0a81
csharp
public sealed class NodeCanvas

An infinite canvas of nodes joined by wires.

No guide page documents this yet — the page shows what the code says about itself.

Remarks

Zoom is arithmetic, not a transform — and that is now a choice rather than the only road. ⚠ This remark used to say there is no transform property; there is. TransformReader reads transform, rotate and scale, the matrix reaches a composited group's four vertices and the hit test inverts it. What survives is the reason that was never about the plumbing: a scaled subtree scales the glyph atlas with it, and text sampled from a field baked at one size and stretched to another is worse at every zoom than text reshaped at the size it is actually drawn at. A transform also leaves layout alone by specification, so the box this canvas culls against would keep its unzoomed size and the pool would realise the wrong nodes. So the canvas converts graph coordinates to screen coordinates itself and writes the answer as a position and a size, and the node's font-size goes with it so that its insides scale too. Everything in the theme below a node is therefore written in em, which is what makes one number carry the whole scale.

⚠ A wire's endpoint is arithmetic too, from the node's rectangle and the port's index rather than from a laid-out port's box. A graph is mostly off screen, the node at the far end of a wire usually has no elements at all, and an endpoint read from layout would collapse to the origin exactly when the wire leaves the viewport. It also means a wire is never a frame behind the node it is attached to, which a laid-out endpoint always is.

Culled by a pool, like TreeView's rows: the elements are the nodes that intersect the viewport plus a margin, rebound as the canvas pans. Ten thousand nodes is ten thousand GraphNodes and a few dozen NodeItems.

A resize is noticed rather than announced. What the canvas realises is what its own box reaches, which is a result of the layout pass — so Control.WhenResized hangs Refresh on LayoutFinished and it runs on the passes where the box actually moved. Panning and zooming realise for themselves, because those are writes this control makes and can see.

Fields and properties (46)

  • public const float Overscan

    How much of the canvas beyond each edge is still realised, as a fraction of it.

  • protected override string TagName

    The element name this type answers to when a caller does not choose one.

  • protected override bool AcceptsFocus

    Whether the focus can rest on this kind of control at all.

  • protected override AccessibleRole NativeRole
  • public NodeGraph Graph

    The nodes, wires and groups being shown.

  • public UiElement Surface

    Where the nodes go.

  • public UiElement GroupLayer

    Where the group boxes go, under the wires.

  • public NodeWireLayer WireLayer

    The layer the wires are drawn on.

  • public NodeOverlayLayer OverlayLayer

    The layer shaded regions are drawn on, under the nodes.

  • public List<GraphOverlayRegion> Overlay

    The regions that layer draws. Write into it and call Refresh.

  • public UiElement Marquee

    The rubber band, hidden unless one is being dragged.

  • public NodeMinimap Minimap

    The overview in the corner.

  • public IReadOnlyList<NodeItem> Items

    The node elements that exist, including the parked ones.

  • public IReadOnlyList<GraphNode> Visible

    The nodes that are realised, in order.

  • public IReadOnlyCollection<GraphNode> Selection

    What is selected.

  • public GraphNode? Cursor

    The node the keyboard is on, which is not the same thing as the selection.

  • public Vector2 Pan
  • public float Zoom
  • public float MinimumZoom
  • public float MaximumZoom
  • public float GridSize
  • public bool SnapToGrid
  • public bool MultiSelect
  • public GraphOrientation Orientation

    Which way the graph reads, and therefore which edge a wire leaves a node by.

  • public float WireThickness
  • public float WireCurvature
  • public float WireHitRadius

    How far from a wire a press still counts as a press on it, in screen pixels.

  • public GraphWire? SelectedWire

    The wire the pointer chose, if one is chosen.

  • public GraphPort? PendingPort

    The port a wire is being dragged from, if one is.

  • public Vector2 PendingPoint

    Where that wire's loose end is, in document space.

  • public Color4 WireColor

    The colour of a wire, from --wire-color.

  • public Color4 WireActiveColor

    The colour of a selected or pending one, from --wire-active-color.

  • public float HeaderHeight

    How tall a node's title bar is, in graph units, from --node-header.

  • public float PortPitch

    How far apart the ports are down a node's side, from --port-pitch.

  • public float NodePadding

    How much room is left under the last port, from --node-padding.

  • public float NodeFontSize

    A node's font size at a zoom of one, from --node-font-size.

  • public Rectangle View

    What the canvas can see, in graph units.

  • public static readonly UiPropertyKey PanProperty

    Identity for Pan.

  • public static readonly UiPropertyKey ZoomProperty

    Identity for Zoom.

  • public static readonly UiPropertyKey MinimumZoomProperty

    Identity for MinimumZoom.

  • public static readonly UiPropertyKey MaximumZoomProperty

    Identity for MaximumZoom.

  • public static readonly UiPropertyKey GridSizeProperty

    Identity for GridSize.

  • public static readonly UiPropertyKey SnapToGridProperty

    Identity for SnapToGrid.

  • public static readonly UiPropertyKey MultiSelectProperty

    Identity for MultiSelect.

  • public static readonly UiPropertyKey WireThicknessProperty

    Identity for WireThickness.

  • public static readonly UiPropertyKey WireCurvatureProperty

    Identity for WireCurvature.

Events (7)

  • public Action<NodeCanvas, GraphWire?>? WireSelectionChanged

    Raised after SelectedWire changes, with what is chosen now.

  • public Action<NodeCanvas>? SelectionChanged

    Raised when the selection changes.

  • public Action<NodeCanvas>? NodesMoved

    Raised after a drag has moved some nodes.

  • public Action<NodeCanvas, GraphNode>? Activated

    Raised when a node is double-clicked.

  • public Action<NodeCanvas, GraphWire>? Connected

    Raised after a wire is made by dragging.

  • public Action<NodeCanvas, GraphPort>? PortEdited

    Raised after a value was typed into a port's inline editor.

  • public Action<NodeCanvas, GraphNode, Vector2>? Dropped

    Raised when a node drag ends, with where in graph space it was let go.

Methods (29)

  • protected override void OnCreated()

    Builds whatever this element is made of, once, as it joins a document.

  • protected override void OnDraw(DrawContext context)

    Draws the grid, under everything.

  • public Vector2 ToScreen(Vector2 point)

    Where a graph point is, in document space.

  • public Vector2 ToGraph(float x, float y)

    Where a document-space point is, in graph units.

  • public float HeightOf(GraphNode node)

    How tall a node is, in graph units.

  • public Rectangle RectOf(GraphNode node)

    Where a node is, in graph units.

  • public Rectangle RectOf(GraphGroup group)

    Where a group's box is, in graph units.

  • public Vector2 AnchorOf(GraphPort port)

    Where a wire attaches to a port, in graph units.

  • public NodeItem? ItemOf(GraphNode node)

    The element showing a node, if it has one.

  • public NodeGroupView? ViewOf(GraphGroup group)

    The element showing a group, if there is one.

  • public void Refresh()

    Brings the elements back into agreement with the graph and the view.

  • public static (Vector2 First, Vector2 Second) Handles(NodeCanvas canvas, Vector2 from, Vector2 to)

    The two handles of the cubic a wire is drawn as, in the space its ends are in.

  • public GraphWire? WireAt(float x, float y)

    The wire under a point, if the point is near enough to one.

  • public void SelectWire(GraphWire? wire)

    Chooses a wire, or chooses none.

  • public void Select(GraphNode? node, ModifierKeys modifiers = None)

    Selects a node, or adds it to or removes it from the selection.

  • public void SelectAll()

    Selects everything.

  • public void ClearSelection()

    Selects nothing.

  • public void ZoomToFit(bool selectionOnly = false, float margin = 32)

    Pans and zooms until everything fits, or until the selection does.

  • public bool EnsureVisible(GraphNode node)

    Pans the least it can until a node is inside the view.

  • public void Reveal(GraphNode node, float margin = 32)

    Pans the least that puts a node inside the view.

  • public void ClearPan()

    Unsets Pan, so it takes its default or its ancestor's value again.

  • public void ClearZoom()

    Unsets Zoom, so it takes its default or its ancestor's value again.

  • public void ClearMinimumZoom()

    Unsets MinimumZoom, so it takes its default or its ancestor's value again.

  • public void ClearMaximumZoom()

    Unsets MaximumZoom, so it takes its default or its ancestor's value again.

  • public void ClearGridSize()

    Unsets GridSize, so it takes its default or its ancestor's value again.

  • public void ClearSnapToGrid()

    Unsets SnapToGrid, so it takes its default or its ancestor's value again.

  • public void ClearMultiSelect()

    Unsets MultiSelect, so it takes its default or its ancestor's value again.

  • public void ClearWireThickness()

    Unsets WireThickness, so it takes its default or its ancestor's value again.

  • public void ClearWireCurvature()

    Unsets WireCurvature, so it takes its default or its ancestor's value again.

Used by (22)

  • EditorShellSceneVixen.Benchmarks.Ui
  • SceneVixen.Benchmarks.Ui
  • AccessibilityTreeTestsVixen.Ui.Controls.Advanced.Tests
  • EditorShellBudgetTestsVixen.Ui.Controls.Advanced.Tests
  • NodeCanvasKeyboardTestsVixen.Ui.Controls.Advanced.Tests
  • NodeCanvasTestsVixen.Ui.Controls.Advanced.Tests
  • NodeMinimapVixen.Ui.Controls.Advanced
  • NodeOverlayLayerVixen.Ui.Controls.Advanced
  • NodeWireLayerVixen.Ui.Controls.Advanced
  • ResizeTestsVixen.Ui.Controls.Advanced.Tests
  • AgentFollowWiringTestsVixen.Editor.App.Tests
  • BehaviorTreeProjectionVixen.Editor.Ai
  • BehaviorTreeViewVixen.Editor.AssetEditors
  • GoapDomainViewVixen.Editor.AssetEditors
  • LiveTreeCanvasTestsVixen.Editor.AssetEditors.Tests
  • NodeGraphViewVixen.Editor.NodeGraph
  • NodePreviewLayerVixen.Editor.NodeGraph
  • PortValueTestsVixen.Editor.NodeGraph.Tests
  • TextureGraphPanelTestsVixen.Editor.Texturing.Tests
  • TextureGraphUndoTestsVixen.Editor.Texturing.Tests
  • ViewFixtureVixen.Editor.NodeGraph.Tests
  • ViewTestsVixen.Editor.NodeGraph.Tests