Esempio n. 1
0
	/// <summary>
	/// Retrieves object info from Houdini session and updates internal state.
	/// New geo nodes are created, unused geo nodes are destroyed.
	/// Geo nodes are then refreshed to be in sync with Houdini session.
	/// </summary>
	/// <returns>True if internal state has changed (including geometry).</returns>
	internal void UpdateObject(HEU_SessionBase session, bool bForceUpdate)
	{
	    if (ParentAsset == null)
	    {
		return;
	    }

	    // Update the geo info
	    if (!session.GetObjectInfo(ObjectID, ref _objectInfo))
	    {
		return;
	    }
	    SyncWithObjectInfo(session);

	    // Update the object transform
	    _objectTransform = ParentAsset.GetObjectTransform(session, ObjectID);

	    // Container for existing geo nodes that are still in use
	    List<HEU_GeoNode> geoNodesToKeep = new List<HEU_GeoNode>();

	    // Container for new geo infos that need to be created
	    List<HAPI_GeoInfo> newGeoInfosToCreate = new List<HAPI_GeoInfo>();

	    if (_objectInfo.haveGeosChanged || bForceUpdate)
	    {
		// Indicates that the geometry nodes have changed
		//HEU_Logger.Log("Geos have changed!");

		// Form a list of geo infos that are now present after cooking
		List<HAPI_GeoInfo> postCookGeoInfos = new List<HAPI_GeoInfo>();


		bool useOutputNodes = true;
		if (ParentAsset) useOutputNodes = ParentAsset.UseOutputNodes;

		HEU_HAPIUtility.GatherAllAssetGeoInfos(session, ParentAsset.AssetInfo, _objectInfo, useOutputNodes, ref postCookGeoInfos);

		// Now for each geo node that are present after cooking, we check if its
		// new or whether we already have it prior to cooking.
		int numPostCookGeoInfos = postCookGeoInfos.Count;
		for (int i = 0; i < numPostCookGeoInfos; i++)
		{
		    bool bFound = false;
		    for (int j = 0; j < _geoNodes.Count; j++)
		    {
			string geoName = HEU_SessionManager.GetString(postCookGeoInfos[i].nameSH, session);
			if (geoName.Equals(_geoNodes[j].GeoName))
			{
			    _geoNodes[j].SetGeoInfo(postCookGeoInfos[i]);

			    geoNodesToKeep.Add(_geoNodes[j]);
			    _geoNodes.RemoveAt(j);

			    bFound = true;
			    break;
			}
		    }

		    if (!bFound)
		    {
			newGeoInfosToCreate.Add(postCookGeoInfos[i]);
		    }
		}

		// Whatever is left in _geoNodes is no longer needed so clean up
		int numCurrentGeos = _geoNodes.Count;
		for (int i = 0; i < numCurrentGeos; ++i)
		{
		    _geoNodes[i].DestroyAllData();
		}
	    }
	    else
	    {
		Debug.Assert(_objectInfo.geoCount == _geoNodes.Count, "Expected same number of geometry nodes.");
	    }

	    // Go through the old geo nodes that are still in use and update if necessary.
	    foreach (HEU_GeoNode geoNode in geoNodesToKeep)
	    {
		// Get geo info and check if geo changed
		bool bGeoChanged = bForceUpdate || geoNode.HasGeoNodeChanged(session);
		if (bGeoChanged)
		{
		    geoNode.UpdateGeo(session);
		}
		else
		{
		    if (_objectInfo.haveGeosChanged)
		    {
			// Clear object instances since the object info has changed.
			// Without this, the object instances were never getting updated
			// if only the inputs changed but not outputs (of instancers).
			geoNode.ClearObjectInstances();
		    }

		    // Visiblity might have changed, so update that
		    geoNode.CalculateVisiblity(IsVisible());
		    geoNode.CalculateColliderState();
		}
	    }

	    // Create the new geo infos and add to our keep list
	    foreach (HAPI_GeoInfo newGeoInfo in newGeoInfosToCreate)
	    {
		geoNodesToKeep.Add(CreateGeoNode(session, newGeoInfo));
	    }

	    // Overwrite the old list with new
	    _geoNodes = geoNodesToKeep;

	    // Updating the trasform is done in GenerateGeometry
	}
