示例#1
0
		private void DisconnectAndDestroyInputAssets(HEU_SessionBase session)
		{
			DisconnectInputAssetActor(session);

			_inputAsset = null;

			if (session != null)
			{
				foreach (HAPI_NodeId nodeID in _inputObjectsConnectedAssetIDs)
				{
					session.DeleteNode(nodeID);
				}

				if (_connectedNodeID != HEU_Defines.HEU_INVALID_NODE_ID && HEU_HAPIUtility.IsNodeValidInHoudini(session, _connectedNodeID))
				{
					// We'll delete the parent Object because we presume to have created the SOP/merge ourselves.
					// If the parent Object doesn't get deleted, it sticks around unused.
					HAPI_NodeInfo parentNodeInfo = new HAPI_NodeInfo();
					if(session.GetNodeInfo(_connectedNodeID, ref parentNodeInfo))
					{
						if (parentNodeInfo.parentId != HEU_Defines.HEU_INVALID_NODE_ID)
						{
							session.DeleteNode(parentNodeInfo.parentId);
						}
					}
				}
			}

			_inputObjectsConnectedAssetIDs.Clear();
			_connectedNodeID = HEU_Defines.HEU_INVALID_NODE_ID;
		}
示例#2
0
	public static void CreateNodeSync(HEU_SessionBase session, string opName, string nodeNabel)
	{
	    if (session == null)
	    {
		session = HEU_SessionManager.GetDefaultSession();
	    }
	    if (session == null || !session.IsSessionValid())
	    {
		return;
	    }

	    HAPI_NodeId newNodeID = -1;
	    HAPI_NodeId parentNodeId = -1;

	    if (!session.CreateNode(parentNodeId, opName, nodeNabel, true, out newNodeID))
	    {
		Debug.LogErrorFormat("Unable to create merge SOP node for connecting input assets.");
		return;
	    }

	    if (parentNodeId == -1)
	    {
		// When creating a node without a parent, for SOP nodes, a container
		// geometry object will have been created by HAPI.
		// In all cases we want to use the node ID of that object container
		// so the below code sets the parent's node ID.

		// But for SOP/subnet we actually do want the subnet SOP node ID
		// hence the useSOPNodeID argument here is to override it.
		bool useSOPNodeID = opName.Equals("SOP/subnet");

		HAPI_NodeInfo nodeInfo = new HAPI_NodeInfo();
		if (!session.GetNodeInfo(newNodeID, ref nodeInfo))
		{
		    return;
		}

		if (nodeInfo.type == HAPI_NodeType.HAPI_NODETYPE_SOP)
		{
		    if (!useSOPNodeID)
		    {
			newNodeID = nodeInfo.parentId;
		    }
		}
		else if (nodeInfo.type != HAPI_NodeType.HAPI_NODETYPE_OBJ)
		{
		    Debug.LogErrorFormat("Unsupported node type {0}", nodeInfo.type);
		    return;
		}
	    }

	    GameObject newGO = new GameObject(nodeNabel);

	    HEU_NodeSync nodeSync = newGO.AddComponent<HEU_NodeSync>();
	    nodeSync.InitializeFromHoudini(session, newNodeID, nodeNabel, "");
	}
	public bool IsValidStore(HEU_SessionBase session)
	{
	    HAPI_NodeInfo nodeInfo = new HAPI_NodeInfo();
	    if (session.GetNodeInfo(_geoID, ref nodeInfo, false))
	    {
		return nodeInfo.isValid;
	    }
	    else
	    {
		return false;
	    }
	}
示例#4
0
	public void SyncFromParameters(HEU_SessionBase session, HEU_HoudiniAsset parentAsset)
	{
	    HAPI_NodeInfo geoNodeInfo = new HAPI_NodeInfo();
	    if (!session.GetNodeInfo(_geoID, ref geoNodeInfo))
	    {
		return;
	    }

	    if (_parameters != null)
	    {
		_parameters.CleanUp();
	    }
	    else
	    {
		_parameters = ScriptableObject.CreateInstance<HEU_Parameters>();
	    }

	    string geoNodeName = HEU_SessionManager.GetString(geoNodeInfo.nameSH, session);
	    _parameters._uiLabel = geoNodeName.ToUpper() + " PARAMETERS";

	    bool bResult = _parameters.Initialize(session, _geoID, ref geoNodeInfo, null, null, parentAsset);
	    if (!bResult)
	    {
		Debug.LogWarningFormat("Parameter generate failed for geo node {0}.", geoNodeInfo.id);
		_parameters.CleanUp();
		return;
	    }

	    _points.Clear();
	    string pointList = _parameters.GetStringFromParameter(HEU_Defines.CURVE_COORDS_PARAM);
	    if (!string.IsNullOrEmpty(pointList))
	    {
		string[] pointSplit = pointList.Split(' ');
		foreach (string str in pointSplit)
		{
		    string[] vecSplit = str.Split(',');
		    if (vecSplit.Length == 3)
		    {
			_points.Add(new Vector3(-System.Convert.ToSingle(vecSplit[0], System.Globalization.CultureInfo.InvariantCulture),
				System.Convert.ToSingle(vecSplit[1], System.Globalization.CultureInfo.InvariantCulture),
				System.Convert.ToSingle(vecSplit[2], System.Globalization.CultureInfo.InvariantCulture)));
		    }
		}
	    }

	    // Since we just reset / created new our parameters and sync'd, we also need to 
	    // get the preset from Houdini session
	    if (!HEU_EditorUtility.IsEditorPlaying() && IsEditable())
	    {
		DownloadPresetData(session);
	    }
	}
示例#5
0
 /// <summary>
 /// Returns true if given asset is valid in given Houdini session.
 /// </summary>
 /// <param name="session">Session to check</param>
 /// <param name="assetID">ID of the asset to check</param>
 /// <returns>True if asset is valid in given session</returns>
 public static bool IsAssetValidInHoudini(HEU_SessionBase session, HAPI_NodeId assetID)
 {
     // Without a valid asset ID, we can't really check in Houdini session
     if (assetID != HEU_Defines.HEU_INVALID_NODE_ID)
     {
         // Use _assetID with uniqueHoudiniNodeId to see if our asset matches up in Houdini
         HAPI_NodeInfo nodeInfo = new HAPI_NodeInfo();
         if (session.GetNodeInfo(assetID, ref nodeInfo, false))
         {
             return(session.IsNodeValid(assetID, nodeInfo.uniqueHoudiniNodeId));
         }
     }
     return(false);
 }
