Beispiel #1
0
		/// <summary>
		/// Loads a copy of the srcAsset at copyPath. Creates a copy if not found.
		/// </summary>
		/// <param name="srcAsset">The source asset object</param>
		/// <param name="copyPath">The full path to the copy</param>
		/// <param name="type">The type of source asset</param>
		/// <param name="bOverwriteExisting">Whether to overwrite existing copy if found</param>
		/// <returns>Returns loaded copy if exists or created, otherwise null</returns>
		public static Object CopyAndLoadAssetAtAnyPath(Object srcAsset, string copyPath, System.Type type, bool bOverwriteExisting)
		{
#if UNITY_EDITOR
			string srcAssetPath = GetAssetPath(srcAsset);
			if (!string.IsNullOrEmpty(srcAssetPath))
			{
				CreatePathWithFolders(copyPath);

				string fileName = HEU_Platform.GetFileName(srcAssetPath);
				string fullCopyPath = HEU_Platform.BuildPath(copyPath, fileName);

				if ((!bOverwriteExisting && HEU_Platform.DoesFileExist(fullCopyPath)) || CopyAsset(srcAssetPath, fullCopyPath))
				{
					// Refresh database as otherwise we won't be able to load it in the next line.
					SaveAndRefreshDatabase();

					return LoadAssetAtPath(fullCopyPath, type);
				}
				else
				{
					Debug.LogErrorFormat("Failed to copy and load asset from {0} to {1}!", srcAssetPath, fullCopyPath);
				}
			}
			return null;
#else
			// TODO RUNTIME: AssetDatabase is not supported at runtime. Do we need to support this for runtime?
			Debug.LogWarning(HEU_Defines.HEU_USERMSG_NONEDITOR_NOT_SUPPORTED);
			return null;
#endif
		}
		/// <summary>
		/// Build up the asset environment paths set in unity_houdini.env.
		/// The paths must have key prefixes start with HEU_Defines.HEU_ENVPATH_PREFIX.
		/// When assets are loaded, these mappings are used to find real paths.
		/// </summary>
		public void LoadAssetEnvironmentPaths()
		{
			string envPath = HEU_Platform.GetHoudiniEngineEnvironmentFilePathFull();
			if (!string.IsNullOrEmpty(envPath) && HEU_Platform.DoesFileExist(envPath))
			{
				_envPathMap = new Dictionary<string, string>();
				char[] delimiter = new char[] { '=' };
				char[] trimEnd = new char[] { '\\', '/' };

				using (var file = new System.IO.StreamReader(envPath))
				{
					string line;
					while((line = file.ReadLine()) != null)
					{
						if (line.StartsWith(HEU_Defines.HEU_ENVPATH_PREFIX))
						{
							string[] split = line.Split(delimiter, 2, System.StringSplitOptions.RemoveEmptyEntries);
							if(split != null && split.Length == 2)
							{
								string value = split[1].Replace("\\", "/").TrimEnd(trimEnd);
								_envPathMap.Add(split[0], value);
							}
						}
					}
				}
			}
		}
Beispiel #3
0
        /// <summary>
        /// For the file path, returns a valid location if exists.
        /// If inFilePath is not valid, it uses the file name to search the asset database to
        /// find the actual valid location (in case it was moved).
        /// </summary>
        /// <param name="gameObjectName">Name of the asset for which to find the path.</param>
        /// <param name="inFilePath">Current path of the asset to validate. Could be null or invalid.</param>
        /// <returns>Valid path or null if none found.</returns>
        public static string LocateValidFilePath(string assetName, string inFilePath)
        {
#if UNITY_EDITOR
            // Convert in path to real path if it was environment mapped previously (ie. has $key/blah.hda)
            inFilePath = HEU_PluginStorage.Instance.ConvertEnvKeyedPathToReal(inFilePath);

            // Find asset if its not at given path
            if (!HEU_Platform.DoesFileExist(inFilePath))
            {
                string   fileName = HEU_Platform.GetFileNameWithoutExtension(inFilePath);
                string[] guids    = AssetDatabase.FindAssets(fileName);
                if (guids.Length > 0)
                {
                    foreach (string guid in guids)
                    {
                        string newPath = AssetDatabase.GUIDToAssetPath(guid);
                        if (newPath != null && newPath.Length > 0)
                        {
                            Debug.Log(string.Format("Note: changing asset path for {0} to {1}.", assetName, newPath));
                            return(newPath);
                        }
                    }
                }

                // No valid path
                throw new HEU_HoudiniEngineError(string.Format("Houdini Asset file has moved from last location: {0}", inFilePath));
            }
#endif
            return(inFilePath);
        }
