/// <summary>
	/// Get the composed list of child node IDs. 
	/// </summary>
	/// <param name="parentNodeID">Parent node ID</param>
	/// <param name="nodeTypeFilter">Node type by which to filter the children</param>
	/// <param name="nodeFlagFilter">Node flags by which to filter the children</param>
	/// <param name="bRecursive">Whether or not to compose the list recursively</param>
	/// <param name="childNodeIDs">Array to store the child node IDs.
	/// <returns>True if successfully retrieved the child node list</returns>
	public static bool GetComposedChildNodeList(HEU_SessionBase session, HAPI_NodeId parentNodeID, HAPI_NodeTypeBits nodeTypeFilter, HAPI_NodeFlagsBits nodeFlagFilter, bool bRecursive, out HAPI_NodeId[] childNodeIDs)
	{
	    childNodeIDs = null;
	    // First compose the internal list and get the count, then get the actual list.
	    int count = -1;
	    bool bResult = session.ComposeChildNodeList(parentNodeID, nodeTypeFilter, nodeFlagFilter, bRecursive, ref count);
	    if (bResult)
	    {
		childNodeIDs = new HAPI_NodeId[count];
		if (count > 0)
		{
		    return session.GetComposedChildNodeList(parentNodeID, childNodeIDs, count);
		}
		else
		{
		    return true;
		}
	    }
	    return false;
	}
	/// <summary>
	/// Find all TOP networks from linked HDA, as well as the TOP nodes within, and populate internal state.
	/// </summary>
	/// <returns>True if successfully populated data</returns>
	public bool PopulateTOPNetworks()
	{
	    HEU_SessionBase session = GetHAPISession();

	    HAPI_NodeInfo assetInfo = new HAPI_NodeInfo();
	    if (!session.GetNodeInfo(_assetID, ref assetInfo, true))
	    {
		return false;
	    }

	    // Get all networks within the asset, recursively.
	    // The reason to get all networks is because there can be TOP network SOP which isn't a TOP network type, but rather a SOP type
	    int nodeCount = 0;
	    if (!session.ComposeChildNodeList(_assetID, (int)(HAPI_NodeType.HAPI_NODETYPE_ANY), (int)HAPI_NodeFlags.HAPI_NODEFLAGS_NETWORK, true, ref nodeCount))
	    {
		return false;
	    }

	    HAPI_NodeId[] nodeIDs = new HAPI_NodeId[nodeCount];
	    if (!session.GetComposedChildNodeList(_assetID, nodeIDs, nodeCount))
	    {
		return false;
	    }

	    // Holds TOP networks in use
	    List<HEU_TOPNetworkData> newNetworks = new List<HEU_TOPNetworkData>();

	    // For each network, only add those with TOP child nodes (therefore guaranteeing only TOP networks are added).
	    for (int t = 0; t < nodeCount; ++t)
	    {
		HAPI_NodeInfo topNodeInfo = new HAPI_NodeInfo();
		if (!session.GetNodeInfo(nodeIDs[t], ref topNodeInfo))
		{
		    return false;
		}

		string nodeName = HEU_SessionManager.GetString(topNodeInfo.nameSH, session);
		//Debug.LogFormat("Top node: {0} - {1}", nodeName, topNodeInfo.type);

		// Skip any non TOP or SOP networks
		if (topNodeInfo.type != HAPI_NodeType.HAPI_NODETYPE_TOP && topNodeInfo.type != HAPI_NodeType.HAPI_NODETYPE_SOP)
		{
		    continue;
		}

		// Get list of all TOP nodes within this network.
		HAPI_NodeId[] topNodeIDs = null;
		if (!HEU_SessionManager.GetComposedChildNodeList(session, nodeIDs[t], (int)(HAPI_NodeType.HAPI_NODETYPE_TOP), (int)HAPI_NodeFlags.HAPI_NODEFLAGS_TOP_NONSCHEDULER, true, out topNodeIDs))
		{
		    continue;
		}

		// Skip networks without TOP nodes
		if (topNodeIDs == null || topNodeIDs.Length == 0)
		{
		    continue;
		}

		// Get any filter tags from spare parms on TOP nodes
		TOPNodeTags tags = new TOPNodeTags();
		if (_useHEngineData)
		{
		    ParseHEngineData(session, nodeIDs[t], ref topNodeInfo, ref tags);

		    if (!tags._show)
		    {
			continue;
		    }
		}
		else
		{
		    tags._show = true;
		}

		HEU_TOPNetworkData topNetworkData = GetTOPNetworkByName(nodeName, _topNetworks);
		if (topNetworkData == null)
		{
		    topNetworkData = new HEU_TOPNetworkData();
		}
		else
		{
		    // Found previous TOP network, so remove it from old list. This makes
		    // sure to not remove it when cleaning up old nodes.
		    _topNetworks.Remove(topNetworkData);
		}

		newNetworks.Add(topNetworkData);

		topNetworkData._nodeID = nodeIDs[t];
		topNetworkData._nodeName = nodeName;
		topNetworkData._parentName = _assetName;
		topNetworkData._tags = tags;

		PopulateTOPNodes(session, topNetworkData, topNodeIDs, _useHEngineData);
	    }

	    // Clear old TOP networks and nodes
	    ClearAllTOPData();
	    _topNetworks = newNetworks;

	    // Update latest TOP network names
	    _topNetworkNames = new string[_topNetworks.Count];
	    for (int i = 0; i < _topNetworks.Count; ++i)
	    {
		_topNetworkNames[i] = _topNetworks[i]._nodeName;
	    }

	    return true;
	}
        public static HAPI_NodeId [] GetNonBypassedNetworkIds(HEU_SessionBase session, HAPI_NodeId assetId)
        {
            if (assetId < 0)
            {
                return(null);
            }

            // Get all network nodes recursively
            // Getting all networks because TOP nework SOPs aren't considered being of TTOP network type, but SOP type
            int networkNodeCount = 0;

            if (!session.ComposeChildNodeList(assetId, (int)HAPI_NodeType.HAPI_NODETYPE_ANY, (int)HAPI_NodeFlags.HAPI_NODEFLAGS_NETWORK, true, ref networkNodeCount, false))
            {
                return(null);
            }

            if (networkNodeCount <= 0)
            {
                return(null);;
            }

            HAPI_NodeId [] allNetworkNodeIds = new HAPI_NodeId[networkNodeCount];
            if (!session.GetComposedChildNodeList(assetId, allNetworkNodeIds, networkNodeCount, false))
            {
                return(null);
            }


            int byPassedTOPNetNodeCount = 0;

            if (!session.ComposeChildNodeList(assetId,
                                              (int)HAPI_NodeType.HAPI_NODETYPE_ANY, (int)(HAPI_NodeFlags.HAPI_NODEFLAGS_NETWORK | HAPI_NodeFlags.HAPI_NODEFLAGS_BYPASS),
                                              true, ref byPassedTOPNetNodeCount, false))
            {
                return(allNetworkNodeIds);
            }

            // Get only non bypassed nodes
            if (byPassedTOPNetNodeCount > 0)
            {
                HAPI_NodeId[] allBypassedTOPNetNodeIDs = new HAPI_NodeId[byPassedTOPNetNodeCount];
                if (!session.GetComposedChildNodeList(assetId, allBypassedTOPNetNodeIDs, byPassedTOPNetNodeCount, false))
                {
                    return(allNetworkNodeIds);
                }

                int lastIndex = allNetworkNodeIds.Length - 1;
                for (int idx = allNetworkNodeIds.Length - 1; idx >= 0; idx--)
                {
                    if (System.Array.Exists <HAPI_NodeId>(allBypassedTOPNetNodeIDs, (HAPI_NodeId id) => id == allNetworkNodeIds[idx]))
                    {
                        // Remove idx by swapping to end and resizing
                        int tmp = allNetworkNodeIds[idx];
                        allNetworkNodeIds[idx]       = allNetworkNodeIds[lastIndex];
                        allNetworkNodeIds[lastIndex] = tmp;
                        lastIndex--;
                    }
                }

                System.Array.Resize <HAPI_NodeId>(ref allNetworkNodeIds, lastIndex + 1);
            }

            return(allNetworkNodeIds);
        }