示例#6
0
        /// <summary>
        /// Returns the parent node's ID of the given node.
        /// </summary>
        /// <param name="session"></param>
        /// <param name="nodeID"></param>
        /// <returns></returns>
        public static HAPI_NodeId GetParentNodeID(HEU_SessionBase session, HAPI_NodeId nodeID)
        {
            HAPI_NodeId parentNodeID = HEU_Defines.HEU_INVALID_NODE_ID;

            if (nodeID != HEU_Defines.HEU_INVALID_NODE_ID)
            {
                HAPI_NodeInfo nodeInfo = new HAPI_NodeInfo();
                if (session.GetNodeInfo(nodeID, ref nodeInfo))
                {
                    parentNodeID = nodeInfo.parentId;
                }
            }
            return(parentNodeID);
        }
示例#7
0
	/// <summary>
	/// Set the input node's transform.
	/// </summary>
	/// <param name="session">Session that the input node exists in</param>
	/// <param name="inputObject">The input object info containing data about the input</param>
	/// <param name="inputNodeID">The input node ID</param>
	/// <param name="bKeepWorldTransform">Whether to use world transform or not</param>
	/// <returns></returns>
	internal static bool UploadInputObjectTransform(HEU_SessionBase session, HEU_InputObjectInfo inputObject, HAPI_NodeId inputNodeID, bool bKeepWorldTransform)
	{
	    Matrix4x4 inputTransform = Matrix4x4.identity;
	    if (inputObject._useTransformOffset)
	    {
		if (bKeepWorldTransform)
		{
		    // Add offset tranform to world transform
		    Transform inputObjTransform = inputObject._gameObject.transform;
		    Vector3 position = inputObjTransform.position + inputObject._translateOffset;
		    Quaternion rotation = inputObjTransform.rotation * Quaternion.Euler(inputObject._rotateOffset);
		    Vector3 scale = Vector3.Scale(inputObjTransform.localScale, inputObject._scaleOffset);

		    Vector3 rotVector = rotation.eulerAngles;
		    inputTransform = HEU_HAPIUtility.GetMatrix4x4(ref position, ref rotVector, ref scale);
		}
		else
		{
		    // Offset from origin.
		    inputTransform = HEU_HAPIUtility.GetMatrix4x4(ref inputObject._translateOffset, ref inputObject._rotateOffset, ref inputObject._scaleOffset);
		}
	    }
	    else
	    {
		inputTransform = inputObject._gameObject.transform.localToWorldMatrix;
	    }

	    HAPI_TransformEuler transformEuler = HEU_HAPIUtility.GetHAPITransformFromMatrix(ref inputTransform);

	    HAPI_NodeInfo inputNodeInfo = new HAPI_NodeInfo();
	    if (!session.GetNodeInfo(inputNodeID, ref inputNodeInfo))
	    {
		return false;
	    }

	    if (session.SetObjectTransform(inputNodeInfo.parentId, ref transformEuler))
	    {
		inputObject._syncdTransform = inputTransform;

		inputObject._syncdChildTransforms.Clear();

		GetChildrenTransforms(inputObject._gameObject.transform, ref inputObject._syncdChildTransforms);
	    }

	    return true;
	}
	/// <summary>
	/// Returns the name of the specified node.
	/// </summary>
	/// <param name="nodeID">Node ID of the node to find the name of</param>
	/// <param name="session">Session that the node should be in</param>
	/// <returns>Name of node or empty string if not valid</returns>
	public static string GetNodeName(HAPI_NodeId nodeID, HEU_SessionBase session = null)
	{
	    if (session == null)
	    {
		session = GetOrCreateDefaultSession();
		if (session == null)
		{
		    return null;
		}
	    }

	    HAPI_NodeInfo nodeInfo = new HAPI_NodeInfo();
	    if (session.GetNodeInfo(nodeID, ref nodeInfo, false))
	    {
		return GetString(nodeInfo.nameSH, session);
	    }
	    return "";
	}
	// GEOMETRY GETTERS -------------------------------------------------------------------------------------------

	public static string GetUniqueMaterialShopName(HAPI_NodeId assetID, HAPI_NodeId materialID)
	{
	    HEU_SessionBase sessionBase = GetOrCreateDefaultSession();
	    if (sessionBase != null)
	    {
		HAPI_AssetInfo assetInfo = new HAPI_AssetInfo();
		if (!sessionBase.GetAssetInfo(assetID, ref assetInfo))
		{
		    return "";
		}

		HAPI_MaterialInfo materialInfo = new HAPI_MaterialInfo();
		if (!sessionBase.GetMaterialInfo(materialID, ref materialInfo))
		{
		    return "";
		}

		HAPI_NodeInfo assetNodeInfo = new HAPI_NodeInfo();
		if (!sessionBase.GetNodeInfo(assetID, ref assetNodeInfo))
		{
		    return "";
		}

		HAPI_NodeInfo materialNodeInfo = new HAPI_NodeInfo();
		if (!sessionBase.GetNodeInfo(materialInfo.nodeId, ref materialNodeInfo))
		{
		    return "";
		}

		string assetNodeName = HEU_SessionManager.GetString(assetNodeInfo.internalNodePathSH, sessionBase);
		string materialNodeName = HEU_SessionManager.GetString(materialNodeInfo.internalNodePathSH, sessionBase);
		if (assetNodeName.Length > 0 && materialNodeName.Length > 0)
		{
		    // Remove assetNodeName from materialNodeName. Extra position is for separator.
		    string materialName = materialNodeName.Substring(assetNodeName.Length + 1);
		    return materialName.Replace("/", "_");
		}
	    }
	    return "";
	}