Beispiel #4
0
        /// <summary>
        /// For the file path, returns a valid location if exists.
        /// If inFilePath is not valid, it uses the file name to search the asset database to
        /// find the actual valid location (in case it was moved).
        /// </summary>
        /// <param name="gameObjectName">Name of the asset for which to find the path.</param>
        /// <param name="inFilePath">Current path of the asset to validate. Could be null or invalid.</param>
        /// <returns>Valid path or null if none found.</returns>
        public static string LocateValidFilePath(string assetName, string inFilePath)
        {
#if UNITY_EDITOR
            // Find asset if its not at given path
            if (!HEU_Platform.DoesFileExist(inFilePath))
            {
                string   fileName = HEU_Platform.GetFileNameWithoutExtension(inFilePath);
                string[] guids    = AssetDatabase.FindAssets(fileName);
                if (guids.Length > 0)
                {
                    foreach (string guid in guids)
                    {
                        string newPath = AssetDatabase.GUIDToAssetPath(guid);
                        if (newPath != null && newPath.Length > 0)
                        {
                            Debug.Log(string.Format("Note: changing asset path for {0} to {1}.", assetName, newPath));
                            return(newPath);
                        }
                    }
                }

                // No valid path
                throw new HEU_HoudiniEngineError(string.Format("Houdini Asset file has moved from last location: {0}", inFilePath));
            }
#endif
            return(inFilePath);
        }
Beispiel #5
0
		private void SelectShelf(int index)
		{
			int numShelves = HEU_ShelfTools.GetNumShelves();
			if(index >= 0 && index < numShelves)
			{
				HEU_Shelf shelf = HEU_ShelfTools.GetShelf(index);
				if (shelf != null)
				{
					int numTools = shelf._tools.Count;
					_guiContents = new GUIContent[numTools];

					for (int i = 0; i < numTools; ++i)
					{
						_guiContents[i] = new GUIContent();
						_guiContents[i].text = shelf._tools[i]._name;

						if (HEU_Platform.DoesFileExist(shelf._tools[i]._iconPath))
						{
							_guiContents[i].image = HEU_GeneralUtility.LoadTextureFromFile(shelf._tools[i]._iconPath);
						}
						
						_guiContents[i].tooltip = shelf._tools[i]._toolTip;
					}
				}
			}
		}
	public virtual bool DoAssetLoad()
	{
	    string assetPath = _filePath;
	    if (!HEU_Platform.DoesFileExist(assetPath))
	    {
		assetPath = HEU_AssetDatabase.GetValidAssetPath(assetPath);
	    }

	    HAPI_NodeId libraryID = -1;
	    HAPI_NodeId newNodeID = -1;

	    byte[] buffer = null;
	    bool bResult = HEU_Platform.LoadFileIntoMemory(assetPath, out buffer);
	    if (bResult)
	    {
		if (!_session.LoadAssetLibraryFromMemory(buffer, true, out libraryID))
		{
		    HEU_Logger.LogErrorFormat("Unable to load asset library.");
		    return false;
		}
		//HEU_Logger.Log("Loaded asset");

		int assetCount = 0;
		bResult = _session.GetAvailableAssetCount(libraryID, out assetCount);
		if (!bResult)
		{
		    return false;
		}

		int[] assetNameLengths = new int[assetCount];
		bResult = _session.GetAvailableAssets(libraryID, ref assetNameLengths, assetCount);
		if (!bResult)
		{
		    return false;
		}

		string[] assetNames = new string[assetCount];
		for (int i = 0; i < assetCount; ++i)
		{
		    assetNames[i] = HEU_SessionManager.GetString(assetNameLengths[i], _session);
		}

		// Create top level node. Note that CreateNode will cook the node if HAPI was initialized with threaded cook setting on.
		string topNodeName = assetNames[0];
		bResult = _session.CreateNode(-1, topNodeName, "", false, out newNodeID);
		if (!bResult)
		{
		    return false;
		}
		//HEU_Logger.Log("Created asset node");

		_loadData._cookNodeID = newNodeID;
	    }

	    return true;
	}
		public static string GetHoudiniEngineEnvironmentFilePathFull()
		{
			string envPath = HEU_PluginSettings.HoudiniEngineEnvFilePath;

			if (!HEU_Platform.IsPathRooted(envPath))
			{
				envPath = HEU_AssetDatabase.GetAssetFullPath(envPath);
			}

			return HEU_Platform.DoesFileExist(envPath) ? envPath : "";
		}