Esempio n. 2
0
	/// <summary>
	/// Retrieves object info from Houdini session and updates internal state.
	/// New geo nodes are created, unused geo nodes are destroyed.
	/// Geo nodes are then refreshed to be in sync with Houdini session.
	/// </summary>
	/// <returns>True if internal state has changed (including geometry).</returns>
	public void UpdateObject(HEU_SessionBase session, bool bForceUpdate)
	{
	    // Update the geo info
	    if (!session.GetObjectInfo(ObjectID, ref _objectInfo))
	    {
		return;
	    }
	    SyncWithObjectInfo(session);

	    // Update the object transform
	    _objectTransform = ParentAsset.GetObjectTransform(session, ObjectID);

	    // Container for existing geo nodes that are still in use
	    List<HEU_GeoNode> geoNodesToKeep = new List<HEU_GeoNode>();

	    // Container for new geo infos that need to be created
	    List<HAPI_GeoInfo> newGeoInfosToCreate = new List<HAPI_GeoInfo>();

	    if (_objectInfo.haveGeosChanged || bForceUpdate)
	    {
		// Indicates that the geometry nodes have changed
		//Debug.Log("Geos have changed!");

		// Form a list of geo infos that are now present after cooking
		List<HAPI_GeoInfo> postCookGeoInfos = new List<HAPI_GeoInfo>();

		// Get the display geo info
		HAPI_GeoInfo displayGeoInfo = new HAPI_GeoInfo();
		if (session.GetDisplayGeoInfo(_objectInfo.nodeId, ref displayGeoInfo, false))
		{
		    postCookGeoInfos.Add(displayGeoInfo);
		}
		else
		{
		    displayGeoInfo.nodeId = HEU_Defines.HEU_INVALID_NODE_ID;
		}

		// Get editable nodes, cook em, then create geo nodes for them
		HAPI_NodeId[] editableNodes = null;
		HEU_SessionManager.GetComposedChildNodeList(session, _objectInfo.nodeId, (int)HAPI_NodeType.HAPI_NODETYPE_SOP, (int)HAPI_NodeFlags.HAPI_NODEFLAGS_EDITABLE, true, out editableNodes);
		if (editableNodes != null)
		{
		    foreach (HAPI_NodeId editNodeID in editableNodes)
		    {
			if (editNodeID != displayGeoInfo.nodeId)
			{
			    session.CookNode(editNodeID, HEU_PluginSettings.CookTemplatedGeos);

			    HAPI_GeoInfo editGeoInfo = new HAPI_GeoInfo();
			    if (session.GetGeoInfo(editNodeID, ref editGeoInfo))
			    {
				postCookGeoInfos.Add(editGeoInfo);
			    }
			}
		    }
		}

		// Now for each geo node that are present after cooking, we check if its
		// new or whether we already have it prior to cooking.
		int numPostCookGeoInfos = postCookGeoInfos.Count;
		for (int i = 0; i < numPostCookGeoInfos; i++)
		{
		    bool bFound = false;
		    for (int j = 0; j < _geoNodes.Count; j++)
		    {
			string geoName = HEU_SessionManager.GetString(postCookGeoInfos[i].nameSH, session);
			if (geoName.Equals(_geoNodes[j].GeoName))
			{
			    _geoNodes[j].SetGeoInfo(postCookGeoInfos[i]);

			    geoNodesToKeep.Add(_geoNodes[j]);
			    _geoNodes.RemoveAt(j);

			    bFound = true;
			    break;
			}
		    }

		    if (!bFound)
		    {
			newGeoInfosToCreate.Add(postCookGeoInfos[i]);
		    }
		}

		// Whatever is left in _geoNodes is no longer needed so clean up
		int numCurrentGeos = _geoNodes.Count;
		for (int i = 0; i < numCurrentGeos; ++i)
		{
		    _geoNodes[i].DestroyAllData();
		}
	    }
	    else
	    {
		Debug.Assert(_objectInfo.geoCount == _geoNodes.Count, "Expected same number of geometry nodes.");
	    }

	    // Go through the old geo nodes that are still in use and update if necessary.
	    foreach (HEU_GeoNode geoNode in geoNodesToKeep)
	    {
		// Get geo info and check if geo changed
		bool bGeoChanged = bForceUpdate || geoNode.HasGeoNodeChanged(session);
		if (bGeoChanged)
		{
		    geoNode.UpdateGeo(session);
		}
		else
		{
		    if (_objectInfo.haveGeosChanged)
		    {
			// Clear object instances since the object info has changed.
			// Without this, the object instances were never getting updated
			// if only the inputs changed but not outputs (of instancers).
			geoNode.ClearObjectInstances();
		    }

		    // Visiblity might have changed, so update that
		    geoNode.CalculateVisiblity(IsVisible());
		    geoNode.CalculateColliderState();
		}
	    }

	    // Create the new geo infos and add to our keep list
	    foreach (HAPI_GeoInfo newGeoInfo in newGeoInfosToCreate)
	    {
		geoNodesToKeep.Add(CreateGeoNode(session, newGeoInfo));
	    }

	    // Overwrite the old list with new
	    _geoNodes = geoNodesToKeep;

	    // Updating the trasform is done in GenerateGeometry
	}
        /// <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);
        }