示例#10
0
	private void DisconnectAndDestroyInputs(HEU_SessionBase session)
	{
	    // First disconnect the merge node from its connections
	    DisconnectConnectedMergeNode(session);

	    // Clear out input HDA hooks (upstream callback)
	    ClearConnectedInputHDAs();

	    if (session != null)
	    {
		// Delete the input nodes that were created
		foreach (HAPI_NodeId nodeID in _inputObjectsConnectedAssetIDs)
		{
		    if (nodeID != HEU_Defines.HEU_INVALID_NODE_ID)
		    {
			session.DeleteNode(nodeID);
		    }
		}

		// Delete the SOP/merge we created
		if (_connectedNodeID != HEU_Defines.HEU_INVALID_NODE_ID && HEU_HAPIUtility.IsNodeValidInHoudini(session, _connectedNodeID))
		{
		    // We'll delete the parent Object because we presume to have created the SOP/merge ourselves.
		    // If the parent Object doesn't get deleted, it sticks around unused.
		    HAPI_NodeInfo parentNodeInfo = new HAPI_NodeInfo();
		    if (session.GetNodeInfo(_connectedNodeID, ref parentNodeInfo))
		    {
			if (parentNodeInfo.parentId != HEU_Defines.HEU_INVALID_NODE_ID)
			{
			    session.DeleteNode(parentNodeInfo.parentId);
			}
		    }
		}
	    }

	    _inputObjectsConnectedAssetIDs.Clear();
	    _connectedNodeID = HEU_Defines.HEU_INVALID_NODE_ID;
	}
	/// <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_NodeId[] allNetworkNodeIds = HEU_PDGSession.GetNonBypassedNetworkIds(session, _assetID);
	    if (allNetworkNodeIds == null || allNetworkNodeIds.Length == 0)
	    {
		return false;
	    }

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

	    // Find nodes with TOP child nodes
	    foreach (HAPI_NodeId currentNodeId in allNetworkNodeIds)
	    {
		HAPI_NodeInfo topNodeInfo = new HAPI_NodeInfo();
		if (!session.GetNodeInfo(currentNodeId, ref topNodeInfo))
		{
		    return false;
		}

		string nodeName = HEU_SessionManager.GetString(topNodeInfo.nameSH, session);
		//HEU_Logger.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, currentNodeId, (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, currentNodeId, ref topNodeInfo, ref tags);

		    if (!tags._showHEngineData)
		    {
			continue;
		    }
		}
		else
		{
		    tags._show = true;
		    tags._showHEngineData = 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 = currentNodeId;
		topNetworkData._nodeName = nodeName;
		topNetworkData._parentName = _assetName;
		topNetworkData._tags = tags;

		if (PopulateTOPNodes(session, topNetworkData, topNodeIDs, _useHEngineData))
		{
		    for (int i = 0; i < topNetworkData._topNodes.Count; i++)
		    {
			if (topNetworkData._topNodes[i]._tags._show)
			{
			    topNetworkData._selectedTOPIndex = i;
			    break;
			}
		    }
		}
	    }

	    // 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;
	}
	private bool UseLegacyShaders(HAPI_MaterialInfo materialInfo, string assetCacheFolderPath, HEU_SessionBase session, HAPI_NodeInfo nodeInfo, HAPI_ParmInfo[] parmInfos)
	{
	    // Diffuse texture - render & extract
	    int diffuseMapParmIndex = HEU_ParameterUtility.FindTextureParamByNameOrTag(session, nodeInfo.id, parmInfos, HEU_Defines.MAT_OGL_TEX1_ATTR,  HEU_Defines.MAT_OGL_TEX1_ATTR_ENABLED);
	    if (diffuseMapParmIndex < 0)
	    {
		diffuseMapParmIndex = HEU_ParameterUtility.FindTextureParamByNameOrTag(session, nodeInfo.id, parmInfos, HEU_Defines.MAT_BASECOLOR_ATTR, HEU_Defines.MAT_BASECOLOR_ATTR_ENABLED);
		if (diffuseMapParmIndex < 0)
		{
		    diffuseMapParmIndex = HEU_ParameterUtility.FindTextureParamByNameOrTag(session, nodeInfo.id, parmInfos, HEU_Defines.MAT_MAP_ATTR, "");
		}
	    }
	    if (diffuseMapParmIndex >= 0 && diffuseMapParmIndex < parmInfos.Length)
	    {
		string diffuseTextureFileName = GetTextureFileNameFromMaterialParam(session, materialInfo.nodeId, parmInfos[diffuseMapParmIndex]);
		_material.mainTexture = HEU_MaterialFactory.RenderAndExtractImageToTexture(session, materialInfo, parmInfos[diffuseMapParmIndex].id, diffuseTextureFileName, assetCacheFolderPath, false);
	    }

	    // Normal map - render & extract texture
	    int normalMapParmIndex = HEU_ParameterUtility.FindTextureParamByNameOrTag(session, nodeInfo.id, parmInfos, HEU_Defines.MAT_NORMAL_ATTR, HEU_Defines.MAT_NORMAL_ATTR_ENABLED);
	    if (normalMapParmIndex < 0)
	    {
		normalMapParmIndex = HEU_ParameterUtility.FindTextureParamByNameOrTag(session, nodeInfo.id, parmInfos, HEU_Defines.MAT_OGL_NORMAL_ATTR, "");
	    }
	    
	    if (normalMapParmIndex >= 0 && normalMapParmIndex < parmInfos.Length)
	    {
		string normalTextureFileName = GetTextureFileNameFromMaterialParam(session, materialInfo.nodeId, parmInfos[normalMapParmIndex]);
		Texture2D normalMap = HEU_MaterialFactory.RenderAndExtractImageToTexture(session, materialInfo, parmInfos[normalMapParmIndex].id, normalTextureFileName, assetCacheFolderPath, true);
		if (normalMap != null)
		{
		    _material.SetTexture(HEU_Defines.UNITY_SHADER_BUMP_MAP, normalMap);
		}
	    }

	    // Assign shader properties

	    // Clamp shininess to non-zero as results in very hard shadows. Unity's UI does not allow zero either.

	    float shininess;
	    if (!HEU_ParameterUtility.GetParameterFloatValue(session, materialInfo.nodeId, parmInfos, HEU_Defines.MAT_OGL_ROUGH_ATTR, 0f, out shininess))
	    {
		HEU_ParameterUtility.GetParameterFloatValue(session, materialInfo.nodeId, parmInfos, HEU_Defines.MAT_ROUGH_ATTR, 0f, out shininess);
	    }

	    _material.SetFloat(HEU_Defines.UNITY_SHADER_SHININESS, Mathf.Max(0.03f, 1.0f - shininess));

	    Color diffuseColor;
	    if (!HEU_ParameterUtility.GetParameterColor3Value(session, materialInfo.nodeId, parmInfos, HEU_Defines.MAT_OGL_DIFF_ATTR, Color.white, out diffuseColor))
	    {
		HEU_ParameterUtility.GetParameterColor3Value(session, materialInfo.nodeId, parmInfos, HEU_Defines.MAT_DIFF_ATTR, Color.white, out diffuseColor);
	    }

	    float alpha;
	    if (!HEU_ParameterUtility.GetParameterFloatValue(session, materialInfo.nodeId, parmInfos, HEU_Defines.MAT_OGL_ALPHA_ATTR, 1f, out alpha))
	    {
		HEU_ParameterUtility.GetParameterFloatValue(session, materialInfo.nodeId, parmInfos, HEU_Defines.MAT_ALPHA_ATTR, 1f, out alpha);
	    }

	    diffuseColor.a = alpha;
	    _material.SetColor(HEU_Defines.UNITY_SHADER_COLOR, diffuseColor);

	    Color specular;
	    if (!HEU_ParameterUtility.GetParameterColor3Value(session, materialInfo.nodeId, parmInfos, HEU_Defines.MAT_OGL_SPEC_ATTR, Color.black, out specular))
	    {
	        HEU_ParameterUtility.GetParameterColor3Value(session, materialInfo.nodeId, parmInfos, HEU_Defines.MAT_SPEC_ATTR, Color.black, out specular);
	    }
	    _material.SetColor(HEU_Defines.UNITY_SHADER_SPEC_COLOR, specular);

	    return true;
	}
	/// <summary>
	/// For this object's _material, we update the shader attributes and 
	/// fetch the textures from Houdini.
	/// </summary>
	/// <param name="materialInfo">This material's info from Houdini</param>
	/// <param name="assetCacheFolderPath">Path to asset's cache folder</param>
	public bool UpdateMaterialFromHoudini(HAPI_MaterialInfo materialInfo, string assetCacheFolderPath)
	{
	    if (_material == null)
	    {
		return false;
	    }

	    HEU_SessionBase session = HEU_SessionManager.GetOrCreateDefaultSession();

	    HAPI_NodeInfo nodeInfo = new HAPI_NodeInfo();
	    if (!session.GetNodeInfo(materialInfo.nodeId, ref nodeInfo))
	    {
		return false;
	    }

	    // Get all parameters of this material
	    HAPI_ParmInfo[] parmInfos = new HAPI_ParmInfo[nodeInfo.parmCount];
	    if (!HEU_GeneralUtility.GetArray1Arg(materialInfo.nodeId, session.GetParams, parmInfos, 0, nodeInfo.parmCount))
	    {
		return false;
	    }

	    // Assign transparency shader or non-transparent.

	    bool isTransparent = IsTransparentMaterial(session, materialInfo.nodeId, parmInfos);
	    if (isTransparent)
	    {
		_material.shader = HEU_MaterialFactory.FindPluginShader(HEU_PluginSettings.DefaultTransparentShader);
	    }
	    else
	    {
		_material.shader = HEU_MaterialFactory.FindPluginShader(HEU_PluginSettings.DefaultStandardShader);
	    }

	    if (HEU_PluginSettings.UseLegacyShaders)
	    {
		return UseLegacyShaders(materialInfo, assetCacheFolderPath, session, nodeInfo, parmInfos);
	    }

	    // Diffuse texture - render & extract
	    int diffuseMapParmIndex = HEU_ParameterUtility.FindTextureParamByNameOrTag(session, nodeInfo.id, parmInfos, HEU_Defines.MAT_OGL_TEX1_ATTR, HEU_Defines.MAT_OGL_TEX1_ATTR_ENABLED);
	    if (diffuseMapParmIndex < 0)
	    {
		diffuseMapParmIndex = HEU_ParameterUtility.FindTextureParamByNameOrTag(session, nodeInfo.id, parmInfos, HEU_Defines.MAT_BASECOLOR_ATTR, HEU_Defines.MAT_BASECOLOR_ATTR_ENABLED);
	    }
	    
	    if (diffuseMapParmIndex >= 0 && diffuseMapParmIndex < parmInfos.Length)
	    {
		string diffuseTextureFileName = GetTextureFileNameFromMaterialParam(session, materialInfo.nodeId, parmInfos[diffuseMapParmIndex]);
		_material.mainTexture = HEU_MaterialFactory.RenderAndExtractImageToTexture(session, materialInfo, parmInfos[diffuseMapParmIndex].id, diffuseTextureFileName, assetCacheFolderPath, false);
	    }

	    Color diffuseColor;
	    if (!HEU_ParameterUtility.GetParameterColor3Value(session, materialInfo.nodeId, parmInfos, HEU_Defines.MAT_OGL_DIFF_ATTR, Color.white, out diffuseColor))
	    {
		HEU_ParameterUtility.GetParameterColor3Value(session, materialInfo.nodeId, parmInfos, HEU_Defines.MAT_DIFF_ATTR, Color.white, out diffuseColor);
	    }

	    float alpha;
	    GetMaterialAlpha(session, materialInfo.nodeId, parmInfos, 1f, out alpha);

	    if (isTransparent)
	    {
		int opacityMapParmIndex = HEU_ParameterUtility.FindTextureParamByNameOrTag(session, nodeInfo.id, parmInfos, HEU_Defines.MAT_OGL_OPACITY_MAP_ATTR, HEU_Defines.MAT_OGL_OPACITY_MAP_ATTR_ENABLED);
		if (opacityMapParmIndex < 0)
		{
		    opacityMapParmIndex = HEU_ParameterUtility.FindTextureParamByNameOrTag(session, nodeInfo.id, parmInfos, HEU_Defines.MAT_OPACITY_MAP_ATTR, HEU_Defines.MAT_OPACITY_MAP_ATTR_ENABLED);
		}
		
		if (opacityMapParmIndex >= 0 && opacityMapParmIndex < parmInfos.Length)
		{
		    string opacityTextureFileName = GetTextureFileNameFromMaterialParam(session, materialInfo.nodeId, parmInfos[opacityMapParmIndex]);
		    _material.SetTexture(HEU_Defines.UNITY_SHADER_OPACITY_MAP, HEU_MaterialFactory.RenderAndExtractImageToTexture(session, materialInfo, parmInfos[opacityMapParmIndex].id, opacityTextureFileName, assetCacheFolderPath, false));
		}
	    }

	    diffuseColor.a = alpha;
	    _material.SetColor(HEU_Defines.UNITY_SHADER_COLOR, diffuseColor);

	    if (HEU_PluginSettings.UseSpecularShader)
	    {
		Color specular;
		Color defaultSpecular = new Color(0.2f, 0.2f, 0.2f, 1);
		if (!HEU_ParameterUtility.GetParameterColor3Value(session, materialInfo.nodeId, parmInfos, HEU_Defines.MAT_OGL_SPEC_ATTR, defaultSpecular, out specular))
		{
		    HEU_ParameterUtility.GetParameterColor3Value(session, materialInfo.nodeId, parmInfos, HEU_Defines.MAT_SPEC_ATTR, defaultSpecular, out specular);
		}
		_material.SetColor(HEU_Defines.UNITY_SHADER_SPEC_COLOR, specular);

		int specMapParmIndex = HEU_ParameterUtility.FindTextureParamByNameOrTag(session, nodeInfo.id, parmInfos, HEU_Defines.MAT_OGL_SPEC_MAP_ATTR, HEU_Defines.MAT_OGL_SPEC_MAP_ATTR_ENABLED);
		if (specMapParmIndex < 0)
		{
		    specMapParmIndex = HEU_ParameterUtility.FindTextureParamByNameOrTag(session, nodeInfo.id, parmInfos, HEU_Defines.MAT_SPEC_MAP_ATTR, HEU_Defines.MAT_SPEC_MAP_ATTR_ENABLED);
		}
		
		if (specMapParmIndex >= 0 && specMapParmIndex < parmInfos.Length)
		{
		    string specTextureFileName = GetTextureFileNameFromMaterialParam(session, materialInfo.nodeId, parmInfos[specMapParmIndex]);
		    _material.SetTexture(HEU_Defines.UNITY_SHADER_SPEC_MAP, HEU_MaterialFactory.RenderAndExtractImageToTexture(session, materialInfo, parmInfos[specMapParmIndex].id, specTextureFileName, assetCacheFolderPath, false));
		}
	    }
	    else
	    {
	 	float metallic = 0;
	 	if (!HEU_ParameterUtility.GetParameterFloatValue(session, materialInfo.nodeId, parmInfos, HEU_Defines.MAT_OGL_METALLIC_ATTR, 0f, out metallic))
	 	{
		    HEU_ParameterUtility.GetParameterFloatValue(session, materialInfo.nodeId, parmInfos, HEU_Defines.MAT_METALLIC_ATTR, 0f, out metallic);
	 	}

		_material.SetFloat(HEU_Defines.UNITY_SHADER_METALLIC, metallic);

		int metallicMapParmIndex = HEU_ParameterUtility.FindTextureParamByNameOrTag(session, nodeInfo.id, parmInfos, HEU_Defines.MAT_OGL_METALLIC_MAP_ATTR, HEU_Defines.MAT_OGL_METALLIC_MAP_ATTR_ENABLED);
		if (metallicMapParmIndex < 0)
		{
		    metallicMapParmIndex = HEU_ParameterUtility.FindTextureParamByNameOrTag(session, nodeInfo.id, parmInfos, HEU_Defines.MAT_METALLIC_MAP_ATTR, HEU_Defines.MAT_METALLIC_MAP_ATTR_ENABLED);
		}

		
		if (metallicMapParmIndex >= 0 && metallicMapParmIndex < parmInfos.Length)
		{
		    string metallicTextureFileName = GetTextureFileNameFromMaterialParam(session, materialInfo.nodeId, parmInfos[metallicMapParmIndex]);
		    _material.SetTexture(HEU_Defines.UNITY_SHADER_METALLIC_MAP, HEU_MaterialFactory.RenderAndExtractImageToTexture(session, materialInfo, parmInfos[metallicMapParmIndex].id, metallicTextureFileName, assetCacheFolderPath, false));
		}
	    }

	    // Normal map - render & extract texture
	    int normalMapParmIndex = HEU_ParameterUtility.FindTextureParamByNameOrTag(session, nodeInfo.id, parmInfos, HEU_Defines.MAT_NORMAL_ATTR, HEU_Defines.MAT_NORMAL_ATTR_ENABLED);
	    if (normalMapParmIndex < 0)
	    {
		normalMapParmIndex = HEU_ParameterUtility.FindTextureParamByNameOrTag(session, nodeInfo.id, parmInfos, HEU_Defines.MAT_OGL_NORMAL_ATTR, "");
	    }

	    if (normalMapParmIndex >= 0 && normalMapParmIndex < parmInfos.Length)
	    {
		string normalTextureFileName = GetTextureFileNameFromMaterialParam(session, materialInfo.nodeId, parmInfos[normalMapParmIndex]);
		Texture2D normalMap = HEU_MaterialFactory.RenderAndExtractImageToTexture(session, materialInfo, parmInfos[normalMapParmIndex].id, normalTextureFileName, assetCacheFolderPath, true);
		if (normalMap != null)
		{
		    _material.SetTexture(HEU_Defines.UNITY_SHADER_BUMP_MAP, normalMap);
		}
	    }

	    // Emission
	    Color emission;
	    Color defaultEmission = new Color(0, 0, 0, 0);
	    if (!HEU_ParameterUtility.GetParameterColor3Value(session, materialInfo.nodeId, parmInfos, HEU_Defines.MAT_OGL_EMISSIVE_ATTR, defaultEmission, out emission))
	    {
	        HEU_ParameterUtility.GetParameterColor3Value(session, materialInfo.nodeId, parmInfos, HEU_Defines.MAT_EMISSIVE_ATTR, defaultEmission, out emission);
	    }
	    _material.SetColor(HEU_Defines.UNITY_SHADER_EMISSION_COLOR, emission);

	    int emissionMapParmIndex = HEU_ParameterUtility.FindTextureParamByNameOrTag(session, nodeInfo.id, parmInfos, HEU_Defines.MAT_OGL_EMISSIVE_MAP_ATTR, HEU_Defines.MAT_OGL_EMISSIVE_MAP_ATTR_ENABLED);
	    if (emissionMapParmIndex < 0)
	    {
	        emissionMapParmIndex = HEU_ParameterUtility.FindTextureParamByNameOrTag(session, nodeInfo.id, parmInfos, HEU_Defines.MAT_EMISSIVE_MAP_ATTR, HEU_Defines.MAT_EMISSIVE_MAP_ATTR_ENABLED);
	    }
	    
	    if (emissionMapParmIndex >= 0 && emissionMapParmIndex < parmInfos.Length)
	    {
	        string emissionTextureFileName = GetTextureFileNameFromMaterialParam(session, materialInfo.nodeId, parmInfos[emissionMapParmIndex]);
	        _material.SetTexture(HEU_Defines.UNITY_SHADER_EMISSION_MAP, HEU_MaterialFactory.RenderAndExtractImageToTexture(session, materialInfo, parmInfos[emissionMapParmIndex].id, emissionTextureFileName, assetCacheFolderPath, false));
	    }

	    // Smoothness (need to invert roughness!)
	    float roughness;
	    float defaultRoughness = 0.5f;
	    if (!HEU_ParameterUtility.GetParameterFloatValue(session, materialInfo.nodeId, parmInfos, HEU_Defines.MAT_OGL_ROUGH_ATTR, defaultRoughness, out roughness))
	    {
		HEU_ParameterUtility.GetParameterFloatValue(session, materialInfo.nodeId, parmInfos, HEU_Defines.MAT_ROUGH_ATTR, defaultRoughness, out roughness);
	    }

	    // Clamp shininess to non-zero as results in very hard shadows. Unity's UI does not allow zero either.
	    _material.SetFloat(HEU_Defines.UNITY_SHADER_SMOOTHNESS, Mathf.Max(0.03f, 1.0f - roughness));

	    int roughMapParmIndex = HEU_ParameterUtility.FindTextureParamByNameOrTag(session, nodeInfo.id, parmInfos, HEU_Defines.MAT_OGL_ROUGH_MAP_ATTR, HEU_Defines.MAT_OGL_ROUGH_MAP_ATTR_ENABLED);
	    if (roughMapParmIndex < 0)
	    {
	        roughMapParmIndex = HEU_ParameterUtility.FindTextureParamByNameOrTag(session, nodeInfo.id, parmInfos, HEU_Defines.MAT_ROUGH_MAP_ATTR, HEU_Defines.MAT_ROUGH_MAP_ATTR_ENABLED);
	    }
	    
	    if (roughMapParmIndex >= 0 && roughMapParmIndex < parmInfos.Length)
	    {
	        string roughTextureFileName = GetTextureFileNameFromMaterialParam(session, materialInfo.nodeId, parmInfos[roughMapParmIndex]);
	        _material.SetTexture(HEU_Defines.UNITY_SHADER_SMOOTHNESS_MAP, HEU_MaterialFactory.RenderAndExtractImageToTexture(session, materialInfo, parmInfos[roughMapParmIndex].id, roughTextureFileName, assetCacheFolderPath, false, invertTexture: true));
	    }

	    // Occlusion (only has ogl map) 
	    int occlusionMapParmIndex = HEU_ParameterUtility.FindTextureParamByNameOrTag(session, nodeInfo.id, parmInfos, HEU_Defines.MAT_OGL_OCCLUSION_MAP_ATTR, HEU_Defines.MAT_OGL_ROUGH_MAP_ATTR_ENABLED);

	    if (occlusionMapParmIndex >= 0 && occlusionMapParmIndex < parmInfos.Length)
	    {
	        string occlusionTextureFileName = GetTextureFileNameFromMaterialParam(session, materialInfo.nodeId, parmInfos[occlusionMapParmIndex]);
	        _material.SetTexture(HEU_Defines.UNITY_SHADER_OCCLUSION_MAP, HEU_MaterialFactory.RenderAndExtractImageToTexture(session, materialInfo, parmInfos[occlusionMapParmIndex].id, occlusionTextureFileName, assetCacheFolderPath, false));
	    }

	    return true;
	}
	/// <summary>
	/// Do the geometry loading in Houdini in a thread.
	/// Creates a file node, loads the bgeo, then retrives the geometry into local buffers.
	/// </summary>
	protected override void DoWork()
	{
	    _loadData._loadStatus = HEU_LoadData.LoadStatus.STARTED;

	    //HEU_Logger.LogFormat("DoWork: Loading {0}", _filePath);

	    if (_session == null || !_session.IsSessionValid())
	    {
		AppendLog(HEU_LoadData.LoadStatus.ERROR, "Invalid session!");
		return;
	    }

	    if (_loadType == LoadType.FILE)
	    {
		if (!DoFileLoad())
		{
		    return;
		}
	    }
	    else if (_loadType == LoadType.ASSET)
	    {
		if (!DoAssetLoad())
		{
		    return;
		}
	    }

	    // For LoadType.NODE, assume the node already exists in Houdini session
	    // We simply recook and generate geometry

	    HAPI_NodeId cookNodeID = GetCookNodeID();
	    if (cookNodeID == HEU_Defines.HEU_INVALID_NODE_ID)
	    {
		AppendLog(HEU_LoadData.LoadStatus.ERROR, string.Format("Unable to get cook node."));
		return;
	    }

	    if (_loadCallback != null)
	    {
		_loadCallback(_session, _loadData, HEU_LoadCallbackType.PRECOOK);
	    }

	    // Cooking it will update the node so we can query its details
	    // This will block until cook has completed or failed
	    if (!CookNode(_session, cookNodeID))
	    {
		return;
	    }

	    if (_loadCallback != null)
	    {
		_loadCallback(_session, _loadData, HEU_LoadCallbackType.POSTCOOK);
	    }

	    // Get nodes to cook based on the type of node
	    HAPI_NodeInfo nodeInfo = new HAPI_NodeInfo();
	    if (!_session.GetNodeInfo(cookNodeID, ref nodeInfo))
	    {
		return;
	    }

	    HAPI_ObjectInfo[] objectInfos = null;
	    HAPI_Transform[] objectTransforms = null;
	    if (!HEU_HAPIUtility.GetObjectInfos(_session, cookNodeID, ref nodeInfo, out objectInfos, out objectTransforms))
	    {
		return;
	    }

	    _loadData._loadedObjects = new List<HEU_LoadObject>();
	    bool bResult = true;

	    // For each object, get the display and editable geometries contained inside.
	    for (int i = 0; i < objectInfos.Length; ++i)
	    {
		bResult &= LoadObjectBuffers(_session, ref objectInfos[i]);
	    }

	    if (bResult)
	    {
		AppendLog(HEU_LoadData.LoadStatus.SUCCESS, "Completed!");
	    }
	    else
	    {
		AppendLog(HEU_LoadData.LoadStatus.ERROR, "Failed to load geometry!");
	    }
	}
        /// <summary>
        /// Gets the object infos and transforms for given asset.
        /// </summary>
        /// <param name="assetID">ID of the asset</param>
        /// <param name="nodeInfo">HAPI_NodeInfo of the asset</param>
        /// <param name="objectInfos">Array of retrieved object infos</param>
        /// <param name="objectTransforms">Array of retrieved object transforms</param>
        /// <returns>True if succesfully retrieved object infos and transforms</returns>
        public static bool GetObjectInfos(HEU_SessionBase session, HAPI_NodeId assetID, ref HAPI_NodeInfo nodeInfo, out HAPI_ObjectInfo[] objectInfos, out HAPI_Transform[] objectTransforms)
        {
            objectInfos      = new HAPI_ObjectInfo[0];
            objectTransforms = new HAPI_Transform[0];

            if (nodeInfo.type == HAPI_NodeType.HAPI_NODETYPE_SOP)
            {
                // For SOP assets, we use the parent IDs to get the object info and geo info

                objectInfos = new HAPI_ObjectInfo[1];
                if (!session.GetObjectInfo(nodeInfo.parentId, ref objectInfos[0]))
                {
                    return(false);
                }

                // Identity transform will be used for SOP assets, so not querying transform
                objectTransforms    = new HAPI_Transform[1];
                objectTransforms[0] = new HAPI_Transform(true);
            }
            else if (nodeInfo.type == HAPI_NodeType.HAPI_NODETYPE_OBJ)
            {
                int objectCount = 0;
                if (!session.ComposeObjectList(assetID, out objectCount))
                {
                    return(false);
                }

                if (objectCount <= 0)
                {
                    // Since this asset is an object type and has 0 object as children, we use the object itself

                    objectInfos = new HAPI_ObjectInfo[1];
                    if (!session.GetObjectInfo(nodeInfo.id, ref objectInfos[0]))
                    {
                        return(false);
                    }

                    // Identity transform will be used for single object assets, so not querying transform
                    objectTransforms    = new HAPI_Transform[1];
                    objectTransforms[0] = new HAPI_Transform(true);
                }
                else
                {
                    // This object has children, so use GetComposedObjectList to get list of HAPI_ObjectInfos

                    objectInfos = new HAPI_ObjectInfo[objectCount];
                    if (!session.GetComposedObjectList(nodeInfo.parentId, objectInfos, 0, objectCount))
                    {
                        return(false);
                    }

                    // Now get the object transforms
                    objectTransforms = new HAPI_Transform[objectCount];
                    if (!HEU_SessionManager.GetComposedObjectTransformsMemorySafe(session, nodeInfo.parentId, HAPI_RSTOrder.HAPI_SRT, objectTransforms, 0, objectCount))
                    {
                        return(false);
                    }
                }
            }
            else
            {
                Debug.LogWarningFormat(HEU_Defines.HEU_NAME + ": Unsupported node type {0}", nodeInfo.type);
                return(false);
            }

            return(true);
        }