Beispiel #8
0
	/// <summary>
	/// Create the given object inside the asset cache folder path, with relative folder path.
	/// Depending on type, it might store in a subfolder for organizational purposes.
	/// </summary>
	/// <param name="objectToCreate">The object to create inside the asset cache</param>
	/// <param name="assetCacheRoot">The target path in the asset cache</param>
	/// <param name="relativeFolderPath">If not null or empty, the relative path to append to the assetCacheRoot. 
	/// Otherwise uses type of asset to get subfolder name.</param>
	/// <param name="assetFileName">The asset's file name</param>
	/// <param name="type">The type of asset</param>
	/// <param name="bOverwriteExisting">Whether or not to overwrite if there is an existing file</param>
	public static void CreateObjectInAssetCacheFolder(Object objectToCreate, string assetCacheRoot, string relativeFolderPath, string assetFileName, System.Type type, bool bOverwriteExisting)
	{
#if UNITY_EDITOR
	    Debug.Assert(!string.IsNullOrEmpty(assetCacheRoot), "Must give valid assetCacheFolderPath to create object at");

	    string subFolderPath = assetCacheRoot;

	    if (!string.IsNullOrEmpty(relativeFolderPath))
	    {
		subFolderPath = HEU_Platform.BuildPath(subFolderPath, relativeFolderPath);
	    }
	    else
	    {
		if (type == typeof(Mesh))
		{
		    subFolderPath = AppendMeshesPathToAssetFolder(assetCacheRoot);
		}
		else if (type == typeof(Material))
		{
		    subFolderPath = AppendMaterialsPathToAssetFolder(assetCacheRoot);
		}
		else if (type == typeof(TerrainData)
#if UNITY_2018_3_OR_NEWER
				|| (type == typeof(TerrainLayer))
#else
				|| (type == typeof(SplatPrototype))
#endif
				)
		{
		    subFolderPath = AppendTerrainPathToAssetFolder(assetCacheRoot);
		}
	    }

	    // Make sure subfolders exist
	    HEU_AssetDatabase.CreatePathWithFolders(subFolderPath);

	    // Add file name
	    string finalAssetPath = HEU_Platform.BuildPath(subFolderPath, assetFileName);

	    if (HEU_Platform.DoesFileExist(finalAssetPath) && !bOverwriteExisting)
	    {
		finalAssetPath = AssetDatabase.GenerateUniqueAssetPath(finalAssetPath);
	    }

	    AssetDatabase.CreateAsset(objectToCreate, finalAssetPath);

	    // Commented out AssetDatabase.Refresh() below because its slow and seems to be unnecessary.
	    // Leaving it commented in case need to revisit due to problems with asset creation.
	    //RefreshAssetDatabase();
#else
			// TODO RUNTIME: AssetDatabase is not supported at runtime. Do we need to support this for runtime?
			Debug.LogWarning(HEU_Defines.HEU_USERMSG_NONEDITOR_NOT_SUPPORTED);
#endif
	}
Beispiel #9
0
 /// <summary>
 /// Finds Houdini asset at given file path by matching potential extensions.
 /// </summary>
 /// <param name="filePath">Path of file without extension</param>
 /// <returns>Valid path with extension or null of no asset found</returns>
 public static string FindHoudiniAssetFileInPathWithExt(string filePath)
 {
     string[] extensions = new string[] { ".otl", ".otllc", ".otlnc", ".hda", ".hdalc", ".hdanc" };
     foreach (string ext in extensions)
     {
         string newPath = filePath + ext;
         if (HEU_Platform.DoesFileExist(newPath))
         {
             return(newPath);
         }
     }
     return(null);
 }
		/// <summary>
		/// Loads a copy of the given asset. Creates the copy if not found.
		/// </summary>
		/// <param name="srcAsset">Source asset whose copy will be loaded (and created if no copy exists).</param>
		/// <param name="newAssetFolderPath">Folder of to look for copy or create in</param>
		/// <param name="type">Type of asset</param>
		/// <returns>Loaded copy of the asset</returns>
		public static Object LoadAssetCopy(Object srcAsset, string newAssetFolderPath, System.Type type, bool bOverwriteExisting)
		{
#if UNITY_EDITOR
			string srcAssetPath = GetAssetPath(srcAsset);
			if (!string.IsNullOrEmpty(srcAssetPath) && IsPathInAssetCache(srcAssetPath))
			{
				string subFolderPath = newAssetFolderPath;
				if(type == typeof(Material))
				{
					subFolderPath = AppendMaterialsPathToAssetFolder(newAssetFolderPath);
				}
				else if(type == typeof(Texture))
				{
					subFolderPath = AppendTexturesPathToAssetFolder(newAssetFolderPath);
				}
				else if (type == typeof(Mesh))
				{
					subFolderPath = AppendMeshesPathToAssetFolder(newAssetFolderPath);
				}
				else if (type == typeof(TerrainData))
				{
					subFolderPath = AppendTerrainPathToAssetFolder(newAssetFolderPath);
				}

				CreatePathWithFolders(subFolderPath);

				string fileName = HEU_Platform.GetFileName(srcAssetPath);
				string newAssetPath = HEU_Platform.BuildPath(subFolderPath, fileName);

				if ((!bOverwriteExisting && HEU_Platform.DoesFileExist(newAssetPath)) || CopyAsset(srcAssetPath, newAssetPath))
				{
					// Refresh database as otherwise we won't be able to load it in the next line.
					SaveAndRefreshDatabase();

					return LoadAssetAtPath(newAssetPath, type);
				}
				else
				{
					Debug.LogErrorFormat("Failed to copy and load asset from {0} to {1}!", srcAssetPath, newAssetPath);
				}
			}
			return null;
#else
			// TODO RUNTIME: AssetDatabase is not supported at runtime. Do we need to support this for runtime?
			Debug.LogWarning(HEU_Defines.HEU_USERMSG_NONEDITOR_NOT_SUPPORTED);
			return null;
#endif
		}
