public sealed class NodeCanvasAn 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 OverscanHow much of the canvas beyond each edge is still realised, as a fraction of it.
protected override string TagNameThe element name this type answers to when a caller does not choose one.
protected override bool AcceptsFocusWhether the focus can rest on this kind of control at all.
protected override AccessibleRole NativeRolepublic NodeGraph GraphThe nodes, wires and groups being shown.
public UiElement SurfaceWhere the nodes go.
public UiElement GroupLayerWhere the group boxes go, under the wires.
public NodeWireLayer WireLayerThe layer the wires are drawn on.
public NodeOverlayLayer OverlayLayerThe layer shaded regions are drawn on, under the nodes.
public List<GraphOverlayRegion> OverlayThe regions that layer draws. Write into it and call Refresh.
public UiElement MarqueeThe rubber band, hidden unless one is being dragged.
public NodeMinimap MinimapThe overview in the corner.
public IReadOnlyList<NodeItem> ItemsThe node elements that exist, including the parked ones.
public IReadOnlyList<GraphNode> VisibleThe nodes that are realised, in order.
public IReadOnlyCollection<GraphNode> SelectionWhat is selected.
public GraphNode? CursorThe node the keyboard is on, which is not the same thing as the selection.
public Vector2 Panpublic float Zoompublic float MinimumZoompublic float MaximumZoompublic float GridSizepublic bool SnapToGridpublic bool MultiSelectpublic GraphOrientation OrientationWhich way the graph reads, and therefore which edge a wire leaves a node by.
public float WireThicknesspublic float WireCurvaturepublic float WireHitRadiusHow far from a wire a press still counts as a press on it, in screen pixels.
public GraphWire? SelectedWireThe wire the pointer chose, if one is chosen.
public GraphPort? PendingPortThe port a wire is being dragged from, if one is.
public Vector2 PendingPointWhere that wire's loose end is, in document space.
public Color4 WireColorThe colour of a wire, from --wire-color.
public Color4 WireActiveColorThe colour of a selected or pending one, from --wire-active-color.
public float HeaderHeightHow tall a node's title bar is, in graph units, from --node-header.
public float PortPitchHow far apart the ports are down a node's side, from --port-pitch.
public float NodePaddingHow much room is left under the last port, from --node-padding.
public float NodeFontSizeA node's font size at a zoom of one, from --node-font-size.
public Rectangle ViewWhat the canvas can see, in graph units.
public static readonly UiPropertyKey PanPropertyIdentity for Pan.
public static readonly UiPropertyKey ZoomPropertyIdentity for Zoom.
public static readonly UiPropertyKey MinimumZoomPropertyIdentity for MinimumZoom.
public static readonly UiPropertyKey MaximumZoomPropertyIdentity for MaximumZoom.
public static readonly UiPropertyKey GridSizePropertyIdentity for GridSize.
public static readonly UiPropertyKey SnapToGridPropertyIdentity for SnapToGrid.
public static readonly UiPropertyKey MultiSelectPropertyIdentity for MultiSelect.
public static readonly UiPropertyKey WireThicknessPropertyIdentity for WireThickness.
public static readonly UiPropertyKey WireCurvaturePropertyIdentity for WireCurvature.
Events (7)
public Action<NodeCanvas, GraphWire?>? WireSelectionChangedRaised after SelectedWire changes, with what is chosen now.
public Action<NodeCanvas>? SelectionChangedRaised when the selection changes.
public Action<NodeCanvas>? NodesMovedRaised after a drag has moved some nodes.
public Action<NodeCanvas, GraphNode>? ActivatedRaised when a node is double-clicked.
public Action<NodeCanvas, GraphWire>? ConnectedRaised after a wire is made by dragging.
public Action<NodeCanvas, GraphPort>? PortEditedRaised after a value was typed into a port's inline editor.
public Action<NodeCanvas, GraphNode, Vector2>? DroppedRaised 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