示例#16
0
        HAPI_NodeId GetParentNodeID(HEU_SessionBase session)
        {
            HAPI_NodeInfo nodeInfo = new HAPI_NodeInfo();

            return((session.GetNodeInfo(_cookNodeID, ref nodeInfo, false)) ? nodeInfo.parentId : -1);
        }
示例#17
0
	/// <summary>
	/// For this object's _material, we update the shader attributes and 
	/// fetch the textures from Houdini.
	/// </summary>
	/// <param name="materialInfo">This material's info from Houdini</param>
	/// <param name="assetCacheFolderPath">Path to asset's cache folder</param>
	public void UpdateMaterialFromHoudini(HAPI_MaterialInfo materialInfo, string assetCacheFolderPath)
	{
	    HEU_SessionBase session = HEU_SessionManager.GetOrCreateDefaultSession();

	    HAPI_NodeInfo nodeInfo = new HAPI_NodeInfo();
	    if (!session.GetNodeInfo(materialInfo.nodeId, ref nodeInfo))
	    {
		return;
	    }

	    // Get all parameters of this material
	    HAPI_ParmInfo[] parmInfos = new HAPI_ParmInfo[nodeInfo.parmCount];
	    if (!HEU_GeneralUtility.GetArray1Arg(materialInfo.nodeId, session.GetParams, parmInfos, 0, nodeInfo.parmCount))
	    {
		return;
	    }

	    // Assign transparency shader or non-transparent.
	    if (IsTransparentMaterial(session, materialInfo.nodeId, parmInfos))
	    {
		_material.shader = HEU_MaterialFactory.FindPluginShader(HEU_PluginSettings.DefaultTransparentShader);
	    }
	    else
	    {
		_material.shader = HEU_MaterialFactory.FindPluginShader(HEU_PluginSettings.DefaultStandardShader);
	    }

	    // Diffuse texture - render & extract
	    int diffuseMapParmIndex = HEU_ParameterUtility.GetParameterIndexFromNameOrTag(session, nodeInfo.id, parmInfos, HEU_Defines.MAT_OGL_TEX1_ATTR);
	    if (diffuseMapParmIndex < 0)
	    {
		diffuseMapParmIndex = HEU_ParameterUtility.GetParameterIndexFromNameOrTag(session, nodeInfo.id, parmInfos, HEU_Defines.MAT_BASECOLOR_ATTR);
		if (diffuseMapParmIndex < 0)
		{
		    diffuseMapParmIndex = HEU_ParameterUtility.GetParameterIndexFromNameOrTag(session, nodeInfo.id, parmInfos, HEU_Defines.MAT_MAP_ATTR);
		}
	    }
	    if (diffuseMapParmIndex >= 0 && diffuseMapParmIndex < parmInfos.Length)
	    {
		string diffuseTextureFileName = GetTextureFileNameFromMaterialParam(session, materialInfo.nodeId, parmInfos[diffuseMapParmIndex]);
		_material.mainTexture = HEU_MaterialFactory.RenderAndExtractImageToTexture(session, materialInfo, parmInfos[diffuseMapParmIndex].id, diffuseTextureFileName, assetCacheFolderPath);
	    }

	    // Normal map - render & extract texture
	    int normalMapParmIndex = HEU_ParameterUtility.GetParameterIndexFromNameOrTag(session, nodeInfo.id, parmInfos, HEU_Defines.MAT_OGL_NORMAL_ATTR);
	    if (normalMapParmIndex >= 0 && normalMapParmIndex < parmInfos.Length)
	    {
		string normalTextureFileName = GetTextureFileNameFromMaterialParam(session, materialInfo.nodeId, parmInfos[normalMapParmIndex]);
		Texture2D normalMap = HEU_MaterialFactory.RenderAndExtractImageToTexture(session, materialInfo, parmInfos[normalMapParmIndex].id, normalTextureFileName, assetCacheFolderPath);
		if (normalMap != null)
		{
		    _material.SetTexture(HEU_Defines.UNITY_SHADER_BUMP_MAP, normalMap);
		}
	    }

	    // Assign shader properties

	    // Clamp shininess to non-zero as results in very hard shadows. Unity's UI does not allow zero either.
	    float shininess = HEU_ParameterUtility.GetParameterFloatValue(session, materialInfo.nodeId, parmInfos, HEU_Defines.MAT_OGL_ROUGH_ATTR, 0f);
	    _material.SetFloat(HEU_Defines.UNITY_SHADER_SHININESS, Mathf.Max(0.03f, 1.0f - shininess));

	    Color diffuseColor = HEU_ParameterUtility.GetParameterColor3Value(session, materialInfo.nodeId, parmInfos, HEU_Defines.MAT_OGL_DIFF_ATTR, Color.white);
	    diffuseColor.a = HEU_ParameterUtility.GetParameterFloatValue(session, materialInfo.nodeId, parmInfos, HEU_Defines.MAT_OGL_ALPHA_ATTR, 1f);
	    _material.SetColor(HEU_Defines.UNITY_SHADER_COLOR, diffuseColor);

	    Color specular = HEU_ParameterUtility.GetParameterColor3Value(session, materialInfo.nodeId, parmInfos, HEU_Defines.MAT_OGL_SPEC_ATTR, Color.black);
	    _material.SetColor(HEU_Defines.UNITY_SHADER_SPECCOLOR, specular);
	}
	/// <summary>
	/// Helper to parse spare parm containing the filter key words.
	/// </summary>
	/// <param name="session">Houdini Engine session that the TOP node is in</param>
	/// <param name="topNodeID">TOP node to get spare parm from</param>
	/// <param name="nodeInfo">Previously queried TOP node info</param>
	/// <param name="nodeTags">Tag data to populate</param>
	private static void ParseHEngineData(HEU_SessionBase session, HAPI_NodeId topNodeID, ref HAPI_NodeInfo nodeInfo, ref TOPNodeTags nodeTags)
	{
	    // Turn off session logging error when querying string parm that might not be there
	    bool bLogError = session.LogErrorOverride;
	    session.LogErrorOverride = false;

	    int numStrings = nodeInfo.parmStringValueCount;
	    HAPI_StringHandle henginedatash = 0;
	    if (numStrings > 0 && session.GetParamStringValue(topNodeID, "henginedata", 0, out henginedatash))
	    {
		string henginedatastr = HEU_SessionManager.GetString(henginedatash, session);
		//Debug.Log("HEngine data: " + henginedatastr);

		if (!string.IsNullOrEmpty(henginedatastr))
		{
		    string[] tags = henginedatastr.Split(',');
		    if (tags != null && tags.Length > 0)
		    {
			foreach (string t in tags)
			{
			    if (t.Equals("show"))
			    {
				nodeTags._show = true;
			    }
			    else if (t.Equals("autoload"))
			    {
				nodeTags._autoload = true;
			    }
			}
		    }
		}
	    }

	    // Logging error back on
	    session.LogErrorOverride = bLogError;
	}
	/// <summary>
	/// Given TOP nodes from a TOP network, populate internal state from each TOP node.
	/// </summary>
	/// <param name="session">Houdini Engine session</param>
	/// <param name="topNetwork">TOP network to query TOP nodes from</param>
	/// <param name="topNodeIDs">List of TOP nodes in the TOP network</param>
	/// <param name="useHEngineData">Whether or not to use HEngine data for filtering</param>
	/// <returns>True if successfully populated data</returns>
	public static bool PopulateTOPNodes(HEU_SessionBase session, HEU_TOPNetworkData topNetwork, HAPI_NodeId[] topNodeIDs, bool useHEngineData)
	{
	    // Holds list of found TOP nodes
	    List<HEU_TOPNodeData> newNodes = new List<HEU_TOPNodeData>();

	    foreach (HAPI_NodeId topNodeID in topNodeIDs)
	    {
		// Not necessary. Blocks main thread.
		//session.CookNode(childNodeID, HEU_PluginSettings.CookTemplatedGeos);

		HAPI_NodeInfo childNodeInfo = new HAPI_NodeInfo();
		if (!session.GetNodeInfo(topNodeID, ref childNodeInfo))
		{
		    return false;
		}

		string nodeName = HEU_SessionManager.GetString(childNodeInfo.nameSH, session);
		//Debug.LogFormat("TOP Node: name={0}, type={1}", nodeName, childNodeInfo.type);

		TOPNodeTags tags = new TOPNodeTags();
		if (useHEngineData)
		{
		    ParseHEngineData(session, topNodeID, ref childNodeInfo, ref tags);

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

		HEU_TOPNodeData topNodeData = GetTOPNodeByName(nodeName, topNetwork._topNodes);
		if (topNodeData == null)
		{
		    topNodeData = new HEU_TOPNodeData();
		}
		else
		{
		    topNetwork._topNodes.Remove(topNodeData);
		}

		newNodes.Add(topNodeData);

		//topNodeData.Reset();
		topNodeData._nodeID = topNodeID;
		topNodeData._nodeName = nodeName;
		topNodeData._parentName = topNetwork._parentName + "_" + topNetwork._nodeName;
		topNodeData._tags = tags;
	    }

	    // Clear old unused TOP nodes
	    for (int i = 0; i < topNetwork._topNodes.Count; ++i)
	    {
		ClearTOPNodeWorkItemResults(topNetwork._topNodes[i]);
	    }
	    topNetwork._topNodes = newNodes;

	    // Get list of updated TOP node names
	    topNetwork._topNodeNames = new string[topNetwork._topNodes.Count];
	    for (int i = 0; i < topNetwork._topNodes.Count; ++i)
	    {
		topNetwork._topNodeNames[i] = topNetwork._topNodes[i]._nodeName;
	    }

	    return true;
	}
	/// <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;
	}
	/// <summary>
	/// Given TOP nodes from a TOP network, populate internal state from each TOP node.
	/// </summary>
	/// <param name="session">Houdini Engine session</param>
	/// <param name="topNetwork">TOP network to query TOP nodes from</param>
	/// <param name="topNodeIDs">List of TOP nodes in the TOP network</param>
	/// <param name="useHEngineData">Whether or not to use HEngine data for filtering</param>
	/// <returns>True if successfully populated data</returns>
	private bool PopulateTOPNodes(HEU_SessionBase session, HEU_TOPNetworkData topNetwork, HAPI_NodeId[] topNodeIDs, bool useHEngineData)
	{
	    // Holds list of found TOP nodes
	    List<HEU_TOPNodeData> newNodes = new List<HEU_TOPNodeData>();

	    foreach (HAPI_NodeId topNodeID in topNodeIDs)
	    {
		// Not necessary. Blocks main thread.
		//session.CookNode(childNodeID, HEU_PluginSettings.CookTemplatedGeos);

		HAPI_NodeInfo childNodeInfo = new HAPI_NodeInfo();
		if (!session.GetNodeInfo(topNodeID, ref childNodeInfo))
		{
		    return false;
		}

		string nodeName = HEU_SessionManager.GetString(childNodeInfo.nameSH, session);
		//HEU_Logger.LogFormat("TOP Node: name={0}, type={1}", nodeName, childNodeInfo.type);

		TOPNodeTags tags = new TOPNodeTags();
		if (useHEngineData)
		{
		    ParseHEngineData(session, topNodeID, ref childNodeInfo, ref tags);

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

		HEU_TOPNodeData topNodeData = GetTOPNodeByName(nodeName, topNetwork._topNodes);
		if (topNodeData == null)
		{
		    topNodeData = new HEU_TOPNodeData();
		}
		else
		{
		    topNetwork._topNodes.Remove(topNodeData);
		}

		newNodes.Add(topNodeData);

		//topNodeData.Reset();
		topNodeData._nodeID = topNodeID;
		topNodeData._nodeName = nodeName;
		topNodeData._parentName = topNetwork._parentName + "_" + topNetwork._nodeName;
		topNodeData._tags = tags;

		// Note: Don't have to compare with _showHEngineData because it won't exist in network if false
		if (_bUseTOPOutputFilter && _topNodeFilter != "")
		{
		    if (!nodeName.StartsWith(_topNodeFilter))
		    {
			topNodeData._tags._show = false;
		    }
		}

		if (_bUseTOPOutputFilter)
		{
		    bool bAutoLoad = false;
		    if (_topOutputFilter == "")
		    {
			bAutoLoad = true;
		    }
		    else if (nodeName.StartsWith(_topOutputFilter))
		    {
			bAutoLoad = true;
		    }

		    topNodeData._tags._autoload |= bAutoLoad;
		    topNodeData._showResults = topNodeData._tags._autoload;
		}
	    }

	    // Clear old unused TOP nodes
	    for (int i = 0; i < topNetwork._topNodes.Count; ++i)
	    {
		ClearTOPNodeWorkItemResults(topNetwork._topNodes[i]);
	    }
	    topNetwork._topNodes = newNodes;

	    // Get list of updated TOP node names
	    SetupTopNetworkNames(topNetwork);

	    return true;
	}
		/// <summary>
		/// Returns the node info for the given node.
		/// </summary>
		/// <param name="nodeID">The node to retrieve the node info for</param>
		/// <param name="nodeInfo">The node info structure to populate</param>
		/// <param name="bLogError">True to log any error</param>
		/// <returns>True if successfully queried the node info</returns>
		public virtual bool GetNodeInfo(HAPI_NodeId nodeID, ref HAPI_NodeInfo nodeInfo, bool bLogError = true)
		{
			return false;
		}