Beispiel #11
0
        /// <summary>
        /// Load and instantiate an HDA asset in Unity and Houdini, for the asset located at given path.
        /// </summary>
        /// <param name="filePath">Full path to the HDA in Unity project</param>
        /// <param name="initialPosition">Initial location to create the instance in Unity.</param>
        /// <returns>Returns the newly created gameobject for the asset in the scene, or null if creation failed.</returns>
        public static GameObject InstantiateHDA(string filePath, Vector3 initialPosition, HEU_SessionBase session, bool bBuildAsync)
        {
            if (filePath == null || !HEU_Platform.DoesFileExist(filePath))
            {
                return(null);
            }

            // This will be the root GameObject for the HDA. Adding HEU_HoudiniAssetRoot
            // allows to use a custom Inspector.
            GameObject           rootGO    = new GameObject(HEU_Defines.HEU_DEFAULT_ASSET_NAME);
            HEU_HoudiniAssetRoot assetRoot = rootGO.AddComponent <HEU_HoudiniAssetRoot>();

            // Under the root, we'll add the HEU_HoudiniAsset onto another GameObject
            // This will be marked as EditorOnly to strip out for builds
            GameObject hdaGEO = new GameObject(HEU_PluginSettings.HDAData_Name);

            hdaGEO.transform.parent = rootGO.transform;

            // This holds all Houdini Engine data
            HEU_HoudiniAsset asset = hdaGEO.AddComponent <HEU_HoudiniAsset>();

            // Marking as EditorOnly to be excluded from builds
            if (HEU_GeneralUtility.DoesUnityTagExist(HEU_PluginSettings.EditorOnly_Tag))
            {
                hdaGEO.tag = HEU_PluginSettings.EditorOnly_Tag;
            }

            // Bind the root to the asset
            assetRoot._houdiniAsset = asset;

            // Populate asset with what we know
            asset.SetupAsset(HEU_HoudiniAsset.HEU_AssetType.TYPE_HDA, filePath, rootGO, session);

            // Build it in Houdini Engine
            asset.RequestReload(bBuildAsync);

            // Apply Unity transform and possibly upload to Houdini Engine
            rootGO.transform.position = initialPosition;

            Debug.LogFormat("{0}: Created new HDA asset from {1} of type {2}.", HEU_Defines.HEU_NAME, filePath, asset.AssetType);

            return(rootGO);
        }
		/// <summary>
		/// Loads image file and return as Texture.
		/// Presumes image file is PNG or JPG format (i.e. supported by Texture2D.LoadImage).
		/// </summary>
		/// <param name="filePath">Path to image file</param>
		/// <returns>Loaded texture or null if failed</returns>
		public static Texture LoadTextureFromFile(string filePath)
		{
			Texture2D newTexture = null;

			if (HEU_Platform.DoesFileExist(filePath))
			{
				try
				{
					byte[] imageData = System.IO.File.ReadAllBytes(filePath);
					newTexture = new Texture2D(2, 2);
					newTexture.LoadImage(imageData);
					newTexture.Apply();
					return newTexture;
				}
				catch (Exception ex)
				{
					Debug.LogErrorFormat("Loading image at {0} triggered exception: {1}", filePath, ex);
				}
			}
			return newTexture;
		}
