public bool AddNode(Node node) { if (node == null || _graphNodes.Contains(node)) return false; _graphNodes.Insert(0, node); if (NodeAdded != null) { var eventArgs = new AcceptNodeEventArgs(node); NodeAdded(this, eventArgs); if (eventArgs.Cancel) { _graphNodes.Remove(node); return false; } } BringElementToFront(node); // FocusElement = node; UpdateRevisionIndex(); if (InvalidateViews != null) InvalidateViews(this, EventArgs.Empty); return true; }
private static NodeSize Measure(Graphics context, Node node) { if (node == null) return new NodeSize { BaseSize = SizeF.Empty, LeftPartWidth = 0, RightPartWidth = 0 }; SizeF size = Size.Empty; size.Height = (int)GraphConstants.TopHeight; bool[] firstItem = new bool[3] { true, true, true }; SizeF[] sizes = new SizeF[3] { size, size, size }; foreach (var item in EnumerateNodeItems(node)) { var side = GetSide(item); var itemSize = item.Measure(context); if (side != 1) itemSize = AdjustConnectorSize(itemSize); sizes[side].Width = Math.Max(sizes[side].Width, itemSize.Width); if (!firstItem[side]) sizes[side].Height += GraphConstants.ItemSpacing; sizes[side].Height += itemSize.Height; firstItem[side] = false; } size = sizes[1]; for (uint c = 0; c < 3; ++c) size.Height = Math.Max(size.Height, sizes[c].Height); size.Width += GraphConstants.NodeExtraWidth; size.Height += GraphConstants.BottomHeight; return new NodeSize { BaseSize = size, LeftPartWidth = sizes[0].Width, RightPartWidth = sizes[2].Width }; }
static IEnumerable<NodeItem> EnumerateNodeItems(Node node) { if (node == null) yield break; yield return node.titleItem; if (node.Collapsed) yield break; foreach (var item in node.Items) yield return item; }
public static void RenderConnections(Graphics graphics, Node node, HashSet<NodeConnection> skipConnections, bool showLabels) { foreach (var connection in node.connections.Reverse<NodeConnection>()) { if (connection == null) continue; if (skipConnections.Add(connection)) { var to = connection.To; var from = connection.From; RectangleF toBounds; RectangleF fromBounds; if (to == null) toBounds = new RectangleF(0.0f, 0.0f, 0.0f, 0.0f); else if (to.Node.Collapsed) toBounds = to.Node.inputBounds; else toBounds = to.bounds; if (from == null) fromBounds = new RectangleF(0.0f, 0.0f, 0.0f, 0.0f); else if (from.Node.Collapsed) fromBounds = from.Node.outputBounds; else fromBounds = from.bounds; var pt1 = ConnectorInterfacePoint(fromBounds, ConnectorType.Output); var pt2 = ConnectorInterfacePoint(toBounds, ConnectorType.Input); if (to != null && from != null) { float centerX; float centerY; using (var path = GetArrowLinePath(pt1.X, pt1.Y, pt2.X, pt2.Y, out centerX, out centerY, false)) { using (var brush = new SolidBrush(GetArrowLineColor(connection.state | RenderState.Connected))) { graphics.FillPath(brush, path); graphics.DrawPath(BorderPen, path); } connection.bounds = path.GetBounds(); } if (showLabels && !string.IsNullOrWhiteSpace(connection.Name)) { var center = new PointF(centerX, centerY); RenderLabel(graphics, connection, connection.Name, center, connection.state); } } else if (to!=null || from!=null) { // this is a basic connection. It just connects one connector to a // static string value (either a variable name or constant value) // Draw a small arrow from the connection label to the connector if (!string.IsNullOrWhiteSpace(connection.Name)) { PointF center; if (to != null) center = pt2; else if (from != null) center = pt1; else center = new PointF(); center.X -= 16; RenderLabel(graphics, connection, "= " + connection.Name, center, connection.state); } } } } }
public static void PerformLayout(Graphics graphics, Node node) { if (node == null) return; var size = Measure(graphics, node); var position = node.Location; node.bounds = new RectangleF(position, size); var path = new GraphicsPath(FillMode.Winding); var left = position.X; var top = position.Y; var right = position.X + size.Width; var bottom = position.Y + size.Height; node.inputConnectors.Clear(); node.outputConnectors.Clear(); //node.connections.Clear(); var itemPosition = position; itemPosition.X += (int)GraphConstants.HorizontalSpacing; if (node.Collapsed) { foreach (var item in node.Items) { var inputConnector = item.Input; if (inputConnector != null && inputConnector.Enabled) { inputConnector.bounds = Rectangle.Empty; node.inputConnectors.Add(inputConnector); } var outputConnector = item.Output; if (outputConnector != null && outputConnector.Enabled) { outputConnector.bounds = Rectangle.Empty; node.outputConnectors.Add(outputConnector); } } var itemSize = PreRenderItem(graphics, node.titleItem, itemPosition); var realHeight = itemSize.Height - GraphConstants.TopHeight; var connectorY = itemPosition.Y + (int)Math.Ceiling(realHeight / 2.0f); node.inputBounds = new RectangleF( left - GraphConstants.ConnectorWidthCollapsed, connectorY, GraphConstants.ConnectorWidthCollapsed, realHeight); node.outputBounds = new RectangleF( right - GraphConstants.ConnectorWidthCollapsed, connectorY, GraphConstants.ConnectorWidthCollapsed, realHeight); } else { node.inputBounds = Rectangle.Empty; node.outputBounds = Rectangle.Empty; foreach (var item in EnumerateNodeItems(node)) { var itemSize = PreRenderItem(graphics, item, itemPosition); var realHeight = itemSize.Height; var inputConnector = item.Input; if (inputConnector != null && inputConnector.Enabled) { if (itemSize.IsEmpty) { inputConnector.bounds = Rectangle.Empty; } else { inputConnector.bounds = new RectangleF( left - GraphConstants.ConnectorWidth, itemPosition.Y, GraphConstants.ConnectorWidth, realHeight); } node.inputConnectors.Add(inputConnector); } var outputConnector = item.Output; if (outputConnector != null && outputConnector.Enabled) { if (itemSize.IsEmpty) { outputConnector.bounds = Rectangle.Empty; } else { outputConnector.bounds = new RectangleF(right, itemPosition.Y, GraphConstants.ConnectorWidth, realHeight); } node.outputConnectors.Add(outputConnector); } itemPosition.Y += itemSize.Height + GraphConstants.ItemSpacing; } } node.itemsBounds = new RectangleF(left, top, right - left, bottom - top); }
public static SizeF Measure(Graphics context, Node node) { if (node == null) return SizeF.Empty; SizeF size = Size.Empty; size.Height = (int)GraphConstants.TopHeight; foreach (var item in EnumerateNodeItems(node)) { var itemSize = item.Measure(context); size.Width = Math.Max(size.Width, itemSize.Width); size.Height += GraphConstants.ItemSpacing + itemSize.Height; } if (node.Collapsed) size.Height -= GraphConstants.ItemSpacing; size.Width += GraphConstants.NodeExtraWidth; size.Height += GraphConstants.BottomHeight; return size; }
public AcceptNodeEventArgs(Node node, bool cancel) : base(cancel) { Node = node; }
public AcceptNodeEventArgs(Node node) { Node = node; }
public NodeEventArgs(Node node) { Node = node; }
public bool DisconnectAll(Node node) { bool modified = false; var connections = node.Connections.ToList(); foreach (var connection in connections) modified |= Disconnect(connection); return modified; }
static void Render(Graphics graphics, Node node, object context) { var size = node.bounds.Size; var position = node.bounds.Location; var cornerSize = GraphConstants.CornerSize; var left = position.X; var top = position.Y; var right = position.X + size.Width; var bottom = position.Y + size.Height; Brush brush; if ((node.state & RenderState.Dragging) != 0) { brush = DraggingBrush; } else if ((node.state & RenderState.Hover) != 0) { brush = HoverBrush; } else { brush = NormalBrush; } const Boolean roundedRectRendering = false; if (roundedRectRendering) { using (var path = new GraphicsPath(FillMode.Winding)) { path.AddArc(left, top, cornerSize, cornerSize, 180, 90); path.AddArc(right - cornerSize, top, cornerSize, cornerSize, 270, 90); path.AddArc(right - cornerSize, bottom - cornerSize, cornerSize, cornerSize, 0, 90); path.AddArc(left, bottom - cornerSize, cornerSize, cornerSize, 90, 90); path.CloseFigure(); graphics.FillPath(brush, path); graphics.DrawPath(BorderPen, path); } } else { var rect = new Rectangle((int)left, (int)top, (int)(right - left), (int)(bottom - top)); if (node.Collapsed) { graphics.FillRectangle(TitleAreaBrush, rect); } else { int titleHeight = (node.titleItem != null) ? (int)(node.titleItem.bounds.Height + GraphConstants.TopHeight) : 0; titleHeight = Math.Min((int)(bottom - top), titleHeight); var titleRect = new Rectangle((int)left, (int)top, (int)(right - left), titleHeight); var backgroundRect = new Rectangle((int)left, (int)top + titleHeight, (int)(right - left), (int)(bottom - top) - titleHeight); DrawShadow(graphics, rect); graphics.FillRectangle(brush, backgroundRect); if (titleHeight != 0) graphics.FillRectangle(TitleAreaBrush, titleRect); graphics.DrawRectangle(BorderPen, rect); } if ((node.state & RenderState.Focus) != 0) { // We're going to draw a outline around the edge of the entire node // This should be a thick line, with some bright color var outline = new Rectangle(rect.Left - 4, rect.Top - 4, rect.Width + 8, rect.Height + 8); graphics.DrawRectangle(FocusPen, outline); } } if (node.Collapsed) { RenderItem(graphics, new SizeF(node.bounds.Width - GraphConstants.NodeExtraWidth, 0), node.titleItem, node.titleItem.bounds.Location, context); } else { var minimumItemSize = new SizeF(node.bounds.Width - GraphConstants.NodeExtraWidth, 0); foreach (var item in EnumerateNodeItems(node)) { RenderItem(graphics, minimumItemSize, item, item.bounds.Location, context); } } foreach (var item in node.Items) // (don't use EnumerateItems because we want to show collapsed nodes) { // note -- the "connected" state is not stored in the retained state member // ... so if we want to colour the connectors based on if they are connected, // we need to look for connections now. var inputConnector = item.Input; if (inputConnector != null && inputConnector.Enabled && !inputConnector.bounds.IsEmpty) RenderConnector(graphics, inputConnector.bounds, inputConnector.state, ConnectorType.Input, inputConnector, node.Collapsed); var outputConnector = item.Output; if (outputConnector != null && outputConnector.Enabled && !outputConnector.bounds.IsEmpty) RenderConnector(graphics, outputConnector.bounds, outputConnector.state, ConnectorType.Output, outputConnector, node.Collapsed); } }
public static void PerformLayout(Graphics graphics, Node node) { if (node == null) return; var size = Measure(graphics, node); var position = node.Location; node.bounds = new RectangleF(position, size.BaseSize); position.Y += (int)GraphConstants.TopHeight; var path = new GraphicsPath(FillMode.Winding); var left = position.X; var top = position.Y; var right = position.X + size.BaseSize.Width; var bottom = position.Y + size.BaseSize.Height; var itemPosition = position; itemPosition.X += (int)GraphConstants.HorizontalSpacing; if (node.Collapsed) { uint inputConnectorCount = 0, outputConnectorCount = 0; foreach (var item in node.Items) { if (item.Input != null && item.Input.Enabled) ++inputConnectorCount; if (item.Output != null && item.Output.Enabled) ++outputConnectorCount; } uint inputConnectorIndex = 0, outputConnectorIndex = 0; foreach (var item in node.Items) { if (item.Input != null && item.Input.Enabled) { item.Input.bounds = CollapsedInputConnector(node.bounds, inputConnectorIndex, inputConnectorCount); ++inputConnectorIndex; } if (item.Output != null && item.Output.Enabled) { item.Output.bounds = CollapsedOutputConnector(node.bounds, outputConnectorIndex, outputConnectorCount); ++outputConnectorIndex; } } var itemSize = PreRenderItem(graphics, node.titleItem, itemPosition); } else { PointF[] positions = new PointF[] { itemPosition, itemPosition, itemPosition }; float[] widths = new float[] { size.LeftPartWidth, size.BaseSize.Width, size.RightPartWidth }; foreach (var item in EnumerateNodeItems(node)) { var inputConnector = item.Input; var outputConnector = item.Output; var side = GetSide(item); var itemSize = PreRenderItem(graphics, item, positions[side]); var realHeight = itemSize.Height; if (inputConnector != null && inputConnector.Enabled) { if (itemSize.IsEmpty) { inputConnector.bounds = Rectangle.Empty; } else { inputConnector.bounds = new RectangleF( left - widths[side], positions[side].Y, widths[side], realHeight); } } if (outputConnector != null && outputConnector.Enabled) { if (itemSize.IsEmpty) { outputConnector.bounds = Rectangle.Empty; } else { outputConnector.bounds = new RectangleF( right, positions[side].Y, widths[side], realHeight); } } positions[side].Y += itemSize.Height + GraphConstants.ItemSpacing; } } }
public static Node CreateNode(ShaderFragmentArchive.Function fn, String archiveName, HyperGraph.GraphControl graphControl, ShaderDiagram.Document doc) { var node = new Node(fn.Name); node.Tag = new ShaderProcedureNodeTag(archiveName); node.AddItem(new ShaderFragmentPreviewItem(graphControl, doc)); foreach (var param in fn.InputParameters) { node.AddItem(new ShaderFragmentNodeItem(param.Name, param.Type, archiveName + ":" + param.Name, true, false)); } foreach (var output in fn.Outputs) { node.AddItem(new ShaderFragmentNodeItem(output.Name, output.Type, archiveName + ":" + output.Name, false, true)); } return node; }
public static Node CreateEmptyParameterNode(ShaderFragmentArchive.Parameter.SourceType sourceType, String archiveName, String title) { var node = new Node(title); node.Tag = new ShaderParameterNodeTag(archiveName); int selectedIndex = 0; List<String> typeNames = new List<String>(); foreach (var e in Enum.GetValues(typeof(ShaderFragmentArchive.Parameter.SourceType)).Cast<ShaderFragmentArchive.Parameter.SourceType>()) { if (e == sourceType) { selectedIndex = typeNames.Count; } typeNames.Add(AsString(e)); } var typeSelection = new HyperGraph.Items.NodeDropDownItem(typeNames.ToArray(), selectedIndex, false, false); node.AddItem(typeSelection); typeSelection.SelectionChanged += ParameterNodeTypeChanged; return node; }
static void Render(Graphics graphics, Node node) { var size = node.bounds.Size; var position = node.bounds.Location; var cornerSize = GraphConstants.CornerSize; var left = position.X; var top = position.Y; var right = position.X + size.Width; var bottom = position.Y + size.Height; Brush brush; if ((node.state & (RenderState.Dragging | RenderState.Focus)) != 0) { brush = FocusBrush; } else if ((node.state & RenderState.Hover) != 0) { brush = HoverBrush; } else { brush = NormalBrush; } const Boolean roundedRectRendering = false; if (roundedRectRendering) { using (var path = new GraphicsPath(FillMode.Winding)) { path.AddArc(left, top, cornerSize, cornerSize, 180, 90); path.AddArc(right - cornerSize, top, cornerSize, cornerSize, 270, 90); path.AddArc(right - cornerSize, bottom - cornerSize, cornerSize, cornerSize, 0, 90); path.AddArc(left, bottom - cornerSize, cornerSize, cornerSize, 90, 90); path.CloseFigure(); graphics.FillPath(brush, path); graphics.DrawPath(BorderPen, path); } } else { var rect = new Rectangle((int)left, (int)top, (int)(right - left), (int)(bottom - top)); int titleSize = Math.Min((int)(bottom - top), GraphConstants.TopHeight + GraphConstants.TitleHeight); var titleRect = new Rectangle((int)left, (int)top, (int)(right - left), titleSize); var backgroundRect = new Rectangle((int)left, (int)top + titleSize, (int)(right - left), (int)(bottom - top) - titleSize); DrawShadow(graphics, rect); graphics.FillRectangle(brush, backgroundRect); graphics.FillRectangle(TitleAreaBrush, titleRect); graphics.DrawRectangle(BorderPen, rect); } /* if (!node.Collapsed) graphics.DrawLine(Pens.Black, left + GraphConstants.ConnectorSize, node.titleItem.bounds.Bottom - GraphConstants.ItemSpacing, right - GraphConstants.ConnectorSize, node.titleItem.bounds.Bottom - GraphConstants.ItemSpacing); */ var itemPosition = position; itemPosition.X += (int)GraphConstants.HorizontalSpacing; itemPosition.Y += (int)GraphConstants.TopHeight; if (node.Collapsed) { // bool inputConnected = false; // var inputState = RenderState.None; // var outputState = node.outputState; // foreach (var connection in node.connections) // { // if (connection.To.Node == node) // { // inputState |= connection.state; // inputConnected = true; // } // if (connection.From.Node == node) // outputState |= connection.state | RenderState.Connected; // } RenderItem(graphics, new SizeF(node.bounds.Width - GraphConstants.NodeExtraWidth, 0), node.titleItem, itemPosition); // if (node.inputConnectors.Count > 0) // RenderConnector(graphics, node.inputBounds, node.inputState, ConnectorType.Input); // if (node.outputConnectors.Count > 0) // RenderConnector(graphics, node.outputBounds, outputState, ConnectorType.Output); //if (inputConnected) // RenderArrow(graphics, node.inputBounds, inputState); } else { node.inputBounds = Rectangle.Empty; node.outputBounds = Rectangle.Empty; var minimumItemSize = new SizeF(node.bounds.Width - GraphConstants.NodeExtraWidth, 0); foreach (var item in EnumerateNodeItems(node)) { RenderItem(graphics, minimumItemSize, item, itemPosition); var inputConnector = item.Input; if (inputConnector != null && inputConnector.Enabled) { if (!inputConnector.bounds.IsEmpty) { var state = RenderState.None; var connected = false; foreach (var connection in node.connections) { if (connection.To == inputConnector) { state |= connection.state; connected = true; } } RenderConnector(graphics, inputConnector.bounds, inputConnector.state, ConnectorType.Input, inputConnector); if (connected) RenderArrow(graphics, inputConnector.bounds, state); } } var outputConnector = item.Output; if (outputConnector != null && outputConnector.Enabled) { if (!outputConnector.bounds.IsEmpty) { var state = outputConnector.state; foreach (var connection in node.connections) { if (connection.From == outputConnector) state |= connection.state | RenderState.Connected; } RenderConnector(graphics, outputConnector.bounds, state, ConnectorType.Output, outputConnector); } } itemPosition.Y += item.bounds.Height + GraphConstants.ItemSpacing; } } }
private static NodeItem FindOrCreateNodeItem(Node node, Func<NodeItem, bool> predicate, Func<NodeItem> creator) { foreach (var i in node.Items) if (predicate(i)) return i; var newItem = creator(); node.AddItem(newItem); return newItem; }
private void MatchVisualNode(HyperGraph.Node dst, ShaderPatcherLayer.VisualNode src) { dst.Location = src.Location; dst.Collapsed = src.State == ShaderPatcherLayer.VisualNode.StateType.Collapsed; }
public void RemoveNode(Node node) { if (node == null) return; if (NodeRemoving != null) { var eventArgs = new AcceptNodeEventArgs(node); NodeRemoving(this, eventArgs); if (eventArgs.Cancel) return; } // if (HasFocus(node)) // FocusElement = null; DisconnectAll(node); _graphNodes.Remove(node); UpdateRevisionIndex(); if (InvalidateViews != null) InvalidateViews(this, EventArgs.Empty); if (NodeRemoved != null) NodeRemoved(this, new NodeEventArgs(node)); }