/// <summary> /// Visits all the nodes in a graph. Used when the maximum node identifier is known /// </summary> /// <param name="startNodes">Initial nodes</param> /// <param name="visitor">Visitor object</param> /// <param name="maxNodeId">Maximum node identifier value in the graph</param> /// <remarks> /// A node is only visited once all its input nodes have been visited first. /// </remarks> public static void Walk( IEnumerable<IGraphNode> startNodes, IGraphNodeVisitor visitor, int maxNodeId ) { if ( startNodes == null ) { throw new ArgumentNullException( "startNodes" ); } if ( visitor == null ) { throw new ArgumentNullException( "visitor" ); } visitor.StartVisiting( ); NodeStatus[] nodeStatuses = new NodeStatus[ 32 ]; Queue<IGraphNode> nodeQueue = new Queue<IGraphNode>( ); Enqueue( nodeQueue, startNodes, ref nodeStatuses ); try { while ( nodeQueue.Count > 0 ) { IGraphNode node = nodeQueue.Dequeue( ); if ( nodeStatuses[ node.Id ] == NodeStatus.Visited ) { // Guards against cyclic graphs continue; } // Check that the current node can be visited if ( !CheckNodeStatus( nodeQueue, node, ref nodeStatuses ) ) { // It can't (an input node has not been visited yet) nodeQueue.Enqueue( node ); continue; } // Enqueue all output nodes of the current node Enqueue( nodeQueue, node.OutputNodes, ref nodeStatuses ); // Visit the current node visitor.Visit( node ); nodeStatuses[ node.Id ] = NodeStatus.Visited; } } finally { visitor.FinishVisiting( ); } }
/// <summary> /// Visits all the nodes in a render node graph. /// </summary> /// <param name="startNodes">Initial nodes</param> /// <param name="visitor">Visitor object</param> /// <remarks> /// A node is only visited once all its input nodes have been visited first. /// </remarks> public static void Walk( IGraphNode[] startNodes, IGraphNodeVisitor visitor ) { Walk( startNodes, visitor, 32 ); }