Beispiel #13
0
		public static HEU_ShelfToolData LoadToolFromJsonString(string json, string jsonFilePath)
		{
			//Debug.Log("Loading json: " + jsonFilePath);

			// Get environment variable for tool path
			string envValue = HEU_Platform.GetEnvironmentValue(HEU_Defines.HEU_PATH_KEY_TOOL);
			string envKey = string.Format("<{0}>", HEU_Defines.HEU_PATH_KEY_TOOL);

			HEU_ShelfToolData toolData = null;

			if (!string.IsNullOrEmpty(json))
			{
				try
				{
					JSONNode jsonShelfNode = JSON.Parse(json);
					if (jsonShelfNode != null)
					{
						bool isObject = jsonShelfNode.IsObject;
						bool isArray = jsonShelfNode.IsArray;

						toolData = new HEU_ShelfToolData();

						toolData._name = jsonShelfNode["name"];

						toolData._toolType = (HEU_ShelfToolData.ToolType)System.Enum.Parse(typeof(HEU_ShelfToolData.ToolType), jsonShelfNode["toolType"]);

						toolData._toolTip = jsonShelfNode["toolTip"];

						toolData._iconPath = jsonShelfNode["iconPath"];

						toolData._assetPath = jsonShelfNode["assetPath"];

						toolData._helpURL = jsonShelfNode["helpURL"];

						JSONArray targetArray = jsonShelfNode["target"].AsArray;
						if(targetArray != null)
						{
							int targetCount = targetArray.Count;
							toolData._targets = new string[targetCount];
							for(int j = 0; j < targetCount; ++j)
							{
								toolData._targets[j] = targetArray[j];
							}
						}
	}
				}
				catch (System.Exception ex)
				{
					Debug.LogErrorFormat("Exception when trying to parse shelf json file at path: {0}. Exception: {1}", jsonFilePath, ex.ToString());
					return null;
				}

				toolData._jsonPath = jsonFilePath;

				if (toolData != null && !string.IsNullOrEmpty(toolData._name))
				{
					// Make sure this tool targets Unity (must have "all" or "unity" set in target field)
					bool bCompatiple = false;
					if(toolData._targets != null)
					{
						int numTargets = toolData._targets.Length;
						for(int i = 0; i < numTargets; ++i)
						{
							if (toolData._targets[i].Equals(TARGET_ALL) || toolData._targets[i].Equals(TARGET_UNITY))
							{
								bCompatiple = true;
								break;
							}
						}
					}

					if (bCompatiple)
					{
						if (!string.IsNullOrEmpty(toolData._assetPath))
						{
							toolData._assetPath = toolData._assetPath.Replace(HEU_Defines.HEU_PATH_KEY_PROJECT + "/", "");
							if (toolData._assetPath.Contains(envKey))
							{
								if (string.IsNullOrEmpty(envValue))
								{
									Debug.LogErrorFormat("Environment value {0} used but not set in environment.", HEU_Defines.HEU_PATH_KEY_TOOL);
								}
								else
								{
									toolData._assetPath = toolData._assetPath.Replace(envKey, envValue);
								}
							}
						}
						else
						{
							toolData._assetPath = GetToolAssetPath(toolData, toolData._assetPath);
						}

						string realPath = HEU_PluginStorage.Instance.ConvertEnvKeyedPathToReal(toolData._assetPath);
						if (!HEU_Platform.DoesFileExist(realPath))
						{
							Debug.LogErrorFormat("Houdini Engine shelf tool at {0} does not exist!", realPath);
							return null;
						}

						if (!string.IsNullOrEmpty(toolData._iconPath))
						{
							toolData._iconPath = toolData._iconPath.Replace(HEU_Defines.HEU_PATH_KEY_PROJECT + "/", "");
							if (toolData._iconPath.Contains(envKey))
							{
								if (string.IsNullOrEmpty(envValue))
								{
									Debug.LogErrorFormat("Environment value {0} used but not set in environment.", HEU_Defines.HEU_PATH_KEY_TOOL);
								}
								else
								{
									toolData._iconPath = toolData._iconPath.Replace(envKey, envValue);
								}
							}
						}
						else
						{
							toolData._iconPath = GetToolIconPath(toolData, toolData._iconPath);
						}

						return toolData;
					}
				}
			}

			return null;
		}
		/// <summary>
		/// Load the saved plugin settings from disk.
		/// </summary>
		/// <returns>True if successfully loaded.</returns>
		public bool LoadPluginData()
		{
			// First check if settings pref file exists
			string settingsFilePath = SettingsFilePath();
			if (!HEU_Platform.DoesFileExist(settingsFilePath))
			{
				// Try reading from EditorPrefs to see if this is still using the old method
				return ReadFromEditorPrefs();
			}

			// Open file and read each line to create the settings entry
			using (StreamReader reader = new StreamReader(settingsFilePath))
			{
				// Must match first line
				string line = reader.ReadLine();
				if (string.IsNullOrEmpty(line) || !line.Equals(PluginSettingsLine1))
				{
					Debug.LogWarningFormat("Unable to load Plugin settings file. {0} should have line 1: {1}", settingsFilePath, PluginSettingsLine1);
					return false;
				}

				// Must match 2nd line
				line = reader.ReadLine();
				if (string.IsNullOrEmpty(line) || !line.StartsWith(PluginSettingsLine2))
				{
					Debug.LogWarningFormat("Unable to load Plugin settings file. {0} should start line 2 with: {1}", settingsFilePath, PluginSettingsLine2);
					return false;
				}

				Dictionary<string, StoreData> storeMap = new Dictionary<string, StoreData>();
				string keyStr;
				string typeStr;
				string valueStr;
				DataType dataType;
				// "key(type)=value"
				System.Text.RegularExpressions.Regex regex = new System.Text.RegularExpressions.Regex(@"^(\w+)\((\w+)\)=(.*)");
				while ((line = reader.ReadLine()) != null)
				{
					System.Text.RegularExpressions.Match match = regex.Match(line);
					if (match.Success && match.Groups.Count >= 4)
					{
						keyStr = match.Groups[1].Value;
						typeStr = match.Groups[2].Value;
						valueStr = match.Groups[3].Value;
						
						if (!string.IsNullOrEmpty(keyStr) && !string.IsNullOrEmpty(typeStr) 
							&& !string.IsNullOrEmpty(valueStr))
						{
							try
							{
								dataType = (DataType)System.Enum.Parse(typeof(DataType), typeStr);

								StoreData store = new StoreData();
								store._type = dataType;
								store._valueStr = valueStr;
								storeMap.Add(keyStr, store);
							}
							catch( System.Exception ex)
							{
								Debug.LogErrorFormat("Invalid data type found in settings: {0}. Exception: {1}", typeStr, ex.ToString());
							}
						}
					}
				}

				_dataMap = storeMap;
			}

			return true;
		}
        private void GenerateTerrain(HAPI_NodeId cookNodeId, List <HEU_LoadBufferVolume> terrainBuffers)
        {
            HEU_SessionBase session = GetHoudiniSession(true);
            Transform       parent  = this.gameObject.transform;

            // Directory to store generated terrain files.
            string outputTerrainpath = GetOutputCacheDirectory();

            outputTerrainpath = HEU_Platform.BuildPath(outputTerrainpath, "Terrain");

            int numVolumes = terrainBuffers.Count;

            for (int t = 0; t < numVolumes; ++t)
            {
                if (terrainBuffers[t]._heightMap != null)
                {
                    GameObject newGameObject = new GameObject("heightfield_" + terrainBuffers[t]._tileIndex);

                    HAPI_PartId partId = terrainBuffers[t]._id;
                    ApplyAttributeModifiersOnGameObjectOutput(session, cookNodeId, partId, ref newGameObject);

                    Transform newTransform = newGameObject.transform;
                    newTransform.parent = parent;

                    HEU_GeneratedOutput generatedOutput = new HEU_GeneratedOutput();
                    generatedOutput._outputData._gameObject = newGameObject;

                    Terrain terrain = HEU_GeneralUtility.GetOrCreateComponent <Terrain>(newGameObject);

#if !HEU_TERRAIN_COLLIDER_DISABLED
                    TerrainCollider collider = HEU_GeneralUtility.GetOrCreateComponent <TerrainCollider>(newGameObject);
#endif
                    // The TerrainData and TerrainLayer files needs to be saved out if we create them.
                    // Try user specified path, otherwise use the cache folder
                    string exportTerrainDataPath = terrainBuffers[t]._terrainDataExportPath;
                    if (string.IsNullOrEmpty(exportTerrainDataPath))
                    {
                        // This creates the relative folder path from the Asset's cache folder: {assetCache}/{geo name}/Terrain/Tile{tileIndex}/...
                        exportTerrainDataPath = HEU_Platform.BuildPath(outputTerrainpath, HEU_Defines.HEU_FOLDER_TERRAIN, HEU_Defines.HEU_FOLDER_TILE + terrainBuffers[t]._tileIndex);
                    }

                    bool bFullExportTerrainDataPath = HEU_Platform.DoesFileExist(exportTerrainDataPath);

                    if (!string.IsNullOrEmpty(terrainBuffers[t]._terrainDataPath))
                    {
                        // Load the source TerrainData, then make a unique copy of it in the cache folder

                        TerrainData sourceTerrainData = HEU_AssetDatabase.LoadAssetAtPath(terrainBuffers[t]._terrainDataPath, typeof(TerrainData)) as TerrainData;
                        if (sourceTerrainData == null)
                        {
                            Debug.LogWarningFormat("TerrainData, set via attribute, not found at: {0}", terrainBuffers[t]._terrainDataPath);
                        }

                        if (bFullExportTerrainDataPath)
                        {
                            terrain.terrainData = HEU_AssetDatabase.CopyAndLoadAssetAtGivenPath(sourceTerrainData, exportTerrainDataPath, typeof(TerrainData)) as TerrainData;
                        }
                        else
                        {
                            terrain.terrainData = HEU_AssetDatabase.CopyUniqueAndLoadAssetAtAnyPath(sourceTerrainData, exportTerrainDataPath, typeof(TerrainData)) as TerrainData;
                        }

                        if (terrain.terrainData != null)
                        {
                            // Store path so that it can be deleted on clean up
                            AddGeneratedOutputFilePath(HEU_AssetDatabase.GetAssetPath(terrain.terrainData));
                        }
                    }

                    if (terrain.terrainData == null)
                    {
                        terrain.terrainData = new TerrainData();

                        if (bFullExportTerrainDataPath)
                        {
                            string folderPath = HEU_Platform.GetFolderPath(exportTerrainDataPath, true);
                            HEU_AssetDatabase.CreatePathWithFolders(folderPath);
                            HEU_AssetDatabase.CreateAsset(terrain.terrainData, exportTerrainDataPath);
                        }
                        else
                        {
                            string assetPathName = "TerrainData" + HEU_Defines.HEU_EXT_ASSET;
                            HEU_AssetDatabase.CreateObjectInAssetCacheFolder(terrain.terrainData, exportTerrainDataPath, null, assetPathName, typeof(TerrainData));
                        }
                    }
                    TerrainData terrainData = terrain.terrainData;

#if !HEU_TERRAIN_COLLIDER_DISABLED
                    collider.terrainData = terrainData;
#endif

                    HEU_TerrainUtility.SetTerrainMaterial(terrain, terrainBuffers[t]._specifiedTerrainMaterialName);

#if UNITY_2018_3_OR_NEWER
                    terrain.allowAutoConnect = true;
                    // This has to be set after setting material
                    terrain.drawInstanced = true;
#endif

                    int heightMapSize = terrainBuffers[t]._heightMapWidth;

                    terrainData.heightmapResolution = heightMapSize;
                    if (terrainData.heightmapResolution != heightMapSize)
                    {
                        Debug.LogErrorFormat("Unsupported terrain size: {0}", heightMapSize);
                        continue;
                    }

                    // The terrainData.baseMapResolution is not set here, but rather left to whatever default Unity uses
                    // The terrainData.alphamapResolution is set later when setting the alphamaps.

                    // 32 is the default for resolutionPerPatch
                    const int detailResolution   = 1024;
                    const int resolutionPerPatch = 32;
                    terrainData.SetDetailResolution(detailResolution, resolutionPerPatch);

                    terrainData.SetHeights(0, 0, terrainBuffers[t]._heightMap);

                    // Note that Unity uses a default height range of 600 when a flat terrain is created.
                    // Without a non-zero value for the height range, user isn't able to draw heights.
                    // Therefore, set 600 as the value if height range is currently 0 (due to flat heightfield).
                    float heightRange = terrainBuffers[t]._heightRange;
                    if (heightRange == 0)
                    {
                        heightRange = 600;
                    }

                    terrainData.size = new Vector3(terrainBuffers[t]._terrainSizeX, heightRange, terrainBuffers[t]._terrainSizeY);

                    terrain.Flush();

                    // Set position
                    HAPI_Transform hapiTransformVolume = new HAPI_Transform(true);
                    hapiTransformVolume.position[0] += terrainBuffers[t]._position[0];
                    hapiTransformVolume.position[1] += terrainBuffers[t]._position[1];
                    hapiTransformVolume.position[2] += terrainBuffers[t]._position[2];
                    HEU_HAPIUtility.ApplyLocalTransfromFromHoudiniToUnity(ref hapiTransformVolume, newTransform);

                    // Set layers
                    Texture2D defaultTexture = HEU_VolumeCache.LoadDefaultSplatTexture();
                    int       numLayers      = terrainBuffers[t]._splatLayers.Count;

#if UNITY_2018_3_OR_NEWER
                    // Create TerrainLayer for each heightfield layer.
                    // Note that height and mask layers are ignored (i.e. not created as TerrainLayers).
                    // Since height layer is first, only process layers from 2nd index onwards.
                    if (numLayers > 1)
                    {
                        // Keep existing TerrainLayers, and either update or append to them
                        TerrainLayer[] existingTerrainLayers = terrainData.terrainLayers;

                        // Total layers are existing layers + new alpha maps
                        List <TerrainLayer> finalTerrainLayers = new List <TerrainLayer>(existingTerrainLayers);

                        for (int m = 1; m < numLayers; ++m)
                        {
                            TerrainLayer terrainlayer = null;

                            int terrainLayerIndex = -1;

                            bool bSetTerrainLayerProperties = true;

                            HEU_LoadBufferVolumeLayer layer = terrainBuffers[t]._splatLayers[m];

                            // Look up TerrainLayer file via attribute if user has set it
                            if (!string.IsNullOrEmpty(layer._layerPath))
                            {
                                terrainlayer = HEU_AssetDatabase.LoadAssetAtPath(layer._layerPath, typeof(TerrainLayer)) as TerrainLayer;
                                if (terrainlayer == null)
                                {
                                    Debug.LogWarningFormat("TerrainLayer, set via attribute, not found at: {0}", layer._layerPath);
                                    continue;
                                }
                                else
                                {
                                    // Always check if its part of existing list so as not to add it again
                                    terrainLayerIndex = HEU_TerrainUtility.GetTerrainLayerIndex(terrainlayer, existingTerrainLayers);
                                }
                            }

                            if (terrainlayer == null)
                            {
                                terrainlayer      = new TerrainLayer();
                                terrainLayerIndex = finalTerrainLayers.Count;
                                finalTerrainLayers.Add(terrainlayer);
                            }
                            else
                            {
                                // For existing TerrainLayer, make a copy of it if it has custom layer attributes
                                // because we don't want to change the original TerrainLayer.
                                if (layer._hasLayerAttributes)
                                {
                                    // Copy the TerrainLayer file
                                    TerrainLayer prevTerrainLayer = terrainlayer;
                                    terrainlayer = HEU_AssetDatabase.CopyAndLoadAssetAtAnyPath(terrainlayer, outputTerrainpath, typeof(TerrainLayer), true) as TerrainLayer;
                                    if (terrainlayer != null)
                                    {
                                        if (terrainLayerIndex >= 0)
                                        {
                                            // Update the TerrainLayer reference in the list with this copy
                                            finalTerrainLayers[terrainLayerIndex] = terrainlayer;
                                        }
                                        else
                                        {
                                            // Newly added
                                            terrainLayerIndex = finalTerrainLayers.Count;
                                            finalTerrainLayers.Add(terrainlayer);
                                        }

                                        // Store path for clean up later
                                        AddGeneratedOutputFilePath(HEU_AssetDatabase.GetAssetPath(terrainlayer));
                                    }
                                    else
                                    {
                                        Debug.LogErrorFormat("Unable to copy TerrainLayer '{0}' for generating Terrain. "
                                                             + "Using original TerrainLayer. Will not be able to set any TerrainLayer properties.", layer._layerName);
                                        terrainlayer = prevTerrainLayer;
                                        bSetTerrainLayerProperties = false;
                                        // Again, continuing on to keep proper indexing.
                                    }
                                }
                                else
                                {
                                    // Could be a layer in Assets/ but not part of existing layers in TerrainData
                                    terrainLayerIndex = finalTerrainLayers.Count;
                                    finalTerrainLayers.Add(terrainlayer);
                                    bSetTerrainLayerProperties = false;
                                }
                            }

                            if (bSetTerrainLayerProperties)
                            {
                                if (!string.IsNullOrEmpty(layer._diffuseTexturePath))
                                {
                                    terrainlayer.diffuseTexture = HEU_MaterialFactory.LoadTexture(layer._diffuseTexturePath);
                                }
                                if (terrainlayer.diffuseTexture == null)
                                {
                                    terrainlayer.diffuseTexture = defaultTexture;
                                }

                                terrainlayer.diffuseRemapMin = Vector4.zero;
                                terrainlayer.diffuseRemapMax = Vector4.one;

                                if (!string.IsNullOrEmpty(layer._maskTexturePath))
                                {
                                    terrainlayer.maskMapTexture = HEU_MaterialFactory.LoadTexture(layer._maskTexturePath);
                                }

                                terrainlayer.maskMapRemapMin = Vector4.zero;
                                terrainlayer.maskMapRemapMax = Vector4.one;

                                terrainlayer.metallic = layer._metallic;

                                if (!string.IsNullOrEmpty(layer._normalTexturePath))
                                {
                                    terrainlayer.normalMapTexture = HEU_MaterialFactory.LoadTexture(layer._normalTexturePath);
                                }

                                terrainlayer.normalScale = layer._normalScale;

                                terrainlayer.smoothness = layer._smoothness;
                                terrainlayer.specular   = layer._specularColor;
                                terrainlayer.tileOffset = layer._tileOffset;

                                if (layer._tileSize.magnitude == 0f && terrainlayer.diffuseTexture != null)
                                {
                                    // Use texture size if tile size is 0
                                    layer._tileSize = new Vector2(terrainlayer.diffuseTexture.width, terrainlayer.diffuseTexture.height);
                                }
                                terrainlayer.tileSize = layer._tileSize;
                            }
                        }
                        terrainData.terrainLayers = finalTerrainLayers.ToArray();
                    }
#else
                    // Need to create SplatPrototype for each layer in heightfield, representing the textures.
                    SplatPrototype[] splatPrototypes = new SplatPrototype[numLayers];
                    for (int m = 0; m < numLayers; ++m)
                    {
                        splatPrototypes[m] = new SplatPrototype();

                        HEU_LoadBufferVolumeLayer layer = terrainBuffers[t]._splatLayers[m];

                        Texture2D diffuseTexture = null;
                        if (!string.IsNullOrEmpty(layer._diffuseTexturePath))
                        {
                            diffuseTexture = HEU_MaterialFactory.LoadTexture(layer._diffuseTexturePath);
                        }
                        if (diffuseTexture == null)
                        {
                            diffuseTexture = defaultTexture;
                        }
                        splatPrototypes[m].texture = diffuseTexture;

                        splatPrototypes[m].tileOffset = layer._tileOffset;
                        if (layer._tileSize.magnitude == 0f && diffuseTexture != null)
                        {
                            // Use texture size if tile size is 0
                            layer._tileSize = new Vector2(diffuseTexture.width, diffuseTexture.height);
                        }
                        splatPrototypes[m].tileSize = layer._tileSize;

                        splatPrototypes[m].metallic   = layer._metallic;
                        splatPrototypes[m].smoothness = layer._smoothness;

                        if (!string.IsNullOrEmpty(layer._normalTexturePath))
                        {
                            splatPrototypes[m].normalMap = HEU_MaterialFactory.LoadTexture(layer._normalTexturePath);
                        }
                    }
                    terrainData.splatPrototypes = splatPrototypes;
#endif

                    // Set the splatmaps
                    if (terrainBuffers[t]._splatMaps != null)
                    {
                        // Set the alphamap size before setting the alphamaps to get correct scaling
                        // The alphamap size comes from the first alphamap layer
                        int alphamapResolution = terrainBuffers[t]._heightMapWidth;
                        if (numLayers > 1)
                        {
                            alphamapResolution = terrainBuffers[t]._splatLayers[1]._heightMapWidth;
                        }
                        terrainData.alphamapResolution = alphamapResolution;

                        terrainData.SetAlphamaps(0, 0, terrainBuffers[t]._splatMaps);
                    }

                    // Set the tree scattering
                    if (terrainBuffers[t]._scatterTrees != null)
                    {
                        HEU_TerrainUtility.ApplyScatterTrees(terrainData, terrainBuffers[t]._scatterTrees);
                    }

                    // Set the detail layers
                    if (terrainBuffers[t]._detailPrototypes != null)
                    {
                        HEU_TerrainUtility.ApplyDetailLayers(terrain, terrainData, terrainBuffers[t]._detailProperties,
                                                             terrainBuffers[t]._detailPrototypes, terrainBuffers[t]._detailMaps);
                    }

                    terrainBuffers[t]._generatedOutput = generatedOutput;
                    _generatedOutputs.Add(generatedOutput);

                    SetOutputVisiblity(terrainBuffers[t]);
                }
            }
        }
Beispiel #16
0
        /// <summary>
        /// Returns true if file at inPath exists. Supports inPath with environment mapped values
        /// such as <HFS> or $.
        /// </summary>
        /// <param name="inPath">Path to file</param>
        /// <returns>True if file exists</returns>
        public static bool DoesMappedFileAtPathExist(string inPath)
        {
            string realPath = HEU_PluginStorage.Instance.ConvertEnvKeyedPathToReal(inPath);

            return(HEU_Platform.DoesFileExist(realPath));
        }