4574 lines
178 KiB
C#
4574 lines
178 KiB
C#
using UnityEngine;
|
|
#if UNITY_EDITOR
|
|
using UnityEditor;
|
|
using UnityEditor.SceneManagement;
|
|
using UnityEditor.UIElements;
|
|
using UnityEditor.VersionControl;
|
|
#endif
|
|
using System.Collections;
|
|
using System.IO;
|
|
using System;
|
|
using System.Collections.Generic;
|
|
using System.Reflection;
|
|
using System.Runtime.Serialization.Formatters.Binary;
|
|
using System.Runtime.Serialization;
|
|
using ProcedualWorlds.HierachySystem;
|
|
using static Gaia.GaiaConstants;
|
|
using UnityEngine.SceneManagement;
|
|
using System.Linq;
|
|
#if AQUAS_2020_PRESENT
|
|
using AQUAS;
|
|
#endif
|
|
using UnityEngine.Rendering;
|
|
#if UNITY_POST_PROCESSING_STACK_V2
|
|
using UnityEngine.Rendering.PostProcessing;
|
|
#endif
|
|
#if UPPipeline
|
|
using UnityEngine.Rendering.Universal;
|
|
#endif
|
|
#if HDPipeline
|
|
using UnityEngine.Rendering.HighDefinition;
|
|
#endif
|
|
#if UNITY_POST_PROCESSING_STACK_V1 && AQUAS_PRESENT
|
|
using UnityEngine.PostProcessing;
|
|
#endif
|
|
|
|
namespace Gaia
|
|
{
|
|
public static class GaiaPrefabUtility
|
|
{
|
|
public static readonly string m_vfxLayerName = "PW_VFX";
|
|
public static readonly int m_vfxLayerIndex = 8;
|
|
|
|
public static readonly string m_objectSmallLayerName = "PW_Object_Small";
|
|
public static readonly int m_objectSmallLayerIndex = 9;
|
|
|
|
public static readonly string m_objectMediumLayerName = "PW_Object_Medium";
|
|
public static readonly int m_objectMediumLayerIndex = 10;
|
|
|
|
public static readonly string m_objectLargeLayerName = "PW_Object_Large";
|
|
public static readonly int m_objectLargeLayerIndex = 11;
|
|
|
|
public static readonly string m_objectDefaultLayerName = "Default";
|
|
}
|
|
|
|
public class GaiaUtils : MonoBehaviour
|
|
{
|
|
#region Asset directory helpers
|
|
/// <summary>
|
|
/// Get raw gaia asset directory
|
|
/// </summary>
|
|
/// <returns>Base gaia directory</returns>
|
|
//public static string GetGaiaAssetDirectory()
|
|
//{
|
|
// string path = Path.Combine(Application.dataPath, Gaia.GaiaConstants.AssetDir);
|
|
// return path.Replace('\\', '/');
|
|
//}
|
|
|
|
/// <summary>
|
|
/// Get the asset directory for a particular featiure type
|
|
/// </summary>
|
|
/// <param name="featureType"></param>
|
|
/// <returns>Path of feature type</returns>
|
|
//public static string GetGaiaAssetDirectory(Gaia.GaiaConstants.FeatureType featureType)
|
|
//{
|
|
// string path = Path.Combine(Application.dataPath, Gaia.GaiaConstants.AssetDir);
|
|
// path = Path.Combine(path, featureType.ToString());
|
|
// return path.Replace('\\', '/');
|
|
//}
|
|
|
|
/// <summary>
|
|
/// Get a list of the Gaia stamps for the feature type provided
|
|
/// </summary>
|
|
/// <param name="featureType"></param>
|
|
/// <returns></returns>
|
|
public static List<string> GetGaiaStampsList(Gaia.GaiaConstants.FeatureType featureType)
|
|
{
|
|
return new List<string>(System.IO.Directory.GetFiles(GaiaDirectories.GetStampFeatureDirectory(featureType), "*.exr"));
|
|
}
|
|
|
|
|
|
|
|
/// <summary>
|
|
/// Get the full asset path for a specific asset type and name
|
|
/// </summary>
|
|
/// <param name="featureType">The type of feature this asset is</param>
|
|
/// <param name="assetName">The file name of the asset</param>
|
|
/// <returns>Fully qualified path of the asset</returns>
|
|
//public static string GetGaiaAssetPath(Gaia.GaiaConstants.FeatureType featureType, string assetName)
|
|
//{
|
|
// string path = GetGaiaAssetDirectory(featureType);
|
|
// path = Path.Combine(GetGaiaAssetDirectory(featureType), assetName);
|
|
// return path.Replace('\\','/');
|
|
//}
|
|
|
|
/// <summary>
|
|
/// Get the full asset path for a specific asset type and name
|
|
/// </summary>
|
|
/// <param name="featureType">The type of feature this asset is</param>
|
|
/// <param name="assetName">The file name of the asset</param>
|
|
/// <returns>Fully qualified path of the asset</returns>
|
|
//public static string GetGaiaStampAssetPath(Gaia.GaiaConstants.FeatureType featureType, string assetName)
|
|
//{
|
|
// string path = GetGaiaAssetDirectory(featureType);
|
|
// path = Path.Combine(GetGaiaAssetDirectory(featureType), "Data");
|
|
// path = Path.Combine(path, assetName);
|
|
// return path.Replace('\\', '/');
|
|
//}
|
|
|
|
|
|
/// <summary>
|
|
/// Parse a stamp preview texture to work out where the stamp lives
|
|
/// </summary>
|
|
/// <param name="source">Source texture</param>
|
|
/// <returns></returns>
|
|
public static string GetGaiaStampPath(Texture2D source)
|
|
{
|
|
string path = "";
|
|
#if UNITY_EDITOR
|
|
path = UnityEditor.AssetDatabase.GetAssetPath(source);
|
|
#endif
|
|
|
|
string fileName = Path.GetFileName(path);
|
|
path = Path.Combine(Path.GetDirectoryName(path), "Data");
|
|
path = Path.Combine(path, fileName);
|
|
path = Path.ChangeExtension(path, ".bytes");
|
|
path = path.Replace('\\', '/');
|
|
return path;
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
/// Helper to load in all terrains managed by placeholders, call a function on them, and then unload them again. Helpful to process changes across the entire game world.
|
|
/// </summary>
|
|
/// <param name="terrainAction">A function that accepts a terrain as 1st parameter</param>
|
|
/// <param name="dirtyScenes">Should scenes be marked as 'dirty' so they will be saved during the process?</param>
|
|
public static void CallFunctionOnDynamicLoadedTerrains(Action<Terrain> terrainAction, bool dirtyScenes, List<string> terrainNames = null, string progressBarText = "")
|
|
{
|
|
#if UNITY_EDITOR
|
|
if (string.IsNullOrEmpty(progressBarText))
|
|
{
|
|
progressBarText = "Processing Terrain... ";
|
|
}
|
|
|
|
GaiaSessionManager gsm = GaiaSessionManager.GetSessionManager();
|
|
|
|
TerrainScene[] allTerrainScenes;
|
|
if (terrainNames == null)
|
|
{
|
|
//no list of names given - go over all terrains
|
|
allTerrainScenes = TerrainLoaderManager.TerrainScenes.ToArray();
|
|
}
|
|
else
|
|
{
|
|
//filter by list of terrain names
|
|
allTerrainScenes = TerrainLoaderManager.TerrainScenes.Where(x => terrainNames.Contains(x.GetTerrainName())).ToArray();
|
|
}
|
|
|
|
|
|
if (TerrainLoaderManager.TerrainScenes.Count > 0)
|
|
{
|
|
try
|
|
{
|
|
int count = 1;
|
|
foreach (TerrainScene terrainScene in allTerrainScenes)
|
|
{
|
|
if (ProgressBar.Show(ProgressBarPriority.MultiTerrainAction, "Processing Terrains", progressBarText, count, TerrainLoaderManager.TerrainScenes.Count, true, true))
|
|
{
|
|
break;
|
|
}
|
|
if (terrainScene.m_loadState != LoadState.Loaded)
|
|
{
|
|
terrainScene.AddReference(gsm.gameObject);
|
|
}
|
|
Scene scene = EditorSceneManager.GetSceneByPath(terrainScene.m_scenePath);
|
|
foreach (GameObject go in scene.GetRootGameObjects())
|
|
{
|
|
Terrain terrain = go.GetComponent<Terrain>();
|
|
if (terrain != null)
|
|
{
|
|
terrainAction(terrain);
|
|
}
|
|
}
|
|
if (dirtyScenes)
|
|
{
|
|
EditorSceneManager.MarkSceneDirty(scene);
|
|
}
|
|
terrainScene.RemoveAllReferences();
|
|
count++;
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
Debug.LogError("Error while processing multiple dynamic loaded Terrains, Exception: " + ex.Message + " Stack Trace: " + ex.StackTrace);
|
|
}
|
|
finally
|
|
{
|
|
ProgressBar.Clear(ProgressBarPriority.MultiTerrainAction);
|
|
}
|
|
}
|
|
TerrainLoaderManager.Instance.UpdateTerrainLoadState();
|
|
#endif
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
/// Finds a gameobject by name even when it is deactivated.
|
|
/// </summary>
|
|
/// <param name="searchFor">The name of the GO to look for</param>
|
|
/// <param name="fullNameMatch">Whether the name needs to be a full match or if it is sufficient if the name of the GO just contains "searchFor".</param>
|
|
/// <returns></returns>
|
|
public static GameObject FindObjectDeactivated(string searchFor, bool fullNameMatch = true)
|
|
{
|
|
GameObject[] allGOs = Resources.FindObjectsOfTypeAll<GameObject>();
|
|
foreach (GameObject go in allGOs)
|
|
{
|
|
if (go.name == searchFor || (!fullNameMatch && go.name.Contains(searchFor)))
|
|
{
|
|
return go;
|
|
}
|
|
}
|
|
return null;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Check to see if this actually a valid stamp - needs a .jpg and a .bytes file
|
|
/// </summary>
|
|
/// <param name="source">Source texture</param>
|
|
/// <returns></returns>
|
|
public static bool CheckValidGaiaStampPath(Texture2D source)
|
|
{
|
|
string path = "";
|
|
#if UNITY_EDITOR
|
|
path = UnityEditor.AssetDatabase.GetAssetPath(source);
|
|
#endif
|
|
|
|
//path = GetGaiaAssetDirectory() + path.Replace(Gaia.GaiaConstants.AssetDirFromAssetDB, "");
|
|
|
|
// Check to see if we have a jpg file
|
|
if (Path.GetExtension(path).ToLower() != ".jpg")
|
|
{
|
|
return false;
|
|
}
|
|
|
|
//Check to see if we have asset file
|
|
string fileName = Path.GetFileName(path);
|
|
path = Path.Combine(Path.GetDirectoryName(path), "Data");
|
|
path = Path.Combine(path, fileName);
|
|
path = Path.ChangeExtension(path, ".bytes");
|
|
path = path.Replace('\\', '/');
|
|
|
|
if (System.IO.File.Exists(path))
|
|
{
|
|
return true;
|
|
}
|
|
else
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
|
|
// /// <summary>
|
|
// /// allows non-editor classes to display a progress bar which will not create a conflict on build
|
|
// /// </summary>
|
|
// /// <param name="title"></param>
|
|
// /// <param name="text"></param>
|
|
// /// <param name="progress"></param>
|
|
// public static void DisplayProgressBarNoEditor(string title, string text, float progress)
|
|
// {
|
|
//#if UNITY_EDITOR
|
|
// EditorUtility.DisplayProgressBar(title, text, progress);
|
|
//#endif
|
|
// }
|
|
|
|
public static float GetTreeRadius(GameObject treePrefab)
|
|
{
|
|
//TreePrototype protoType = terrain.terrainData.treePrototypes[m_treePrototypeId];
|
|
//if (protoType != null)
|
|
//{
|
|
// GameObject treeGO = protoType.prefab;
|
|
if (treePrefab != null)
|
|
{
|
|
Bounds bounds = GetBounds(treePrefab);
|
|
return (float)Math.Round(Mathf.Max(bounds.extents.x, bounds.extents.z), 2);
|
|
}
|
|
return 5;
|
|
//}
|
|
//else
|
|
//{
|
|
// return 5;
|
|
//}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Create all the Gaia stamp directories for scans to go into
|
|
/// </summary>
|
|
public static void CreateGaiaStampDirectories()
|
|
{
|
|
#if UNITY_EDITOR
|
|
string path = GaiaDirectories.GetStampDirectory();
|
|
try
|
|
{
|
|
bool addedDir = false;
|
|
foreach (Gaia.GaiaConstants.FeatureType feature in Enum.GetValues(typeof(Gaia.GaiaConstants.FeatureType)))
|
|
{
|
|
path = GaiaDirectories.GetStampFeatureDirectory(feature);
|
|
if (!Directory.Exists(path))
|
|
{
|
|
Directory.CreateDirectory(path);
|
|
path = Path.Combine(path, "Data");
|
|
Directory.CreateDirectory(path);
|
|
addedDir = true;
|
|
}
|
|
}
|
|
|
|
if (addedDir)
|
|
{
|
|
AssetDatabase.Refresh();
|
|
}
|
|
}
|
|
catch (Exception e)
|
|
{
|
|
Debug.LogError(string.Format("Failed to create directory {0} : {1}", path, e.Message));
|
|
}
|
|
#endif
|
|
}
|
|
|
|
public static float GetBoundsForTaggedObject(string tag)
|
|
{
|
|
try
|
|
{
|
|
var allGOsWithTag = GameObject.FindGameObjectsWithTag(tag);
|
|
Bounds bounds = GetBounds(allGOsWithTag[0]);
|
|
return (float)Math.Round(Mathf.Max(bounds.extents.x, bounds.extents.z), 2);
|
|
}
|
|
catch { }
|
|
|
|
return 5f;
|
|
}
|
|
|
|
// /// <summary>
|
|
// /// Clears a progress bar from a class outside the editor namespace
|
|
// /// </summary>
|
|
// public static void ClearProgressBarNoEditor()
|
|
// {
|
|
//#if UNITY_EDITOR
|
|
// EditorUtility.ClearProgressBar();
|
|
//#endif
|
|
// }
|
|
|
|
/// <summary>
|
|
/// Get all objects of the given type at the location in the path. Only works in the editor.
|
|
/// </summary>
|
|
/// <typeparam name="T">Type of object to load</typeparam>
|
|
/// <param name="path">The path to look in</param>
|
|
/// <returns>List of those objects</returns>
|
|
public static T[] GetAtPath<T>(string path)
|
|
{
|
|
|
|
ArrayList al = new ArrayList();
|
|
|
|
#if UNITY_EDITOR
|
|
|
|
string[] fileEntries = Directory.GetFiles(Application.dataPath + "/" + path);
|
|
foreach (string fileName in fileEntries)
|
|
{
|
|
int index = fileName.LastIndexOf("/");
|
|
string localPath = "Assets/" + path;
|
|
|
|
if (index > 0)
|
|
localPath += fileName.Substring(index);
|
|
|
|
UnityEngine.Object t = UnityEditor.AssetDatabase.LoadAssetAtPath(localPath, typeof(T));
|
|
|
|
if (t != null)
|
|
al.Add(t);
|
|
}
|
|
|
|
#endif
|
|
|
|
T[] result = new T[al.Count];
|
|
for (int i = 0; i < al.Count; i++)
|
|
result[i] = (T)al[i];
|
|
|
|
return result;
|
|
}
|
|
|
|
|
|
|
|
#endregion
|
|
|
|
#region Asset, Scriptable Object, GameObject helpers
|
|
|
|
/// <summary>
|
|
/// Color inverter for seasonal color setup
|
|
/// </summary>
|
|
/// <param name="i_color"></param>
|
|
/// <returns></returns>
|
|
public static Color ColorInvert(Color color)
|
|
{
|
|
Color result;
|
|
|
|
result.r = 1.0f - color.r;
|
|
result.g = 1.0f - color.g;
|
|
result.b = 1.0f - color.b;
|
|
result.a = 1.0f - color.a;
|
|
|
|
return (result);
|
|
}
|
|
/// <summary>
|
|
/// Validates that the shader property exists on the material
|
|
/// </summary>
|
|
/// <param name="material"></param>
|
|
/// <param name="shaderID"></param>
|
|
/// <returns></returns>
|
|
public static bool ValidateShaderProperty(Material material, int shaderID)
|
|
{
|
|
if (material == null)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
if (material.HasProperty(shaderID))
|
|
{
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
/// <summary>
|
|
/// Validates that the shader property exists on the material
|
|
/// </summary>
|
|
/// <param name="material"></param>
|
|
/// <param name="shaderID"></param>
|
|
/// <returns></returns>
|
|
public static bool ValidateShaderProperty(Material material, string shaderID)
|
|
{
|
|
if (material == null)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
if (material.HasProperty(shaderID))
|
|
{
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
/// <summary>
|
|
/// Finalizes the scene, removes stamper and spawners from the scene and creates a finalized version
|
|
/// </summary>
|
|
public static void FinalizeScene()
|
|
{
|
|
//TODO
|
|
#if UNITY_EDITOR
|
|
EditorSceneManager.SaveOpenScenes();
|
|
EditorUtility.DisplayProgressBar("Finalizing Scene", "Cleaning Gaia Stamping/Spawning from the Scene", 0.25f);
|
|
GameObject gaiaObjects = GameObject.Find("Gaia");
|
|
if (gaiaObjects != null)
|
|
{
|
|
GameObject.DestroyImmediate(gaiaObjects);
|
|
}
|
|
|
|
//scene info
|
|
Scene scene = EditorSceneManager.GetActiveScene();
|
|
string sceneName = scene.name;
|
|
string scenePath = scene.path;
|
|
if (sceneName.Contains("Finalized"))
|
|
{
|
|
Debug.LogWarning("The scene name contains the string 'Finalized'. It would seem that this scene has already been finalized by Gaia. Exiting the process");
|
|
EditorUtility.ClearProgressBar();
|
|
return;
|
|
}
|
|
|
|
//Create folder
|
|
string folder = "Assets/Gaia User Data/" + sceneName + " Finalized";
|
|
folder = GaiaDirectories.CreatePathIfDoesNotExist(folder);
|
|
AssetDatabase.SaveAssets();
|
|
AssetDatabase.Refresh();
|
|
Debug.Log(folder);
|
|
|
|
//Update path info
|
|
scenePath = scenePath.Substring(0, scenePath.Length - 6);
|
|
scenePath += " Finalized.unity";
|
|
|
|
//Terrain data info
|
|
Terrain[] terrains = Terrain.activeTerrains;
|
|
List<TerrainData> terrainDatas = terrains.Select(t => t.GetComponent<TerrainCollider>().terrainData).ToList();
|
|
|
|
for (int i = 0; i < terrainDatas.Count; i++)
|
|
{
|
|
EditorUtility.DisplayProgressBar("Finalizing Scene", "Moving terrain data: " + i + "/" + terrainDatas.Count, (float)i / (float)terrainDatas.Count);
|
|
Debug.Log(AssetDatabase.ValidateMoveAsset(GetAssetPath(terrainDatas[i].name + ".asset"), folder));
|
|
if (string.IsNullOrEmpty(AssetDatabase.ValidateMoveAsset(GetAssetPath(terrainDatas[i].name + ".asset"), folder)))
|
|
{
|
|
Debug.Log("moving terrain data");
|
|
AssetDatabase.MoveAsset(GetAssetPath(terrainDatas[i].name + ".asset"), folder);
|
|
}
|
|
}
|
|
AssetDatabase.SaveAssets();
|
|
AssetDatabase.Refresh();
|
|
|
|
EditorUtility.DisplayProgressBar("Finalizing Scene", "Saving finalized scene version.", 0.5f);
|
|
EditorSceneManager.SaveScene(scene, scenePath, true);
|
|
AssetDatabase.Refresh();
|
|
|
|
//Move new scene
|
|
if (string.IsNullOrEmpty(AssetDatabase.ValidateMoveAsset(scenePath, folder)))
|
|
{
|
|
Debug.Log("moving scene");
|
|
AssetDatabase.MoveAsset(scenePath, folder);
|
|
}
|
|
|
|
AssetDatabase.Refresh();
|
|
AssetDatabase.SaveAssets();
|
|
|
|
EditorUtility.DisplayProgressBar("Finalizing Scene", "Opening finalized scene version.", 0.9f);
|
|
EditorSceneManager.OpenScene(scenePath);
|
|
EditorUtility.ClearProgressBar();
|
|
|
|
Debug.Log("Finished finalizing: " + sceneName + " Contents is located at: " + folder);
|
|
#endif
|
|
}
|
|
|
|
/// <summary>
|
|
/// Selects and pings the weather object
|
|
/// </summary>
|
|
public static void FocusWeatherObject()
|
|
{
|
|
#if UNITY_EDITOR
|
|
GameObject weatherObject = GameObject.Find(GaiaConstants.weatherObject);
|
|
if (weatherObject != null)
|
|
{
|
|
Selection.activeObject = weatherObject;
|
|
EditorGUIUtility.PingObject(weatherObject);
|
|
}
|
|
#endif
|
|
}
|
|
/// <summary>
|
|
/// Checks to see if the index range of the active lighting profile isn't out of the index bounds of th elighting profiles
|
|
/// </summary>
|
|
/// <returns></returns>
|
|
public static bool CheckLightingProfileIndexRange()
|
|
{
|
|
if (CheckIfSceneProfileExists())
|
|
{
|
|
if (GaiaGlobal.Instance.SceneProfile.m_selectedLightingProfileValuesIndex <= GaiaGlobal.Instance.SceneProfile.m_lightingProfiles.Count - 1)
|
|
{
|
|
return true;
|
|
}
|
|
else
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Gets and returns the particle renderer material
|
|
/// </summary>
|
|
/// <param name="checkSelf"></param>
|
|
/// <param name="objectName"></param>
|
|
/// <returns></returns>
|
|
public static Material GetParticleMaterial(GameObject selfObject)
|
|
{
|
|
Material material = null;
|
|
if (selfObject != null)
|
|
{
|
|
ParticleSystemRenderer systemRenderer = selfObject.GetComponent<ParticleSystemRenderer>();
|
|
if (systemRenderer != null)
|
|
{
|
|
material = systemRenderer.sharedMaterial;
|
|
}
|
|
}
|
|
|
|
return material;
|
|
}
|
|
|
|
public static UserFiles GetOrCreateUserFiles()
|
|
{
|
|
#if UNITY_EDITOR
|
|
UserFiles returnedObject = GetAsset("UserFiles.asset", typeof(Gaia.UserFiles)) as Gaia.UserFiles;
|
|
if (returnedObject == null)
|
|
{
|
|
returnedObject = ScriptableObject.CreateInstance<UserFiles>();
|
|
string path = GaiaDirectories.GetUserSettingsDirectory() + "/UserFiles.asset";
|
|
AssetDatabase.CreateAsset(returnedObject, path);
|
|
AssetDatabase.ImportAsset(path);
|
|
returnedObject = (UserFiles)AssetDatabase.LoadAssetAtPath(path, typeof(UserFiles));
|
|
//Reset back to initial state
|
|
ResetBiomePresets(true);
|
|
}
|
|
|
|
//Purge empty entries
|
|
bool changesMade = false;
|
|
for (int i = returnedObject.m_gaiaManagerBiomePresets.Count()-1; i >= 0; i--)
|
|
{
|
|
if (returnedObject.m_gaiaManagerBiomePresets[i] == null)
|
|
{
|
|
returnedObject.m_gaiaManagerBiomePresets.RemoveAt(i);
|
|
changesMade = true;
|
|
}
|
|
}
|
|
|
|
for (int i = returnedObject.m_gaiaManagerSpawnerSettings.Count()-1; i >= 0; i--)
|
|
{
|
|
if (returnedObject.m_gaiaManagerSpawnerSettings[i] == null)
|
|
{
|
|
returnedObject.m_gaiaManagerSpawnerSettings.RemoveAt(i);
|
|
changesMade = true;
|
|
}
|
|
}
|
|
if (changesMade)
|
|
{
|
|
EditorUtility.SetDirty(returnedObject);
|
|
AssetDatabase.SaveAssets();
|
|
}
|
|
return returnedObject;
|
|
#else
|
|
return null;
|
|
#endif
|
|
|
|
}
|
|
|
|
/// <summary>
|
|
/// Updates the reflection probe generation settigns
|
|
/// </summary>
|
|
/// <param name="sceneProfile"></param>
|
|
public static void UpdateProbeDataDefaults(SceneProfile sceneProfile)
|
|
{
|
|
if (sceneProfile == null || sceneProfile.m_selectedLightingProfileValuesIndex == -99)
|
|
{
|
|
return;
|
|
}
|
|
|
|
GaiaLightingProfileValues m_profileValues = sceneProfile.m_lightingProfiles[sceneProfile.m_selectedLightingProfileValuesIndex];
|
|
if (m_profileValues != null)
|
|
{
|
|
switch (m_profileValues.m_profileType)
|
|
{
|
|
case GaiaConstants.GaiaLightingProfileType.ProceduralWorldsSky:
|
|
sceneProfile.m_reflectionProbeData.reflectionProbeMode = ReflectionProbeMode.Realtime;
|
|
sceneProfile.m_reflectionProbeData.reflectionProbeRefresh = GaiaConstants.ReflectionProbeRefreshModePW.ProbeManager;
|
|
sceneProfile.m_reflectionProbeData.reflectionProbeTimeSlicingMode = ReflectionProbeTimeSlicingMode.IndividualFaces;
|
|
sceneProfile.m_reflectionProbeData.reflectionProbeResolution = GaiaConstants.ReflectionProbeResolution.Resolution64;
|
|
#if GAIA_PRO_PRESENT
|
|
ReflectionProbeManager.GetOrCreateProbeManager();
|
|
#endif
|
|
break;
|
|
case GaiaConstants.GaiaLightingProfileType.Procedural:
|
|
sceneProfile.m_reflectionProbeData.reflectionProbeMode = ReflectionProbeMode.Baked;
|
|
sceneProfile.m_reflectionProbeData.reflectionProbeRefresh = GaiaConstants.ReflectionProbeRefreshModePW.OnAwake;
|
|
sceneProfile.m_reflectionProbeData.reflectionProbeTimeSlicingMode = ReflectionProbeTimeSlicingMode.IndividualFaces;
|
|
sceneProfile.m_reflectionProbeData.reflectionProbeResolution = GaiaConstants.ReflectionProbeResolution.Resolution64;
|
|
#if GAIA_PRO_PRESENT
|
|
ReflectionProbeManager.RemoveReflectionProbeManager();
|
|
#endif
|
|
break;
|
|
case GaiaConstants.GaiaLightingProfileType.HDRI:
|
|
sceneProfile.m_reflectionProbeData.reflectionProbeMode = ReflectionProbeMode.Baked;
|
|
sceneProfile.m_reflectionProbeData.reflectionProbeRefresh = GaiaConstants.ReflectionProbeRefreshModePW.OnAwake;
|
|
sceneProfile.m_reflectionProbeData.reflectionProbeTimeSlicingMode = ReflectionProbeTimeSlicingMode.IndividualFaces;
|
|
sceneProfile.m_reflectionProbeData.reflectionProbeResolution = GaiaConstants.ReflectionProbeResolution.Resolution64;
|
|
#if GAIA_PRO_PRESENT
|
|
ReflectionProbeManager.RemoveReflectionProbeManager();
|
|
#endif
|
|
break;
|
|
}
|
|
|
|
UpdateAllSceneProbes(sceneProfile.m_reflectionProbeData);
|
|
}
|
|
}
|
|
|
|
private static void UpdateAllSceneProbes(ReflectionProbeData data)
|
|
{
|
|
if (data == null)
|
|
{
|
|
return;
|
|
}
|
|
|
|
ReflectionProbe[] probes = GameObject.FindObjectsOfType<ReflectionProbe>();
|
|
if (probes.Length > 0)
|
|
{
|
|
foreach (var probe in probes)
|
|
{
|
|
probe.mode = data.reflectionProbeMode;
|
|
probe.timeSlicingMode = data.reflectionProbeTimeSlicingMode;
|
|
switch (data.reflectionProbeRefresh)
|
|
{
|
|
case ReflectionProbeRefreshModePW.OnAwake:
|
|
probe.refreshMode = ReflectionProbeRefreshMode.OnAwake;
|
|
break;
|
|
case ReflectionProbeRefreshModePW.EveryFrame:
|
|
probe.refreshMode = ReflectionProbeRefreshMode.EveryFrame;
|
|
break;
|
|
case ReflectionProbeRefreshModePW.ViaScripting:
|
|
probe.refreshMode = ReflectionProbeRefreshMode.ViaScripting;
|
|
break;
|
|
case ReflectionProbeRefreshModePW.ProbeManager:
|
|
probe.refreshMode = ReflectionProbeRefreshMode.ViaScripting;
|
|
break;
|
|
}
|
|
switch (data.reflectionProbeResolution)
|
|
{
|
|
case ReflectionProbeResolution.Resolution16:
|
|
probe.resolution = 16;
|
|
break;
|
|
case ReflectionProbeResolution.Resolution32:
|
|
probe.resolution = 32;
|
|
break;
|
|
case ReflectionProbeResolution.Resolution64:
|
|
probe.resolution = 64;
|
|
break;
|
|
case ReflectionProbeResolution.Resolution128:
|
|
probe.resolution = 128;
|
|
break;
|
|
case ReflectionProbeResolution.Resolution256:
|
|
probe.resolution = 256;
|
|
break;
|
|
case ReflectionProbeResolution.Resolution512:
|
|
probe.resolution = 512;
|
|
break;
|
|
case ReflectionProbeResolution.Resolution1024:
|
|
probe.resolution = 1024;
|
|
break;
|
|
case ReflectionProbeResolution.Resolution2048:
|
|
probe.resolution = 2048;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Gets and returns the particle renderer material
|
|
/// </summary>
|
|
/// <param name="checkSelf"></param>
|
|
/// <param name="objectName"></param>
|
|
/// <returns></returns>
|
|
public static Material GetParticleMaterial(string objectName)
|
|
{
|
|
Material material = null;
|
|
if (objectName.Length > 0)
|
|
{
|
|
GameObject particleObject = GameObject.Find(objectName);
|
|
if (particleObject != null)
|
|
{
|
|
ParticleSystemRenderer systemRenderer = particleObject.GetComponent<ParticleSystemRenderer>();
|
|
if (systemRenderer != null)
|
|
{
|
|
material = systemRenderer.sharedMaterial;
|
|
}
|
|
}
|
|
}
|
|
|
|
return material;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Gets the cloud materials from the scene
|
|
/// </summary>
|
|
/// <param name="objectName"></param>
|
|
/// <returns></returns>
|
|
public static List<Material> GetCloudLayerMaterials(string objectName, string ignoreContainName)
|
|
{
|
|
List<Material> materials = new List<Material>();
|
|
if (objectName.Length > 0)
|
|
{
|
|
GameObject cloudObject = GameObject.Find(objectName);
|
|
if (cloudObject != null)
|
|
{
|
|
MeshRenderer[] meshRenderers = cloudObject.GetComponentsInChildren<MeshRenderer>();
|
|
if (meshRenderers.Length > 0)
|
|
{
|
|
foreach (MeshRenderer renderer in meshRenderers)
|
|
{
|
|
if (ignoreContainName.Length > 0)
|
|
{
|
|
if (!renderer.sharedMaterial.name.Contains(ignoreContainName))
|
|
{
|
|
materials.Add(renderer.sharedMaterial);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
materials.Add(renderer.sharedMaterial);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return materials;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Gets the current installed SRP
|
|
/// </summary>
|
|
/// <returns></returns>
|
|
public static GaiaConstants.EnvironmentRenderer GetActivePipeline()
|
|
{
|
|
GaiaConstants.EnvironmentRenderer renderer = GaiaConstants.EnvironmentRenderer.BuiltIn;
|
|
//Sets up the render to the correct pipeline
|
|
if (GraphicsSettings.defaultRenderPipeline == null)
|
|
{
|
|
renderer = GaiaConstants.EnvironmentRenderer.BuiltIn;
|
|
}
|
|
else if (GraphicsSettings.defaultRenderPipeline.GetType().ToString().Contains("HDRenderPipelineAsset"))
|
|
{
|
|
renderer = GaiaConstants.EnvironmentRenderer.HighDefinition;
|
|
}
|
|
else if (GraphicsSettings.defaultRenderPipeline.GetType().ToString().Contains("UniversalRenderPipelineAsset"))
|
|
{
|
|
renderer = GaiaConstants.EnvironmentRenderer.Universal;
|
|
}
|
|
else
|
|
{
|
|
renderer = GaiaConstants.EnvironmentRenderer.Lightweight;
|
|
}
|
|
|
|
return renderer;
|
|
}
|
|
|
|
public static void SetDefaultStampImportSettings(string textureFileName)
|
|
{
|
|
#if UNITY_EDITOR
|
|
var importer = AssetImporter.GetAtPath(textureFileName) as TextureImporter;
|
|
if (importer != null)
|
|
{
|
|
importer.alphaSource = TextureImporterAlphaSource.None;
|
|
importer.alphaIsTransparency = false;
|
|
importer.sRGBTexture = false;
|
|
importer.maxTextureSize = 8192;
|
|
importer.wrapMode = TextureWrapMode.Clamp;
|
|
importer.mipmapEnabled = false;
|
|
TextureImporterPlatformSettings texImpPlatSet = new TextureImporterPlatformSettings();
|
|
texImpPlatSet.maxTextureSize = 8192;
|
|
texImpPlatSet.format = TextureImporterFormat.Automatic;
|
|
texImpPlatSet.textureCompression = TextureImporterCompression.Uncompressed;
|
|
importer.SetPlatformTextureSettings(texImpPlatSet);
|
|
AssetDatabase.ImportAsset(textureFileName);
|
|
}
|
|
#endif
|
|
}
|
|
|
|
/// <summary>
|
|
/// Gets the global volume profile
|
|
/// </summary>
|
|
/// <returns></returns>
|
|
#if HDPipeline || UPPipeline
|
|
public static VolumeProfile GetVolumeProfile(bool isPlaying, string deepSearchName, string doesNotContain)
|
|
{
|
|
VolumeProfile volumeProfile = null;
|
|
Volume[] volumes = FindObjectsOfType<Volume>();
|
|
if (Application.isPlaying)
|
|
{
|
|
isPlaying = true;
|
|
}
|
|
else
|
|
{
|
|
isPlaying = false;
|
|
}
|
|
|
|
if (volumes.Length > 0)
|
|
{
|
|
foreach (Volume volume in volumes)
|
|
{
|
|
if (volume.isGlobal)
|
|
{
|
|
if (volume.name.Contains(deepSearchName) && !volume.name.Contains(doesNotContain))
|
|
{
|
|
volumeProfile = volume.sharedProfile;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return volumeProfile;
|
|
}
|
|
|
|
#if UNITY_POST_PROCESSING_STACK_V2 && UNITY_EDITOR
|
|
public static void CreateURPOrHDRPPostProcessing(GaiaConstants.EnvironmentRenderer renderPipeline, PostProcessProfile profile, string saveLocation)
|
|
{
|
|
if (profile == null)
|
|
{
|
|
Debug.LogError("No Post Process Profile to copy from has been assigned, please assign a profile you wish to copy from");
|
|
return;
|
|
}
|
|
|
|
string extentionName = "";
|
|
|
|
//V2
|
|
#if HDPipeline
|
|
UnityEngine.Rendering.PostProcessing.AmbientOcclusion ambientOcclusion;
|
|
#endif
|
|
UnityEngine.Rendering.PostProcessing.Bloom bloom;
|
|
UnityEngine.Rendering.PostProcessing.ChromaticAberration chromaticAberration;
|
|
UnityEngine.Rendering.PostProcessing.ColorGrading colorGrading;
|
|
UnityEngine.Rendering.PostProcessing.DepthOfField depthOfField;
|
|
UnityEngine.Rendering.PostProcessing.Grain grain;
|
|
UnityEngine.Rendering.PostProcessing.LensDistortion lensDistortion;
|
|
UnityEngine.Rendering.PostProcessing.MotionBlur motionBlur;
|
|
UnityEngine.Rendering.PostProcessing.Vignette vignette;
|
|
//URP
|
|
#if UPPipeline
|
|
UnityEngine.Rendering.Universal.Bloom URPBloom;
|
|
UnityEngine.Rendering.Universal.ChromaticAberration URPChromaticAberration;
|
|
UnityEngine.Rendering.Universal.ColorAdjustments URPColorAdjustments;
|
|
UnityEngine.Rendering.Universal.WhiteBalance URPWhiteBalance;
|
|
UnityEngine.Rendering.Universal.ChannelMixer URPChannelMixer;
|
|
UnityEngine.Rendering.Universal.Tonemapping URPTonemapping;
|
|
UnityEngine.Rendering.Universal.DepthOfField URPDepthOfField;
|
|
UnityEngine.Rendering.Universal.FilmGrain URPFilmGrain;
|
|
UnityEngine.Rendering.Universal.LensDistortion URPLensDistortion;
|
|
UnityEngine.Rendering.Universal.MotionBlur URPMotionBlur;
|
|
UnityEngine.Rendering.Universal.Vignette URPVignette;
|
|
UnityEngine.Rendering.Universal.SplitToning URPSplitToning;
|
|
#endif
|
|
//HDRP
|
|
#if HDPipeline
|
|
UnityEngine.Rendering.HighDefinition.AmbientOcclusion HDRPAmbientOcclusion;
|
|
UnityEngine.Rendering.HighDefinition.Bloom HDRPBloom;
|
|
UnityEngine.Rendering.HighDefinition.ChromaticAberration HDRPChromaticAberration;
|
|
UnityEngine.Rendering.HighDefinition.ColorAdjustments HDRPColorAdjustments;
|
|
UnityEngine.Rendering.HighDefinition.WhiteBalance HDRPWhiteBalance;
|
|
UnityEngine.Rendering.HighDefinition.ChannelMixer HDRPChannelMixer;
|
|
UnityEngine.Rendering.HighDefinition.Tonemapping HDRPTonemapping;
|
|
UnityEngine.Rendering.HighDefinition.DepthOfField HDRPDepthOfField;
|
|
UnityEngine.Rendering.HighDefinition.FilmGrain HDRPFilmGrain;
|
|
UnityEngine.Rendering.HighDefinition.LensDistortion HDRPLensDistortion;
|
|
UnityEngine.Rendering.HighDefinition.MotionBlur HDRPMotionBlur;
|
|
UnityEngine.Rendering.HighDefinition.Vignette HDRPVignette;
|
|
UnityEngine.Rendering.HighDefinition.SplitToning HDRPSplitToning;
|
|
#endif
|
|
|
|
//Configure file
|
|
VolumeProfile volumeProfile = ScriptableObject.CreateInstance<VolumeProfile>();
|
|
|
|
//Save file
|
|
if (saveLocation.Contains(Application.dataPath))
|
|
{
|
|
saveLocation = saveLocation.Replace(Application.dataPath, "Assets/");
|
|
}
|
|
AssetDatabase.CreateAsset(volumeProfile, saveLocation + "/" + extentionName + profile.name + ".asset");
|
|
volumeProfile = AssetDatabase.LoadAssetAtPath<VolumeProfile>(saveLocation + "/" + extentionName + profile.name + ".asset");
|
|
if (renderPipeline == EnvironmentRenderer.Universal)
|
|
{
|
|
//Copy settings
|
|
extentionName = "UP ";
|
|
#if UPPipeline
|
|
//Bloom
|
|
if (profile.TryGetSettings(out bloom))
|
|
{
|
|
if (!volumeProfile.Has<UnityEngine.Rendering.Universal.Bloom>())
|
|
{
|
|
volumeProfile.Add<UnityEngine.Rendering.Universal.Bloom>();
|
|
}
|
|
if (volumeProfile.TryGet(out URPBloom))
|
|
{
|
|
URPBloom.active = true;
|
|
URPBloom.intensity.value = bloom.intensity;
|
|
URPBloom.threshold.value = bloom.threshold;
|
|
URPBloom.tint.value = bloom.color;
|
|
URPBloom.scatter.value = bloom.softKnee;
|
|
URPBloom.highQualityFiltering.value = true;
|
|
URPBloom.dirtTexture.value = bloom.dirtTexture;
|
|
URPBloom.dirtIntensity.value = bloom.dirtIntensity;
|
|
URPBloom.SetAllOverridesTo(true);
|
|
}
|
|
}
|
|
|
|
//Chromatic Aberration
|
|
if (profile.TryGetSettings(out chromaticAberration))
|
|
{
|
|
if (!volumeProfile.Has<UnityEngine.Rendering.Universal.ChromaticAberration>())
|
|
{
|
|
volumeProfile.Add<UnityEngine.Rendering.Universal.ChromaticAberration>();
|
|
}
|
|
if (volumeProfile.TryGet(out URPChromaticAberration))
|
|
{
|
|
URPChromaticAberration.active = true;
|
|
URPChromaticAberration.intensity.value = chromaticAberration.intensity;
|
|
URPChromaticAberration.SetAllOverridesTo(true);
|
|
}
|
|
}
|
|
|
|
//Color Grading
|
|
if (profile.TryGetSettings(out colorGrading))
|
|
{
|
|
if (!volumeProfile.Has<UnityEngine.Rendering.Universal.ColorAdjustments>())
|
|
{
|
|
volumeProfile.Add<UnityEngine.Rendering.Universal.ColorAdjustments>();
|
|
}
|
|
if (volumeProfile.TryGet(out URPColorAdjustments))
|
|
{
|
|
URPColorAdjustments.active = true;
|
|
URPColorAdjustments.postExposure.value = colorGrading.postExposure;
|
|
URPColorAdjustments.contrast.value = colorGrading.contrast;
|
|
URPColorAdjustments.colorFilter.value = colorGrading.colorFilter;
|
|
URPColorAdjustments.hueShift.value = colorGrading.hueShift;
|
|
URPColorAdjustments.saturation.value = colorGrading.saturation;
|
|
URPColorAdjustments.SetAllOverridesTo(true);
|
|
}
|
|
|
|
if (!volumeProfile.Has<UnityEngine.Rendering.Universal.WhiteBalance>())
|
|
{
|
|
volumeProfile.Add<UnityEngine.Rendering.Universal.WhiteBalance>();
|
|
}
|
|
if (volumeProfile.TryGet(out URPWhiteBalance))
|
|
{
|
|
URPWhiteBalance.active = true;
|
|
URPWhiteBalance.temperature.value = colorGrading.temperature;
|
|
URPWhiteBalance.tint.value = colorGrading.tint;
|
|
URPWhiteBalance.SetAllOverridesTo(true);
|
|
}
|
|
|
|
if (!volumeProfile.Has<UnityEngine.Rendering.Universal.ChannelMixer>())
|
|
{
|
|
volumeProfile.Add<UnityEngine.Rendering.Universal.ChannelMixer>();
|
|
}
|
|
if (volumeProfile.TryGet(out URPChannelMixer))
|
|
{
|
|
URPChannelMixer.active = true;
|
|
URPChannelMixer.blueOutBlueIn.value = colorGrading.mixerBlueOutBlueIn;
|
|
URPChannelMixer.blueOutGreenIn.value = colorGrading.mixerBlueOutGreenIn;
|
|
URPChannelMixer.blueOutRedIn.value = colorGrading.mixerBlueOutRedIn;
|
|
|
|
URPChannelMixer.greenOutBlueIn.value = colorGrading.mixerGreenOutBlueIn;
|
|
URPChannelMixer.greenOutGreenIn.value = colorGrading.mixerGreenOutGreenIn;
|
|
URPChannelMixer.greenOutRedIn.value = colorGrading.mixerGreenOutRedIn;
|
|
|
|
URPChannelMixer.redOutBlueIn.value = colorGrading.mixerRedOutBlueIn;
|
|
URPChannelMixer.redOutGreenIn.value = colorGrading.mixerRedOutGreenIn;
|
|
URPChannelMixer.redOutRedIn.value = colorGrading.mixerRedOutRedIn;
|
|
URPChannelMixer.SetAllOverridesTo(true);
|
|
}
|
|
|
|
if (!volumeProfile.Has<UnityEngine.Rendering.Universal.Tonemapping>())
|
|
{
|
|
volumeProfile.Add<UnityEngine.Rendering.Universal.Tonemapping>();
|
|
}
|
|
if (volumeProfile.TryGet(out URPTonemapping))
|
|
{
|
|
URPTonemapping.active = true;
|
|
switch (colorGrading.tonemapper.value)
|
|
{
|
|
case Tonemapper.None:
|
|
URPTonemapping.mode.value = UnityEngine.Rendering.Universal.TonemappingMode.None;
|
|
break;
|
|
case Tonemapper.Neutral:
|
|
URPTonemapping.mode.value = UnityEngine.Rendering.Universal.TonemappingMode.Neutral;
|
|
break;
|
|
case Tonemapper.ACES:
|
|
URPTonemapping.mode.value = UnityEngine.Rendering.Universal.TonemappingMode.ACES;
|
|
break;
|
|
}
|
|
URPTonemapping.SetAllOverridesTo(true);
|
|
}
|
|
}
|
|
|
|
//Depth Of Field
|
|
if (profile.TryGetSettings(out depthOfField))
|
|
{
|
|
if (!volumeProfile.Has<UnityEngine.Rendering.Universal.DepthOfField>())
|
|
{
|
|
volumeProfile.Add<UnityEngine.Rendering.Universal.DepthOfField>();
|
|
}
|
|
if (volumeProfile.TryGet(out URPDepthOfField))
|
|
{
|
|
URPDepthOfField.active = true;
|
|
URPDepthOfField.mode.value = UnityEngine.Rendering.Universal.DepthOfFieldMode.Bokeh;
|
|
URPDepthOfField.aperture.value = depthOfField.aperture;
|
|
URPDepthOfField.focalLength.value = depthOfField.focalLength;
|
|
URPDepthOfField.focusDistance.value = depthOfField.focusDistance;
|
|
URPDepthOfField.SetAllOverridesTo(true);
|
|
}
|
|
}
|
|
|
|
//Film Grain
|
|
if (profile.TryGetSettings(out grain))
|
|
{
|
|
if (!volumeProfile.Has<UnityEngine.Rendering.Universal.FilmGrain>())
|
|
{
|
|
volumeProfile.Add<UnityEngine.Rendering.Universal.FilmGrain>();
|
|
}
|
|
if (volumeProfile.TryGet(out URPFilmGrain))
|
|
{
|
|
URPFilmGrain.active = true;
|
|
URPFilmGrain.intensity.value = grain.intensity;
|
|
URPFilmGrain.SetAllOverridesTo(true);
|
|
}
|
|
}
|
|
|
|
//Lens Distortion
|
|
if (profile.TryGetSettings(out lensDistortion))
|
|
{
|
|
if (!volumeProfile.Has<UnityEngine.Rendering.Universal.LensDistortion>())
|
|
{
|
|
volumeProfile.Add<UnityEngine.Rendering.Universal.LensDistortion>();
|
|
}
|
|
if (volumeProfile.TryGet(out URPLensDistortion))
|
|
{
|
|
URPLensDistortion.active = true;
|
|
Vector2 center = new Vector2(lensDistortion.centerX, lensDistortion.centerY);
|
|
URPLensDistortion.center.value = center;
|
|
URPLensDistortion.intensity.value = lensDistortion.intensity;
|
|
URPLensDistortion.xMultiplier.value = lensDistortion.intensityX;
|
|
URPLensDistortion.yMultiplier.value = lensDistortion.intensityY;
|
|
URPLensDistortion.scale.value = lensDistortion.scale;
|
|
URPLensDistortion.SetAllOverridesTo(true);
|
|
}
|
|
}
|
|
|
|
//Motion Blur
|
|
if (profile.TryGetSettings(out motionBlur))
|
|
{
|
|
if (!volumeProfile.Has<UnityEngine.Rendering.Universal.MotionBlur>())
|
|
{
|
|
volumeProfile.Add<UnityEngine.Rendering.Universal.MotionBlur>();
|
|
}
|
|
if (volumeProfile.TryGet(out URPMotionBlur))
|
|
{
|
|
URPMotionBlur.active = true;
|
|
URPMotionBlur.intensity.value = motionBlur.shutterAngle;
|
|
URPMotionBlur.SetAllOverridesTo(true);
|
|
}
|
|
}
|
|
|
|
//Vignette
|
|
if (profile.TryGetSettings(out vignette))
|
|
{
|
|
if (!volumeProfile.Has<UnityEngine.Rendering.Universal.Vignette>())
|
|
{
|
|
volumeProfile.Add<UnityEngine.Rendering.Universal.Vignette>();
|
|
}
|
|
if (volumeProfile.TryGet(out URPVignette))
|
|
{
|
|
URPVignette.active = true;
|
|
URPVignette.intensity.value = vignette.intensity;
|
|
URPVignette.rounded.value = vignette.rounded;
|
|
URPVignette.smoothness.value = vignette.smoothness;
|
|
URPVignette.SetAllOverridesTo(true);
|
|
}
|
|
}
|
|
|
|
//Split Toning
|
|
if (!volumeProfile.Has<UnityEngine.Rendering.Universal.SplitToning>())
|
|
{
|
|
volumeProfile.Add<UnityEngine.Rendering.Universal.SplitToning>();
|
|
}
|
|
if (volumeProfile.TryGet(out URPSplitToning))
|
|
{
|
|
URPSplitToning.active = true;
|
|
URPSplitToning.shadows.value = GaiaUtils.GetColorFromHTML("636363");
|
|
URPSplitToning.highlights.value = GaiaUtils.GetColorFromHTML("909090");
|
|
URPSplitToning.balance.value = -20f;
|
|
URPSplitToning.SetAllOverridesTo(true);
|
|
}
|
|
|
|
#endif
|
|
}
|
|
else if (renderPipeline == EnvironmentRenderer.HighDefinition)
|
|
{
|
|
extentionName = "HD ";
|
|
#if HDPipeline
|
|
//Copy settings
|
|
//Ambient Occlusion
|
|
if (profile.TryGetSettings(out ambientOcclusion))
|
|
{
|
|
if (!volumeProfile.Has<UnityEngine.Rendering.HighDefinition.AmbientOcclusion>())
|
|
{
|
|
volumeProfile.Add<UnityEngine.Rendering.HighDefinition.AmbientOcclusion>();
|
|
}
|
|
if (volumeProfile.TryGet(out HDRPAmbientOcclusion))
|
|
{
|
|
HDRPAmbientOcclusion.active = true;
|
|
HDRPAmbientOcclusion.intensity.value = ambientOcclusion.intensity;
|
|
HDRPAmbientOcclusion.directLightingStrength.value = ambientOcclusion.directLightingStrength;
|
|
HDRPAmbientOcclusion.radius.value = ambientOcclusion.thicknessModifier;
|
|
HDRPAmbientOcclusion.quality.value = 2;
|
|
HDRPAmbientOcclusion.SetAllOverridesTo(true);
|
|
}
|
|
}
|
|
|
|
//Bloom
|
|
if (profile.TryGetSettings(out bloom))
|
|
{
|
|
if (!volumeProfile.Has<UnityEngine.Rendering.HighDefinition.Bloom>())
|
|
{
|
|
volumeProfile.Add<UnityEngine.Rendering.HighDefinition.Bloom>();
|
|
}
|
|
if (volumeProfile.TryGet(out HDRPBloom))
|
|
{
|
|
HDRPBloom.active = true;
|
|
HDRPBloom.intensity.value = bloom.intensity;
|
|
HDRPBloom.threshold.value = bloom.threshold;
|
|
HDRPBloom.tint.value = bloom.color;
|
|
HDRPBloom.scatter.value = bloom.softKnee;
|
|
HDRPBloom.quality.value = 3;
|
|
HDRPBloom.dirtTexture.value = bloom.dirtTexture;
|
|
HDRPBloom.dirtIntensity.value = bloom.dirtIntensity;
|
|
HDRPBloom.SetAllOverridesTo(true);
|
|
}
|
|
}
|
|
|
|
//Chromatic Aberration
|
|
if (profile.TryGetSettings(out chromaticAberration))
|
|
{
|
|
if (!volumeProfile.Has<UnityEngine.Rendering.HighDefinition.ChromaticAberration>())
|
|
{
|
|
volumeProfile.Add<UnityEngine.Rendering.HighDefinition.ChromaticAberration>();
|
|
}
|
|
if (volumeProfile.TryGet(out HDRPChromaticAberration))
|
|
{
|
|
HDRPChromaticAberration.active = true;
|
|
HDRPChromaticAberration.intensity.value = chromaticAberration.intensity;
|
|
HDRPChromaticAberration.SetAllOverridesTo(true);
|
|
}
|
|
}
|
|
|
|
//Color Grading
|
|
if (profile.TryGetSettings(out colorGrading))
|
|
{
|
|
if (!volumeProfile.Has<UnityEngine.Rendering.HighDefinition.ColorAdjustments>())
|
|
{
|
|
volumeProfile.Add<UnityEngine.Rendering.HighDefinition.ColorAdjustments>();
|
|
}
|
|
if (volumeProfile.TryGet(out HDRPColorAdjustments))
|
|
{
|
|
HDRPColorAdjustments.active = true;
|
|
HDRPColorAdjustments.postExposure.value = colorGrading.postExposure;
|
|
HDRPColorAdjustments.contrast.value = colorGrading.contrast;
|
|
HDRPColorAdjustments.colorFilter.value = colorGrading.colorFilter;
|
|
HDRPColorAdjustments.hueShift.value = colorGrading.hueShift;
|
|
HDRPColorAdjustments.saturation.value = colorGrading.saturation;
|
|
HDRPColorAdjustments.SetAllOverridesTo(true);
|
|
}
|
|
|
|
if (!volumeProfile.Has<UnityEngine.Rendering.HighDefinition.WhiteBalance>())
|
|
{
|
|
volumeProfile.Add<UnityEngine.Rendering.HighDefinition.WhiteBalance>();
|
|
}
|
|
if (volumeProfile.TryGet(out HDRPWhiteBalance))
|
|
{
|
|
HDRPWhiteBalance.active = true;
|
|
HDRPWhiteBalance.temperature.value = colorGrading.temperature;
|
|
HDRPWhiteBalance.tint.value = colorGrading.tint;
|
|
HDRPWhiteBalance.SetAllOverridesTo(true);
|
|
}
|
|
|
|
if (!volumeProfile.Has<UnityEngine.Rendering.HighDefinition.ChannelMixer>())
|
|
{
|
|
volumeProfile.Add<UnityEngine.Rendering.HighDefinition.ChannelMixer>();
|
|
}
|
|
if (volumeProfile.TryGet(out HDRPChannelMixer))
|
|
{
|
|
HDRPChannelMixer.active = true;
|
|
HDRPChannelMixer.blueOutBlueIn.value = colorGrading.mixerBlueOutBlueIn;
|
|
HDRPChannelMixer.blueOutGreenIn.value = colorGrading.mixerBlueOutGreenIn;
|
|
HDRPChannelMixer.blueOutRedIn.value = colorGrading.mixerBlueOutRedIn;
|
|
|
|
HDRPChannelMixer.greenOutBlueIn.value = colorGrading.mixerGreenOutBlueIn;
|
|
HDRPChannelMixer.greenOutGreenIn.value = colorGrading.mixerGreenOutGreenIn;
|
|
HDRPChannelMixer.greenOutRedIn.value = colorGrading.mixerGreenOutRedIn;
|
|
|
|
HDRPChannelMixer.redOutBlueIn.value = colorGrading.mixerRedOutBlueIn;
|
|
HDRPChannelMixer.redOutGreenIn.value = colorGrading.mixerRedOutGreenIn;
|
|
HDRPChannelMixer.redOutRedIn.value = colorGrading.mixerRedOutRedIn;
|
|
HDRPChannelMixer.SetAllOverridesTo(true);
|
|
}
|
|
|
|
if (!volumeProfile.Has<UnityEngine.Rendering.HighDefinition.Tonemapping>())
|
|
{
|
|
volumeProfile.Add<UnityEngine.Rendering.HighDefinition.Tonemapping>();
|
|
}
|
|
if (volumeProfile.TryGet(out HDRPTonemapping))
|
|
{
|
|
HDRPTonemapping.active = true;
|
|
switch (colorGrading.tonemapper.value)
|
|
{
|
|
case Tonemapper.None:
|
|
HDRPTonemapping.mode.value = UnityEngine.Rendering.HighDefinition.TonemappingMode.None;
|
|
break;
|
|
case Tonemapper.Neutral:
|
|
HDRPTonemapping.mode.value = UnityEngine.Rendering.HighDefinition.TonemappingMode.Neutral;
|
|
break;
|
|
case Tonemapper.ACES:
|
|
HDRPTonemapping.mode.value = UnityEngine.Rendering.HighDefinition.TonemappingMode.ACES;
|
|
break;
|
|
}
|
|
HDRPTonemapping.SetAllOverridesTo(true);
|
|
}
|
|
}
|
|
|
|
//Depth Of Field
|
|
if (profile.TryGetSettings(out depthOfField))
|
|
{
|
|
if (!volumeProfile.Has<UnityEngine.Rendering.HighDefinition.DepthOfField>())
|
|
{
|
|
volumeProfile.Add<UnityEngine.Rendering.HighDefinition.DepthOfField>();
|
|
}
|
|
if (volumeProfile.TryGet(out HDRPDepthOfField))
|
|
{
|
|
HDRPDepthOfField.active = true;
|
|
HDRPDepthOfField.focusMode.value = UnityEngine.Rendering.HighDefinition.DepthOfFieldMode.UsePhysicalCamera;
|
|
HDRPDepthOfField.focusDistance.value = depthOfField.focusDistance;
|
|
HDRPDepthOfField.SetAllOverridesTo(true);
|
|
}
|
|
}
|
|
|
|
//Film Grain
|
|
if (profile.TryGetSettings(out grain))
|
|
{
|
|
if (!volumeProfile.Has<UnityEngine.Rendering.HighDefinition.FilmGrain>())
|
|
{
|
|
volumeProfile.Add<UnityEngine.Rendering.HighDefinition.FilmGrain>();
|
|
}
|
|
if (volumeProfile.TryGet(out HDRPFilmGrain))
|
|
{
|
|
HDRPFilmGrain.active = true;
|
|
HDRPFilmGrain.intensity.value = grain.intensity;
|
|
HDRPFilmGrain.SetAllOverridesTo(true);
|
|
}
|
|
}
|
|
|
|
//Lens Distortion
|
|
if (profile.TryGetSettings(out lensDistortion))
|
|
{
|
|
if (!volumeProfile.Has<UnityEngine.Rendering.HighDefinition.LensDistortion>())
|
|
{
|
|
volumeProfile.Add<UnityEngine.Rendering.HighDefinition.LensDistortion>();
|
|
}
|
|
if (volumeProfile.TryGet(out HDRPLensDistortion))
|
|
{
|
|
HDRPLensDistortion.active = true;
|
|
Vector2 center = new Vector2(lensDistortion.centerX, lensDistortion.centerY);
|
|
HDRPLensDistortion.center.value = center;
|
|
HDRPLensDistortion.intensity.value = lensDistortion.intensity;
|
|
HDRPLensDistortion.xMultiplier.value = lensDistortion.intensityX;
|
|
HDRPLensDistortion.yMultiplier.value = lensDistortion.intensityY;
|
|
HDRPLensDistortion.scale.value = lensDistortion.scale;
|
|
HDRPLensDistortion.SetAllOverridesTo(true);
|
|
}
|
|
}
|
|
|
|
//Motion Blur
|
|
if (profile.TryGetSettings(out motionBlur))
|
|
{
|
|
if (!volumeProfile.Has<UnityEngine.Rendering.HighDefinition.MotionBlur>())
|
|
{
|
|
volumeProfile.Add<UnityEngine.Rendering.HighDefinition.MotionBlur>();
|
|
}
|
|
if (volumeProfile.TryGet(out HDRPMotionBlur))
|
|
{
|
|
HDRPMotionBlur.active = true;
|
|
HDRPMotionBlur.intensity.value = motionBlur.shutterAngle;
|
|
HDRPMotionBlur.SetAllOverridesTo(true);
|
|
}
|
|
}
|
|
|
|
//Vignette
|
|
if (profile.TryGetSettings(out vignette))
|
|
{
|
|
if (!volumeProfile.Has<UnityEngine.Rendering.HighDefinition.Vignette>())
|
|
{
|
|
volumeProfile.Add<UnityEngine.Rendering.HighDefinition.Vignette>();
|
|
}
|
|
if (volumeProfile.TryGet(out HDRPVignette))
|
|
{
|
|
HDRPVignette.active = true;
|
|
HDRPVignette.intensity.value = vignette.intensity;
|
|
HDRPVignette.rounded.value = vignette.rounded;
|
|
HDRPVignette.smoothness.value = vignette.smoothness;
|
|
HDRPVignette.SetAllOverridesTo(true);
|
|
}
|
|
}
|
|
|
|
//Split Toning
|
|
if (!volumeProfile.Has<UnityEngine.Rendering.HighDefinition.SplitToning>())
|
|
{
|
|
volumeProfile.Add<UnityEngine.Rendering.HighDefinition.SplitToning>();
|
|
}
|
|
if (volumeProfile.TryGet(out HDRPSplitToning))
|
|
{
|
|
HDRPSplitToning.active = true;
|
|
HDRPSplitToning.shadows.value = GaiaUtils.GetColorFromHTML("636363");
|
|
HDRPSplitToning.highlights.value = GaiaUtils.GetColorFromHTML("909090");
|
|
HDRPSplitToning.balance.value = -20f;
|
|
HDRPSplitToning.SetAllOverridesTo(true);
|
|
}
|
|
#endif
|
|
}
|
|
else
|
|
{
|
|
Debug.Log("This feature only supported to create URP/HDRP post processing profiles from Built-In Post FX Stack V2. Please make sure the correct pipeline is selected to create to.");
|
|
}
|
|
|
|
EditorUtility.SetDirty(volumeProfile);
|
|
AssetDatabase.SaveAssets();
|
|
EditorGUIUtility.PingObject(volumeProfile);
|
|
}
|
|
#endif
|
|
#endif
|
|
|
|
#if HDPipeline
|
|
/// <summary>
|
|
/// Used to check if the light render mode is in LUX
|
|
/// </summary>
|
|
/// <param name="lightData"></param>
|
|
/// <param name="currentLightIntensity"></param>
|
|
public static void CheckHDRPLightRenderMode(HDAdditionalLightData lightData, float currentLightIntensity)
|
|
{
|
|
if (lightData != null)
|
|
{
|
|
if (lightData.lightUnit != LightUnit.Lux)
|
|
{
|
|
lightData.lightUnit = LightUnit.Lux;
|
|
lightData.intensity = currentLightIntensity;
|
|
}
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Checks to see if HDRP Light data is on active light set as 'checkLight'
|
|
/// </summary>
|
|
/// <param name="checkLight"></param>
|
|
/// <returns></returns>
|
|
public static HDAdditionalLightData GetOrAddHDRPLightData(Light checkLight)
|
|
{
|
|
HDAdditionalLightData HDRPLightData = null;
|
|
if (checkLight != null)
|
|
{
|
|
HDRPLightData = checkLight.GetComponent<HDAdditionalLightData>();
|
|
if (HDRPLightData == null)
|
|
{
|
|
HDRPLightData = checkLight.gameObject.AddComponent<HDAdditionalLightData>();
|
|
}
|
|
}
|
|
|
|
return HDRPLightData;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Multiplies the value by multiply value, which is defaulted to 3.14
|
|
/// </summary>
|
|
/// <param name="value"></param>
|
|
/// <returns></returns>
|
|
public static float SetHDRPFloat(float value, float multiply = 3.14f)
|
|
{
|
|
float newValue = value * multiply;
|
|
return newValue;
|
|
}
|
|
|
|
public static Color SetHDRPColor(Color value)
|
|
{
|
|
Color newColor = value;
|
|
return newColor;
|
|
}
|
|
#endif
|
|
|
|
/// <summary>
|
|
/// Gets and returns the main camera in the scene
|
|
/// If check tag is set to ture it will check to see if the camera found tag is marked as MainCamera or Player
|
|
/// </summary>
|
|
/// <returns></returns>
|
|
public static Camera GetCamera(bool checkTag = false)
|
|
{
|
|
Camera camera = Camera.main;
|
|
if (camera != null)
|
|
{
|
|
if (checkTag)
|
|
{
|
|
if (camera.tag == "MainCamera" || camera.tag == "Player")
|
|
{
|
|
return camera;
|
|
}
|
|
}
|
|
return camera;
|
|
}
|
|
|
|
camera = GameObject.FindObjectOfType<Camera>();
|
|
if (camera != null)
|
|
{
|
|
if (checkTag)
|
|
{
|
|
if (camera.tag == "MainCamera" || camera.tag == "Player")
|
|
{
|
|
return camera;
|
|
}
|
|
}
|
|
|
|
return camera;
|
|
}
|
|
|
|
return null;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Gets the player that has a character ocntroller attached to the camera/player
|
|
/// </summary>
|
|
/// <returns></returns>
|
|
public static GameObject GetCharacter()
|
|
{
|
|
GameObject playerObject = null;
|
|
|
|
CharacterController characterController = GameObject.FindObjectOfType<CharacterController>();
|
|
if (characterController != null)
|
|
{
|
|
playerObject = characterController.gameObject;
|
|
}
|
|
|
|
return playerObject;
|
|
}
|
|
/// <summary>
|
|
/// Checks to see if the scene profile is present. This check can also be used to see if gaia global exists too
|
|
/// </summary>
|
|
/// <returns></returns>
|
|
public static bool CheckIfSceneProfileExists()
|
|
{
|
|
if (GaiaGlobal.Instance == null)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
if (GaiaGlobal.Instance.SceneProfile == null)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Get the main directional light in the scene
|
|
/// </summary>
|
|
/// <returns>Main light or null</returns>
|
|
public static Light GetMainDirectionalLight()
|
|
{
|
|
GameObject lightObject = GameObject.Find("Directional Light");
|
|
Light mainSunLight = null;
|
|
|
|
if (lightObject == null)
|
|
{
|
|
lightObject = GameObject.Find("Enviro Directional Light");
|
|
}
|
|
|
|
if (lightObject != null)
|
|
{
|
|
mainSunLight = lightObject.GetComponent<Light>();
|
|
}
|
|
if (lightObject == null)
|
|
{
|
|
//Grab the first directional light we can find
|
|
Light[] lights = GameObject.FindObjectsOfType<Light>();
|
|
foreach (var light in lights)
|
|
{
|
|
if (light.type == LightType.Directional && light.name != "Moon Light")
|
|
{
|
|
if (light.isActiveAndEnabled)
|
|
{
|
|
lightObject = light.gameObject;
|
|
mainSunLight = light;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if (lightObject == null)
|
|
{
|
|
lightObject = new GameObject("Directional Light");
|
|
lightObject.transform.rotation = Quaternion.Euler(50f, -30f, 0f);
|
|
Light lightSettings = lightObject.AddComponent<Light>();
|
|
lightSettings.type = LightType.Directional;
|
|
mainSunLight = lightSettings;
|
|
mainSunLight.shadowStrength = 0.8f;
|
|
}
|
|
|
|
GameObject parentObject = GameObject.Find("Gaia Lighting");
|
|
if (parentObject != null)
|
|
{
|
|
lightObject.transform.SetParent(parentObject.transform);
|
|
}
|
|
|
|
return mainSunLight;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Gets or creates the moon object
|
|
/// </summary>
|
|
/// <returns></returns>
|
|
public static Light GetMainMoonLight()
|
|
{
|
|
Light moonLight = null;
|
|
GameObject moonObject = GameObject.Find("Moon Light");
|
|
if (moonObject == null)
|
|
{
|
|
moonObject = new GameObject("Moon Light");
|
|
}
|
|
|
|
moonLight = moonObject.GetComponent<Light>();
|
|
if (moonLight == null)
|
|
{
|
|
moonLight = moonObject.AddComponent<Light>();
|
|
}
|
|
|
|
moonLight.type = LightType.Directional;
|
|
moonLight.shadows = LightShadows.Soft;
|
|
moonLight.color = GaiaUtils.GetColorFromHTML("6A95CF");
|
|
moonLight.intensity = 0f;
|
|
|
|
return moonLight;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Gets the water material on the object
|
|
/// </summary>
|
|
/// <returns></returns>
|
|
public static Material GetWaterMaterial(string waterObjectName, bool getUnderWaterMaterial = false)
|
|
{
|
|
Material material = null;
|
|
MeshRenderer meshRender = null;
|
|
GameObject waterObject = GameObject.Find(waterObjectName);
|
|
if (waterObject != null)
|
|
{
|
|
meshRender = waterObject.GetComponent<MeshRenderer>();
|
|
if (meshRender != null)
|
|
{
|
|
Material[] materials = meshRender.sharedMaterials;
|
|
if (materials.Length == 2)
|
|
{
|
|
if (getUnderWaterMaterial)
|
|
{
|
|
material = materials[1];
|
|
}
|
|
else
|
|
{
|
|
material = materials[0];
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return material;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Removes systems from scene
|
|
/// </summary>
|
|
public static void RemoveWaterSystems()
|
|
{
|
|
GameObject waterObject = GameObject.Find(GaiaConstants.waterSurfaceObject);
|
|
if (waterObject != null)
|
|
{
|
|
GameObject.DestroyImmediate(waterObject);
|
|
}
|
|
|
|
|
|
GameObject underwaterObject = GameObject.Find(GaiaConstants.underwaterEffectsName);
|
|
if (underwaterObject != null)
|
|
{
|
|
GameObject.DestroyImmediate(underwaterObject);
|
|
}
|
|
}
|
|
/// <summary>
|
|
/// Removes Aquas from the scene
|
|
/// </summary>
|
|
/// <param name="camera"></param>
|
|
public static void RemoveAquas(Camera camera, GaiaConstants.GlobalSystemMode overrideMode = GlobalSystemMode.Gaia)
|
|
{
|
|
if (camera == null)
|
|
{
|
|
return;
|
|
}
|
|
|
|
GameObject aquasWater = GameObject.Find("AQUAS Waterplane");
|
|
if (aquasWater != null)
|
|
{
|
|
GameObject.DestroyImmediate(aquasWater);
|
|
}
|
|
|
|
GameObject aquasWater2 = GameObject.Find("AQUAS Container");
|
|
if (aquasWater2 != null)
|
|
{
|
|
GameObject.DestroyImmediate(aquasWater2);
|
|
}
|
|
|
|
GameObject aquasUnderwater = GameObject.Find("UnderWaterCameraEffects");
|
|
if (aquasUnderwater != null)
|
|
{
|
|
GameObject.DestroyImmediate(aquasUnderwater);
|
|
}
|
|
|
|
#if AQUAS_PRESENT
|
|
AQUAS_Camera aquasCamera = camera.GetComponent<AQUAS_Camera>();
|
|
if (aquasCamera != null)
|
|
{
|
|
GameObject.DestroyImmediate(aquasCamera);
|
|
}
|
|
#endif
|
|
|
|
#if AQUAS_2020_PRESENT
|
|
AQUAS_Camera aquasCamera = camera.GetComponent<AQUAS_Camera>();
|
|
if (aquasCamera != null)
|
|
{
|
|
GameObject.DestroyImmediate(aquasCamera);
|
|
}
|
|
#endif
|
|
|
|
#if UNITY_POST_PROCESSING_STACK_V2
|
|
PostProcessVolume underwaterVolume = camera.GetComponent<PostProcessVolume>();
|
|
if (underwaterVolume != null)
|
|
{
|
|
GameObject.DestroyImmediate(underwaterVolume);
|
|
}
|
|
#endif
|
|
#if UNITY_POST_PROCESSING_STACK_V1 && AQUAS_PRESENT
|
|
PostProcessingBehaviour postProcessV1 = camera.gameObject.GetComponent<PostProcessingBehaviour>();
|
|
if (postProcessV1 != null)
|
|
{
|
|
GameObject.DestroyImmediate(postProcessV1);
|
|
}
|
|
#endif
|
|
|
|
if (GaiaGlobal.Instance != null)
|
|
{
|
|
if (GaiaGlobal.Instance.SceneProfile != null)
|
|
{
|
|
GaiaGlobal.Instance.SceneProfile.m_waterSystemMode = overrideMode;
|
|
}
|
|
}
|
|
}
|
|
/// <summary>
|
|
/// Parents the enviro system objects to Gaia Lighting
|
|
/// </summary>
|
|
public static void ParentEnviroToGaiaSystem()
|
|
{
|
|
GameObject parent = GetOrCreateParentObject(GaiaConstants.gaiaLightingObject, true);
|
|
|
|
GameObject mainInstance = GameObject.Find("Enviro Sky Manager for GAIA");
|
|
if (mainInstance != null)
|
|
{
|
|
mainInstance.transform.SetParent(parent.transform);
|
|
}
|
|
|
|
GameObject mainLight = GameObject.Find("Enviro Directional Light");
|
|
if (mainLight != null)
|
|
{
|
|
mainLight.transform.SetParent(parent.transform);
|
|
}
|
|
|
|
GameObject mainEffects = GameObject.Find("Enviro Effects");
|
|
if (mainEffects != null)
|
|
{
|
|
mainEffects.transform.SetParent(parent.transform);
|
|
}
|
|
|
|
GameObject mainEffectsLW = GameObject.Find("Enviro Effects LW");
|
|
if (mainEffectsLW != null)
|
|
{
|
|
mainEffectsLW.transform.SetParent(parent.transform);
|
|
}
|
|
}
|
|
/// <summary>
|
|
/// Removes enviro from the scene
|
|
/// </summary>
|
|
public static void RemoveEnviro()
|
|
{
|
|
GameObject mainInstance = GameObject.Find("Enviro Sky Manager for GAIA");
|
|
if (mainInstance != null)
|
|
{
|
|
GameObject.DestroyImmediate(mainInstance);
|
|
}
|
|
|
|
GameObject mainLight = GameObject.Find("Enviro Directional Light");
|
|
if (mainLight != null)
|
|
{
|
|
GameObject.DestroyImmediate(mainLight);
|
|
}
|
|
|
|
GameObject mainEffects = GameObject.Find("Enviro Effects");
|
|
if (mainEffects != null)
|
|
{
|
|
GameObject.DestroyImmediate(mainEffects);
|
|
}
|
|
|
|
GameObject mainEffectsLW = GameObject.Find("Enviro Effects LW");
|
|
if (mainEffectsLW != null)
|
|
{
|
|
GameObject.DestroyImmediate(mainEffectsLW);
|
|
}
|
|
|
|
#if ENVIRO_HD
|
|
EnviroSkyRendering skyRendering = FindObjectOfType<EnviroSkyRendering>();
|
|
if (skyRendering != null)
|
|
{
|
|
GameObject.DestroyImmediate(skyRendering);
|
|
}
|
|
|
|
EnviroPostProcessing enviroPostProcessing = FindObjectOfType<EnviroPostProcessing>();
|
|
if (enviroPostProcessing != null)
|
|
{
|
|
GameObject.DestroyImmediate(enviroPostProcessing);
|
|
}
|
|
#endif
|
|
|
|
#if ENVIRO_LW
|
|
EnviroSkyRenderingLW skyRenderingLW = FindObjectOfType<EnviroSkyRenderingLW>();
|
|
if (skyRenderingLW != null)
|
|
{
|
|
GameObject.DestroyImmediate(skyRenderingLW);
|
|
}
|
|
#endif
|
|
}
|
|
/// <summary>
|
|
/// Get or create a parent object
|
|
/// </summary>
|
|
/// <param name="parentGameObject"></param>
|
|
/// <param name="parentToGaia"></param>
|
|
/// <returns>Parent Object</returns>
|
|
private static GameObject GetOrCreateParentObject(string parentGameObject, bool parentToGaia)
|
|
{
|
|
//Get the parent object
|
|
GameObject theParentGo = GameObject.Find(parentGameObject);
|
|
|
|
if (theParentGo == null)
|
|
{
|
|
theParentGo = GameObject.Find(GaiaConstants.gaiaLightingObject);
|
|
|
|
if (theParentGo == null)
|
|
{
|
|
theParentGo = new GameObject(GaiaConstants.gaiaLightingObject);
|
|
}
|
|
}
|
|
|
|
if (theParentGo.GetComponent<GaiaSceneLighting>() == null)
|
|
{
|
|
theParentGo.AddComponent<GaiaSceneLighting>();
|
|
}
|
|
|
|
if (parentToGaia)
|
|
{
|
|
GameObject gaiaParent = GaiaUtils.GetRuntimeSceneObject();
|
|
if (gaiaParent != null)
|
|
{
|
|
theParentGo.transform.SetParent(gaiaParent.transform);
|
|
}
|
|
}
|
|
|
|
return theParentGo;
|
|
}
|
|
/// <summary>
|
|
/// Sets custom water in the scene
|
|
/// </summary>
|
|
/// <param name="customWaterObject"></param>
|
|
public static void SetCustomWaterSystem(GameObject customWaterObject)
|
|
{
|
|
if (customWaterObject == null)
|
|
{
|
|
Debug.LogError("Custom Water Object is null please make sure the object is not null before calling SetCustomWaterSystem()");
|
|
return;
|
|
}
|
|
|
|
if (GaiaGlobal.Instance != null)
|
|
{
|
|
if (GaiaGlobal.Instance.SceneProfile != null)
|
|
{
|
|
GaiaGlobal.Instance.SceneProfile.m_waterSystemMode = GlobalSystemMode.ThirdParty;
|
|
GaiaGlobal.Instance.SceneProfile.m_thirdPartyWaterObject = customWaterObject;
|
|
}
|
|
}
|
|
}
|
|
/// <summary>
|
|
/// Sets custom lighting in the scene
|
|
/// </summary>
|
|
/// <param name="customLightObject"></param>
|
|
public static void SetCustomLightSystem(GameObject customLightObject)
|
|
{
|
|
if (customLightObject == null)
|
|
{
|
|
Debug.LogError("Custom Light Object is null please make sure the object is not null before calling SetCustomLightSystem()");
|
|
return;
|
|
}
|
|
|
|
if (GaiaGlobal.Instance != null)
|
|
{
|
|
if (GaiaGlobal.Instance.SceneProfile != null)
|
|
{
|
|
GaiaGlobal.Instance.SceneProfile.m_lightSystemMode = GlobalSystemMode.ThirdParty;
|
|
GaiaGlobal.Instance.SceneProfile.m_thirdPartyLightObject = customLightObject;
|
|
}
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Loads the underwater material
|
|
/// </summary>
|
|
/// <returns></returns>
|
|
public static Material LoadUnderwaterMaterial()
|
|
{
|
|
#if UNITY_EDITOR
|
|
return AssetDatabase.LoadAssetAtPath<Material>(GetAssetPath(GaiaConstants.gaiaUnderwaterMaterial + ".mat"));
|
|
#else
|
|
return null;
|
|
#endif
|
|
}
|
|
/// <summary>
|
|
/// Removes the post processing v2 volume component from the supplied object
|
|
/// </summary>
|
|
/// <param name="postFXObject"></param>
|
|
public static void RemovePostPorcessV2VolumeComponent(GameObject postFXObject)
|
|
{
|
|
if (postFXObject == null)
|
|
{
|
|
return;
|
|
}
|
|
|
|
#if UNITY_POST_PROCESSING_STACK_V2
|
|
PostProcessVolume volume = postFXObject.GetComponent<PostProcessVolume>();
|
|
if (volume != null)
|
|
{
|
|
GameObject.DestroyImmediate(volume);
|
|
}
|
|
#endif
|
|
}
|
|
|
|
#if HDPipeline
|
|
/// <summary>
|
|
/// Gets the HDRP planar reflection probes
|
|
/// </summary>
|
|
/// <returns></returns>
|
|
public static PlanarReflectionProbe GetHDRPPlanarReflectionProbe()
|
|
{
|
|
PlanarReflectionProbe planarReflection = null;
|
|
GameObject planarReflectionObject = GameObject.Find(GaiaConstants.gaiaHDRPPlanarReflections);
|
|
if (planarReflectionObject != null)
|
|
{
|
|
planarReflection = planarReflectionObject.GetComponent<PlanarReflectionProbe>();
|
|
}
|
|
else
|
|
{
|
|
planarReflectionObject = new GameObject(GaiaConstants.gaiaHDRPPlanarReflections);
|
|
planarReflection = planarReflectionObject.AddComponent<PlanarReflectionProbe>();
|
|
}
|
|
|
|
return planarReflection;
|
|
}
|
|
#endif
|
|
|
|
/// <summary>
|
|
/// Write a scriptable object out into a new asset that can be shared
|
|
/// </summary>
|
|
/// <typeparam name="T">The scriptable object to be saved as an asset</typeparam>
|
|
public static T CreateAsset<T>(string path = "", string name = "") where T : ScriptableObject
|
|
{
|
|
#if UNITY_EDITOR
|
|
T asset = ScriptableObject.CreateInstance<T>();
|
|
|
|
if (path == "")
|
|
{
|
|
path = AssetDatabase.GetAssetPath(Selection.activeObject);
|
|
if (path == "")
|
|
{
|
|
path = "Assets";
|
|
}
|
|
else if (Path.GetExtension(path) != "")
|
|
{
|
|
path = path.Replace(Path.GetFileName(AssetDatabase.GetAssetPath(Selection.activeObject)), "");
|
|
}
|
|
}
|
|
if (name == "")
|
|
{
|
|
name = path + "/New " + typeof(T).ToString() + ".asset";
|
|
}
|
|
else
|
|
{
|
|
name = path + "/New " + name + ".asset";
|
|
}
|
|
|
|
string assetPathAndName = AssetDatabase.GenerateUniqueAssetPath(name);
|
|
AssetDatabase.CreateAsset(asset, assetPathAndName);
|
|
AssetDatabase.SaveAssets();
|
|
AssetDatabase.Refresh();
|
|
EditorUtility.FocusProjectWindow();
|
|
Selection.activeObject = asset;
|
|
return asset;
|
|
#else
|
|
return null;
|
|
#endif
|
|
}
|
|
|
|
/// <summary>
|
|
/// Finds a unitypackage based on the packageName provided.
|
|
/// If autoImport is set to ture the package will just import without showing the package import window.
|
|
/// </summary>
|
|
/// <param name="packageName"></param>
|
|
/// <param name="autoImport"></param>
|
|
public static void ImportUnityPackage(string packageName, bool autoImport)
|
|
{
|
|
#if UNITY_EDITOR
|
|
if (string.IsNullOrEmpty(packageName))
|
|
{
|
|
return;
|
|
}
|
|
|
|
string packagePath = GetAssetPath(packageName + ".unitypackage");
|
|
if (string.IsNullOrEmpty(packagePath))
|
|
{
|
|
return;
|
|
}
|
|
|
|
AssetDatabase.ImportPackage(packagePath, autoImport);
|
|
#endif
|
|
}
|
|
|
|
/// <summary>
|
|
/// Get the path of the unity object supplied
|
|
/// </summary>
|
|
/// <param name="uo"></param>
|
|
/// <returns></returns>
|
|
public static string GetAssetPath(UnityEngine.Object uo)
|
|
{
|
|
string path = "";
|
|
#if UNITY_EDITOR
|
|
path = Path.Combine(Application.dataPath, AssetDatabase.GetAssetPath(uo));
|
|
path = path.Replace("/Assets", "");
|
|
path = path.Replace("\\", "/");
|
|
#endif
|
|
return path;
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
/// Wrap the scriptable object up so that it can be transferred without causing unity errors
|
|
/// </summary>
|
|
/// <param name="so"></param>
|
|
public static string WrapScriptableObject(ScriptableObject so)
|
|
{
|
|
string newpath = "";
|
|
#if UNITY_EDITOR
|
|
string path = GetAssetPath(so);
|
|
if (File.Exists(path))
|
|
{
|
|
newpath = Path.ChangeExtension(path, "bytes");
|
|
UnityEditor.FileUtil.CopyFileOrDirectory(path, newpath);
|
|
}
|
|
else
|
|
{
|
|
Debug.LogError("There is no file at the path supplied: " + path);
|
|
}
|
|
#endif
|
|
return newpath;
|
|
}
|
|
|
|
|
|
public static void UnwrapScriptableObject(string path, string newpath)
|
|
{
|
|
#if UNITY_EDITOR
|
|
if (File.Exists(path))
|
|
{
|
|
if (!File.Exists(newpath))
|
|
{
|
|
UnityEditor.FileUtil.CopyFileOrDirectory(path, newpath);
|
|
}
|
|
else
|
|
{
|
|
Debug.LogError("There is already a file with this name at the path supplied: " + newpath);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
Debug.LogError("There is no file at the path supplied: " + path);
|
|
}
|
|
#endif
|
|
}
|
|
|
|
public static string WrapGameObjectAsPrefab(GameObject go)
|
|
{
|
|
#if UNITY_EDITOR
|
|
#if UNITY_2018_3_OR_NEWER
|
|
string name = go.name;
|
|
UnityEngine.Object prefab = PrefabUtility.SaveAsPrefabAsset(new GameObject(), "Assets/" + name + ".prefab");
|
|
PrefabUtility.SavePrefabAsset(go);
|
|
AssetDatabase.Refresh();
|
|
return AssetDatabase.GetAssetPath(prefab);
|
|
#else
|
|
string name = go.name;
|
|
UnityEngine.Object prefab = PrefabUtility.CreateEmptyPrefab("Assets/" + name + ".prefab");
|
|
PrefabUtility.ReplacePrefab(go, prefab);
|
|
AssetDatabase.Refresh();
|
|
return AssetDatabase.GetAssetPath(prefab);
|
|
#endif
|
|
#else
|
|
return "";
|
|
#endif
|
|
}
|
|
|
|
public static bool HasTerrains()
|
|
{
|
|
return (TerrainLoaderManager.TerrainScenes.Count > 0 || Terrain.activeTerrains.Where(x => !TerrainHelper.IsWorldMapTerrain(x)).Count() > 0);
|
|
}
|
|
|
|
public static EnvironmentSize IntToEnvironmentSize(int terrainSize)
|
|
{
|
|
switch (terrainSize)
|
|
{
|
|
case 256:
|
|
return GaiaConstants.EnvironmentSize.Is256MetersSq;
|
|
case 512:
|
|
return GaiaConstants.EnvironmentSize.Is512MetersSq;
|
|
case 1024:
|
|
return GaiaConstants.EnvironmentSize.Is1024MetersSq;
|
|
case 2048:
|
|
return GaiaConstants.EnvironmentSize.Is2048MetersSq;
|
|
case 4096:
|
|
return GaiaConstants.EnvironmentSize.Is4096MetersSq;
|
|
case 8192:
|
|
return GaiaConstants.EnvironmentSize.Is8192MetersSq;
|
|
case 16384:
|
|
return GaiaConstants.EnvironmentSize.Is16384MetersSq;
|
|
}
|
|
return GaiaConstants.EnvironmentSize.Is256MetersSq;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Get the asset path of the first thing that matches the name
|
|
/// </summary>
|
|
/// <param name="fileName">File name to search for</param>
|
|
/// <returns></returns>
|
|
public static string GetAssetPath(string fileName)
|
|
{
|
|
#if UNITY_EDITOR
|
|
string fName = Path.GetFileNameWithoutExtension(fileName);
|
|
string[] assets = AssetDatabase.FindAssets(fName, null);
|
|
for (int idx = 0; idx < assets.Length; idx++)
|
|
{
|
|
string path = AssetDatabase.GUIDToAssetPath(assets[idx]);
|
|
if (Path.GetFileName(path) == fileName)
|
|
{
|
|
return path;
|
|
}
|
|
}
|
|
#endif
|
|
return "";
|
|
}
|
|
|
|
/// <summary>
|
|
/// Get the asset path of the first thing that matches the name
|
|
/// </summary>
|
|
/// <param name="name">Name to search for</param>
|
|
/// <param name="name">Type to search for</param>
|
|
/// <returns></returns>
|
|
public static string GetAssetPath(string name, string type)
|
|
{
|
|
#if UNITY_EDITOR
|
|
string[] assets = AssetDatabase.FindAssets(name, null);
|
|
string[] file;
|
|
for (int idx = 0; idx < assets.Length; idx++)
|
|
{
|
|
string path = AssetDatabase.GUIDToAssetPath(assets[idx]);
|
|
//Make sure its an exact match
|
|
file = Path.GetFileName(path).Split('.');
|
|
if (file.GetLength(0) != 2)
|
|
{
|
|
continue;
|
|
}
|
|
if (file[0] != name)
|
|
{
|
|
continue;
|
|
}
|
|
if (file[1] != type)
|
|
{
|
|
continue;
|
|
}
|
|
return path;
|
|
}
|
|
#endif
|
|
return "";
|
|
}
|
|
|
|
/// <summary>
|
|
/// Returns the first asset that matches the file path and name passed. Will try
|
|
/// full path first, then will try just the file name.
|
|
/// </summary>
|
|
/// <param name="fileNameOrPath">File name as standalone or fully pathed</param>
|
|
/// <returns>Object or null if it was not found</returns>
|
|
public static UnityEngine.Object GetAsset(string fileNameOrPath, Type assetType)
|
|
{
|
|
#if UNITY_EDITOR
|
|
if (!string.IsNullOrEmpty(fileNameOrPath))
|
|
{
|
|
UnityEngine.Object obj = AssetDatabase.LoadAssetAtPath(fileNameOrPath, assetType);
|
|
if (obj != null)
|
|
{
|
|
return obj;
|
|
}
|
|
else
|
|
{
|
|
string path = GetAssetPath(Path.GetFileName(fileNameOrPath));
|
|
if (!string.IsNullOrEmpty(path))
|
|
{
|
|
return AssetDatabase.LoadAssetAtPath(path, assetType);
|
|
}
|
|
}
|
|
}
|
|
#endif
|
|
return null;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Return the first prefab that exactly matches the given name from within the current project
|
|
/// </summary>
|
|
/// <param name="name">Asset to search for</param>
|
|
/// <returns>Returns the prefab or null</returns>
|
|
public static GameObject GetAssetPrefab(string name)
|
|
{
|
|
#if UNITY_EDITOR
|
|
string path = GetAssetPath(name, "prefab");
|
|
if (!string.IsNullOrEmpty(path))
|
|
{
|
|
return AssetDatabase.LoadAssetAtPath<GameObject>(path);
|
|
}
|
|
#endif
|
|
return null;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Return the first scriptable that exactly matches the given name from within the current project
|
|
/// </summary>
|
|
/// <param name="name">Asset to search for</param>
|
|
/// <returns>Returns the prefab or null</returns>
|
|
public static ScriptableObject GetAssetScriptableObject(string name)
|
|
{
|
|
#if UNITY_EDITOR
|
|
string path = GetAssetPath(name, "asset");
|
|
if (!string.IsNullOrEmpty(path))
|
|
{
|
|
return AssetDatabase.LoadAssetAtPath<ScriptableObject>(path);
|
|
}
|
|
#endif
|
|
return null;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Return the first texture that exactly matches the given name from within the current project
|
|
/// </summary>
|
|
/// <param name="name">Asset to search for</param>
|
|
/// <returns>Returns the texture or null</returns>
|
|
public static Texture2D GetAssetTexture2D(string name)
|
|
{
|
|
#if UNITY_EDITOR
|
|
string[] assets = AssetDatabase.FindAssets(name, null);
|
|
for (int idx = 0; idx < assets.Length; idx++)
|
|
{
|
|
string path = AssetDatabase.GUIDToAssetPath(assets[idx]);
|
|
if (path.Contains(".jpg") || path.Contains(".psd") || path.Contains(".png"))
|
|
{
|
|
//Make sure its an exact match
|
|
string filename = Path.GetFileNameWithoutExtension(path);
|
|
if (filename == name)
|
|
{
|
|
return AssetDatabase.LoadAssetAtPath<Texture2D>(path);
|
|
}
|
|
}
|
|
}
|
|
#endif
|
|
return null;
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region Image helpers
|
|
|
|
/// <summary>
|
|
/// Make the texture supplied into a normal map
|
|
/// </summary>
|
|
/// <param name="texture">Texture to convert</param>
|
|
public static void MakeTextureNormal(Texture2D texture)
|
|
{
|
|
if (texture == null)
|
|
{
|
|
return;
|
|
}
|
|
#if UNITY_EDITOR
|
|
string assetPath = AssetDatabase.GetAssetPath(texture);
|
|
var tImporter = AssetImporter.GetAtPath(assetPath) as TextureImporter;
|
|
if (tImporter != null && tImporter.textureType != TextureImporterType.NormalMap)
|
|
{
|
|
tImporter.textureType = TextureImporterType.NormalMap;
|
|
tImporter.SaveAndReimport();
|
|
AssetDatabase.Refresh();
|
|
}
|
|
#endif
|
|
}
|
|
|
|
/// <summary>
|
|
/// Make the texture supplied readable
|
|
/// </summary>
|
|
/// <param name="texture">Texture to convert</param>
|
|
public static void MakeTextureReadable(Texture2D texture)
|
|
{
|
|
if (texture == null)
|
|
{
|
|
return;
|
|
}
|
|
#if UNITY_EDITOR
|
|
string assetPath = AssetDatabase.GetAssetPath(texture);
|
|
var tImporter = AssetImporter.GetAtPath(assetPath) as TextureImporter;
|
|
if (tImporter != null && tImporter.isReadable != true)
|
|
{
|
|
tImporter.isReadable = true;
|
|
tImporter.SaveAndReimport();
|
|
AssetDatabase.Refresh();
|
|
}
|
|
#endif
|
|
}
|
|
|
|
/// <summary>
|
|
/// Make the texture supplied uncompressed
|
|
/// </summary>
|
|
/// <param name="texture">Texture to convert</param>
|
|
public static void MakeTextureUncompressed(Texture2D texture)
|
|
{
|
|
if (texture == null)
|
|
{
|
|
return;
|
|
}
|
|
#if UNITY_EDITOR
|
|
string assetPath = AssetDatabase.GetAssetPath(texture);
|
|
var tImporter = AssetImporter.GetAtPath(assetPath) as TextureImporter;
|
|
if (tImporter != null && tImporter.textureCompression != TextureImporterCompression.Uncompressed)
|
|
{
|
|
tImporter.textureCompression = TextureImporterCompression.Uncompressed;
|
|
tImporter.SaveAndReimport();
|
|
AssetDatabase.Refresh();
|
|
}
|
|
#endif
|
|
}
|
|
|
|
/// <summary>
|
|
/// Compress / encode a single layer map file to an image
|
|
/// </summary>
|
|
/// <param name="input">Single layer map in format x,y</param>
|
|
/// <param name="imageName">Output image name - image image index and extension will be added</param>
|
|
/// <param name="exportPNG">True if a png is wanted</param>
|
|
/// <param name="exportJPG">True if a jpg is wanted</param>
|
|
public static void CompressToSingleChannelFileImage(float[,] input, string imageName, TextureFormat imageStorageFormat = Gaia.GaiaConstants.defaultTextureFormat, bool exportPNG = true, bool exportJPG = true)
|
|
{
|
|
int width = input.GetLength(0);
|
|
int height = input.GetLength(1);
|
|
|
|
Texture2D exportTexture = new Texture2D(width, height, imageStorageFormat, false);
|
|
Color pixelColor = new Color();
|
|
pixelColor.a = 1f;
|
|
pixelColor.r = pixelColor.g = pixelColor.b = 0f;
|
|
|
|
for (int x = 0; x < width; x++)
|
|
{
|
|
for (int y = 0; y < height; y++)
|
|
{
|
|
pixelColor.r = pixelColor.b = pixelColor.g = input[x, y];
|
|
exportTexture.SetPixel(x, y, pixelColor);
|
|
}
|
|
}
|
|
|
|
exportTexture.Apply();
|
|
|
|
// Write JPG
|
|
if (exportJPG)
|
|
{
|
|
ExportJPG(imageName, exportTexture);
|
|
}
|
|
|
|
// Write PNG
|
|
if (exportPNG)
|
|
{
|
|
ExportPNG(imageName, exportTexture);
|
|
}
|
|
|
|
//Lose the texture
|
|
DestroyImmediate(exportTexture);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Compress / encode a multi layer map file to an image
|
|
/// </summary>
|
|
/// <param name="input">Multi layer map in format x,y,layer</param>
|
|
/// <param name="imageName">Output image name - image image index and extension will be added</param>
|
|
/// <param name="exportPNG">True if a png is wanted</param>
|
|
/// <param name="exportJPG">True if a jpg is wanted</param>
|
|
public static void CompressToMultiChannelFileImage(float[,,] input, string imageName, TextureFormat imageStorageFormat = Gaia.GaiaConstants.defaultTextureFormat, bool flip = false, bool exportPNG = true, bool exportJPG = true)
|
|
{
|
|
int width = input.GetLength(0);
|
|
int height = input.GetLength(1);
|
|
int layers = input.GetLength(2);
|
|
int images = (layers + 3) / 4;
|
|
|
|
for (int image = 0; image < images; image++)
|
|
{
|
|
Texture2D exportTexture = new Texture2D(width, width, imageStorageFormat, false);
|
|
Color pixelColor = new Color();
|
|
int layer = image * 4;
|
|
|
|
for (int x = 0; x < width; x++)
|
|
{
|
|
for (int y = 0; y < height; y++)
|
|
{
|
|
pixelColor.r = layer < layers ? input[x, y, layer] : 0f;
|
|
pixelColor.g = (layer + 1) < layers ? input[x, y, (layer + 1)] : 0f;
|
|
pixelColor.b = (layer + 2) < layers ? input[x, y, (layer + 2)] : 0f;
|
|
pixelColor.a = (layer + 3) < layers ? input[x, y, (layer + 3)] : 0f;
|
|
if (flip)
|
|
{
|
|
exportTexture.SetPixel(y, x, pixelColor);
|
|
}
|
|
else
|
|
{
|
|
exportTexture.SetPixel(x, y, pixelColor);
|
|
}
|
|
}
|
|
}
|
|
exportTexture.Apply();
|
|
|
|
// Write JPG
|
|
if (exportJPG)
|
|
{
|
|
byte[] jpgBytes = exportTexture.EncodeToJPG();
|
|
PWCommon3.Utils.WriteAllBytes(imageName + image + ".jpg", jpgBytes);
|
|
}
|
|
|
|
// Write PNG
|
|
if (exportPNG)
|
|
{
|
|
byte[] pngBytes = exportTexture.EncodeToPNG();
|
|
PWCommon3.Utils.WriteAllBytes(imageName + image + ".png", pngBytes);
|
|
}
|
|
|
|
//Lose the texture
|
|
DestroyImmediate(exportTexture);
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Compress / encode a multi layer map file to an image
|
|
/// </summary>
|
|
/// <param name="input">Multi layer map in format x,y,layer</param>
|
|
/// <param name="imageName">Output image name - image image index and extension will be added</param>
|
|
/// <param name="exportPNG">True if a png is wanted</param>
|
|
/// <param name="exportJPG">True if a jpg is wanted</param>
|
|
public static void CompressToMultiChannelFileImage(string imageName, HeightMap r, HeightMap g, HeightMap b, HeightMap a, TextureFormat imageStorageFormat, GaiaConstants.ImageFileType imageFileType, float baseLevel, GaiaConstants.GaiaProWaterReflectionsQuality textureResolution = GaiaProWaterReflectionsQuality.Resolution1024)
|
|
{
|
|
int width = 0;
|
|
int height = 0;
|
|
|
|
if (r != null)
|
|
{
|
|
width = r.Width();
|
|
height = r.Depth();
|
|
}
|
|
else if (g != null)
|
|
{
|
|
width = g.Width();
|
|
height = g.Depth();
|
|
}
|
|
else if (b != null)
|
|
{
|
|
width = b.Width();
|
|
height = b.Depth();
|
|
}
|
|
else if (a != null)
|
|
{
|
|
width = a.Width();
|
|
height = a.Depth();
|
|
}
|
|
|
|
if (string.IsNullOrEmpty(imageName))
|
|
{
|
|
Debug.LogError("Cannot write image - no name supplied!");
|
|
return;
|
|
}
|
|
|
|
if (width == 0 || height == 0)
|
|
{
|
|
Debug.LogError("Cannot write image - invalid dimensions : " + width + ", " + height);
|
|
return;
|
|
}
|
|
|
|
Texture2D exportTexture;
|
|
if (imageFileType == ImageFileType.Exr)
|
|
{
|
|
//Assume we are storing a high quality image for stamping
|
|
exportTexture = new Texture2D(width, height, imageStorageFormat, true, true);
|
|
}
|
|
else
|
|
{
|
|
exportTexture = new Texture2D(width, height, imageStorageFormat, true, false);
|
|
}
|
|
|
|
Color pixelColor = new Color();
|
|
for (int x = 0; x < width; x++)
|
|
{
|
|
for (int y = 0; y < height; y++)
|
|
{
|
|
pixelColor.r = r?[x, y] ?? 0f;
|
|
pixelColor.g = g?[x, y] ?? 0f;
|
|
pixelColor.b = b?[x, y] ?? 0f;
|
|
pixelColor.a = a?[x, y] ?? 1f;
|
|
|
|
//Add base level
|
|
//Mathf.Clamp01(pixelColor.r += baseLevel);
|
|
//Mathf.Clamp01(pixelColor.g += baseLevel);
|
|
//Mathf.Clamp01(pixelColor.b += baseLevel);
|
|
//Mathf.Clamp01(pixelColor.a += baseLevel);
|
|
exportTexture.SetPixel(x, y, pixelColor);
|
|
}
|
|
}
|
|
exportTexture.Apply();
|
|
|
|
#if UNITY_2017_1_OR_NEWER
|
|
switch (imageFileType)
|
|
{
|
|
case GaiaConstants.ImageFileType.Jpg:
|
|
byte[] jpgBytes = ImageConversion.EncodeToJPG(exportTexture, 100);
|
|
PWCommon3.Utils.WriteAllBytes(imageName + ".jpg", jpgBytes);
|
|
break;
|
|
case GaiaConstants.ImageFileType.Png:
|
|
byte[] pngBytes = ImageConversion.EncodeToPNG(exportTexture);
|
|
PWCommon3.Utils.WriteAllBytes(imageName + ".png", pngBytes);
|
|
break;
|
|
case GaiaConstants.ImageFileType.Exr:
|
|
byte[] exrBytes = ImageConversion.EncodeToEXR(exportTexture, Texture2D.EXRFlags.CompressZIP);
|
|
PWCommon3.Utils.WriteAllBytes(imageName + ".exr", exrBytes);
|
|
break;
|
|
}
|
|
#else
|
|
switch (imageFileType)
|
|
{
|
|
case GaiaConstants.ImageFileType.Jpg:
|
|
byte[] jpgBytes = exportTexture.EncodeToJPG();
|
|
PWCommon1.Utils.WriteAllBytes(imageName + ".jpg", jpgBytes);
|
|
break;
|
|
case GaiaConstants.ImageFileType.Png:
|
|
byte[] pngBytes = exportTexture.EncodeToPNG();
|
|
PWCommon1.Utils.WriteAllBytes(imageName + ".png", pngBytes);
|
|
break;
|
|
case GaiaConstants.ImageFileType.Exr:
|
|
byte[] exrBytes = exportTexture.EncodeToEXR(Texture2D.EXRFlags.CompressZIP);
|
|
PWCommon1.Utils.WriteAllBytes(imageName + ".exr", exrBytes);
|
|
break;
|
|
}
|
|
#endif
|
|
|
|
#if UNITY_EDITOR
|
|
AssetDatabase.Refresh();
|
|
#endif
|
|
|
|
//Lose the texture
|
|
DestroyImmediate(exportTexture);
|
|
}
|
|
/// <summary>
|
|
/// Compress / encode a multi layer map file to an image
|
|
/// </summary>
|
|
/// <param name="input">Multi layer map in format x,y,layer</param>
|
|
/// <param name="imageName">Output image name - image image index and extension will be added</param>
|
|
/// <param name="exportPNG">True if a png is wanted</param>
|
|
/// <param name="exportJPG">True if a jpg is wanted</param>
|
|
public static void CompressToMultiChannelFileImage(string imageName, HeightMap r, HeightMap g, HeightMap b, HeightMap a, TextureFormat imageStorageFormat, GaiaConstants.ImageFileType imageFileType, GaiaConstants.GaiaProWaterReflectionsQuality textureResolution = GaiaProWaterReflectionsQuality.Resolution1024)
|
|
{
|
|
int width = 0;
|
|
int height = 0;
|
|
|
|
if (r != null)
|
|
{
|
|
width = r.Width();
|
|
height = r.Depth();
|
|
}
|
|
else if (g != null)
|
|
{
|
|
width = g.Width();
|
|
height = g.Depth();
|
|
}
|
|
else if (b != null)
|
|
{
|
|
width = b.Width();
|
|
height = b.Depth();
|
|
}
|
|
else if (a != null)
|
|
{
|
|
width = a.Width();
|
|
height = a.Depth();
|
|
}
|
|
|
|
if (string.IsNullOrEmpty(imageName))
|
|
{
|
|
Debug.LogError("Cannot write image - no name supplied!");
|
|
return;
|
|
}
|
|
|
|
if (width == 0 || height == 0)
|
|
{
|
|
Debug.LogError("Cannot write image - invalid dimensions : " + width + ", " + height);
|
|
return;
|
|
}
|
|
|
|
Texture2D exportTexture;
|
|
if (imageFileType == ImageFileType.Exr)
|
|
{
|
|
//Assume we are storing a high quality image for stamping
|
|
exportTexture = new Texture2D(width, height, imageStorageFormat, true, true);
|
|
}
|
|
else
|
|
{
|
|
exportTexture = new Texture2D(width, height, imageStorageFormat, true, false);
|
|
}
|
|
|
|
Color pixelColor = new Color();
|
|
for (int x = 0; x < width; x++)
|
|
{
|
|
for (int y = 0; y < height; y++)
|
|
{
|
|
pixelColor.r = r != null ? r[x, y] : 0f;
|
|
pixelColor.g = g != null ? g[x, y] : 0f;
|
|
pixelColor.b = b != null ? b[x, y] : 0f;
|
|
pixelColor.a = a != null ? a[x, y] : 1f;
|
|
exportTexture.SetPixel(x, y, pixelColor);
|
|
}
|
|
}
|
|
exportTexture.Apply();
|
|
|
|
#if UNITY_2017_1_OR_NEWER
|
|
switch (imageFileType)
|
|
{
|
|
case GaiaConstants.ImageFileType.Jpg:
|
|
byte[] jpgBytes = ImageConversion.EncodeToJPG(exportTexture, 100);
|
|
PWCommon3.Utils.WriteAllBytes(imageName + ".jpg", jpgBytes);
|
|
break;
|
|
case GaiaConstants.ImageFileType.Png:
|
|
byte[] pngBytes = ImageConversion.EncodeToPNG(exportTexture);
|
|
PWCommon3.Utils.WriteAllBytes(imageName + ".png", pngBytes);
|
|
break;
|
|
case GaiaConstants.ImageFileType.Exr:
|
|
byte[] exrBytes = ImageConversion.EncodeToEXR(exportTexture, Texture2D.EXRFlags.CompressZIP);
|
|
PWCommon3.Utils.WriteAllBytes(imageName + ".exr", exrBytes);
|
|
break;
|
|
}
|
|
#else
|
|
switch (imageFileType)
|
|
{
|
|
case GaiaConstants.ImageFileType.Jpg:
|
|
byte[] jpgBytes = exportTexture.EncodeToJPG();
|
|
PWCommon1.Utils.WriteAllBytes(imageName + ".jpg", jpgBytes);
|
|
break;
|
|
case GaiaConstants.ImageFileType.Png:
|
|
byte[] pngBytes = exportTexture.EncodeToPNG();
|
|
PWCommon1.Utils.WriteAllBytes(imageName + ".png", pngBytes);
|
|
break;
|
|
case GaiaConstants.ImageFileType.Exr:
|
|
byte[] exrBytes = exportTexture.EncodeToEXR(Texture2D.EXRFlags.CompressZIP);
|
|
PWCommon1.Utils.WriteAllBytes(imageName + ".exr", exrBytes);
|
|
break;
|
|
}
|
|
#endif
|
|
|
|
#if UNITY_EDITOR
|
|
AssetDatabase.Refresh();
|
|
#endif
|
|
|
|
//Lose the texture
|
|
DestroyImmediate(exportTexture);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Convert the supplied texture to an array based on grayscale value
|
|
/// </summary>
|
|
/// <param name="texture">Input texture - must be read enabled</param>
|
|
/// <returns>Texture as grayscale array</returns>
|
|
public static float[,] ConvertTextureToArray(Texture2D texture)
|
|
{
|
|
float[,] array = new float[texture.width, texture.height];
|
|
for (int x = 0; x < texture.width; x++)
|
|
{
|
|
for (int z = 0; z < texture.height; z++)
|
|
{
|
|
array[x, z] = texture.GetPixel(x, z).grayscale;
|
|
}
|
|
}
|
|
return array;
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
/// Decompress a single channel from the provided file into a float array.
|
|
/// </summary>
|
|
/// <param name="fileName">File to process</param>
|
|
/// <param name="channelR">Take data from R channel</param>
|
|
/// <param name="channelG">Take data from G channel</param>
|
|
/// <param name="channelB">Take data from B channel</param>
|
|
/// <param name="channelA">Take data from A channel</param>
|
|
/// <returns>Array of float values from the selected channel</returns>
|
|
public static float[,] DecompressFromSingleChannelFileImage(string fileName, int width, int height, TextureFormat imageStorageFormat = Gaia.GaiaConstants.defaultTextureFormat, bool channelR = true, bool channelG = false, bool channelB = false, bool channelA = false)
|
|
{
|
|
float[,] retArray = null;
|
|
|
|
if (System.IO.File.Exists(fileName))
|
|
{
|
|
byte[] bytes = PWCommon3.Utils.ReadAllBytes(fileName);
|
|
Texture2D importTexture = new Texture2D(width, height, imageStorageFormat, false);
|
|
importTexture.LoadImage(bytes);
|
|
retArray = new float[width, height];
|
|
for (int x = 0; x < width; x++)
|
|
{
|
|
for (int y = 0; y < height; y++)
|
|
{
|
|
retArray[x, y] = importTexture.GetPixel(x, y).r;
|
|
}
|
|
}
|
|
//Lose the texture
|
|
DestroyImmediate(importTexture);
|
|
}
|
|
else
|
|
{
|
|
Debug.LogError("Unable to find " + fileName);
|
|
}
|
|
return retArray;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Decompress a single channel from the provided file into a float array.
|
|
/// </summary>
|
|
/// <param name="fileName">File to process</param>
|
|
/// <param name="channelR">Take data from R channel</param>
|
|
/// <param name="channelG">Take data from G channel</param>
|
|
/// <param name="channelB">Take data from B channel</param>
|
|
/// <param name="channelA">Take data from A channel</param>
|
|
/// <returns>Array of float values from the selected channel</returns>
|
|
public static float[,] DecompressFromSingleChannelTexture(Texture2D importTexture, bool channelR = true, bool channelG = false, bool channelB = false, bool channelA = false)
|
|
{
|
|
if ((importTexture == null) || importTexture.width <= 0 || importTexture.height <= 0)
|
|
{
|
|
Debug.LogError("Unable to import from texture");
|
|
return null;
|
|
}
|
|
|
|
float[,] retArray = new float[importTexture.width, importTexture.height];
|
|
|
|
if (channelR)
|
|
{
|
|
for (int x = 0; x < importTexture.width; x++)
|
|
{
|
|
for (int y = 0; y < importTexture.height; y++)
|
|
{
|
|
retArray[x, y] = importTexture.GetPixel(x, y).r;
|
|
}
|
|
}
|
|
}
|
|
else if (channelG)
|
|
{
|
|
for (int x = 0; x < importTexture.width; x++)
|
|
{
|
|
for (int y = 0; y < importTexture.height; y++)
|
|
{
|
|
retArray[x, y] = importTexture.GetPixel(x, y).g;
|
|
}
|
|
}
|
|
}
|
|
else if (channelB)
|
|
{
|
|
for (int x = 0; x < importTexture.width; x++)
|
|
{
|
|
for (int y = 0; y < importTexture.height; y++)
|
|
{
|
|
retArray[x, y] = importTexture.GetPixel(x, y).b;
|
|
}
|
|
}
|
|
}
|
|
if (channelA)
|
|
{
|
|
for (int x = 0; x < importTexture.width; x++)
|
|
{
|
|
for (int y = 0; y < importTexture.height; y++)
|
|
{
|
|
retArray[x, y] = importTexture.GetPixel(x, y).a;
|
|
}
|
|
}
|
|
}
|
|
return retArray;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Export a texture to jpg
|
|
/// </summary>
|
|
/// <param name="fileName">File name to us - will have .jpg appended</param>
|
|
/// <param name="texture">Texture source</param>
|
|
public static void ExportJPG(string fileName, Texture2D texture)
|
|
{
|
|
byte[] bytes = texture.EncodeToJPG();
|
|
PWCommon3.Utils.WriteAllBytes(fileName + ".jpg", bytes);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Export a texture to png
|
|
/// </summary>
|
|
/// <param name="fileName">File name to us - will have .png appended</param>
|
|
/// <param name="texture">Texture source</param>
|
|
public static void ExportPNG(string fileName, Texture2D texture)
|
|
{
|
|
byte[] bytes = texture.EncodeToPNG();
|
|
PWCommon3.Utils.WriteAllBytes(fileName + ".png", bytes);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Will import the raw file provided - it assumes that it is in a square 16 bit PC format
|
|
/// </summary>
|
|
/// <param name="fileName">Fully qualified file name</param>
|
|
/// <returns>File contents or null</returns>
|
|
public static float[,] LoadRawFile(string fileName)
|
|
{
|
|
if (!System.IO.File.Exists(fileName))
|
|
{
|
|
Debug.LogError("Could not locate heightmap file : " + fileName);
|
|
return null;
|
|
}
|
|
|
|
float[,] heights = null;
|
|
using (FileStream fileStream = File.OpenRead(fileName))
|
|
{
|
|
using (BinaryReader br = new BinaryReader(fileStream))
|
|
{
|
|
int mapSize = Mathf.CeilToInt(Mathf.Sqrt(fileStream.Length / 2));
|
|
heights = new float[mapSize, mapSize];
|
|
for (int x = 0; x < mapSize; x++)
|
|
{
|
|
for (int y = 0; y < mapSize; y++)
|
|
{
|
|
heights[x, y] = (float)(br.ReadUInt16() / 65535.0f);
|
|
}
|
|
}
|
|
}
|
|
fileStream.Close();
|
|
}
|
|
|
|
return heights;
|
|
}
|
|
|
|
|
|
#endregion
|
|
|
|
#region Mesh helpers
|
|
|
|
/// <summary>
|
|
/// Fucntion used to fix prefabs layers
|
|
/// </summary>
|
|
/// <param name="prefabs"></param>
|
|
public static void FixPrefabLayers(List<string> paths)
|
|
{
|
|
#if UNITY_EDITOR
|
|
if (paths.Count < 1)
|
|
{
|
|
Debug.LogWarning(("No prefab paths provided"));
|
|
}
|
|
|
|
try
|
|
{
|
|
var SerializedObjectTagManager =
|
|
new SerializedObject(AssetDatabase.LoadAllAssetsAtPath("ProjectSettings/TagManager.asset")[0]);
|
|
if (SerializedObjectTagManager != null)
|
|
{
|
|
SerializedProperty serializedProperties = SerializedObjectTagManager.FindProperty("layers");
|
|
if (serializedProperties != null)
|
|
{
|
|
//Add layers if missing
|
|
string[] layers = UnityEditorInternal.InternalEditorUtility.layers;
|
|
if (layers.Length > 0)
|
|
{
|
|
bool addVFX = true;
|
|
bool addObjectSmall = true;
|
|
bool addObjectMedium = true;
|
|
bool addObjectLarge = true;
|
|
foreach (string name in layers)
|
|
{
|
|
if (name == GaiaPrefabUtility.m_vfxLayerName)
|
|
{
|
|
addVFX = false;
|
|
}
|
|
|
|
if (name == GaiaPrefabUtility.m_objectSmallLayerName)
|
|
{
|
|
addObjectSmall = false;
|
|
}
|
|
|
|
if (name == GaiaPrefabUtility.m_objectMediumLayerName)
|
|
{
|
|
addObjectMedium = false;
|
|
}
|
|
|
|
if (name == GaiaPrefabUtility.m_objectLargeLayerName)
|
|
{
|
|
addObjectLarge = false;
|
|
}
|
|
}
|
|
|
|
for (int i = 8; i < 31; i++)
|
|
{
|
|
SerializedProperty property = serializedProperties.GetArrayElementAtIndex(i);
|
|
|
|
if (property.stringValue.Length < 1)
|
|
{
|
|
if (addVFX)
|
|
{
|
|
property.stringValue = GaiaPrefabUtility.m_vfxLayerName;
|
|
addVFX = false;
|
|
continue;
|
|
}
|
|
|
|
if (addObjectSmall)
|
|
{
|
|
property.stringValue = GaiaPrefabUtility.m_objectSmallLayerName;
|
|
addObjectSmall = false;
|
|
continue;
|
|
}
|
|
|
|
if (addObjectMedium)
|
|
{
|
|
property.stringValue = GaiaPrefabUtility.m_objectMediumLayerName;
|
|
addObjectMedium = false;
|
|
continue;
|
|
}
|
|
|
|
if (addObjectLarge)
|
|
{
|
|
property.stringValue = GaiaPrefabUtility.m_objectLargeLayerName;
|
|
addObjectLarge = false;
|
|
continue;
|
|
}
|
|
}
|
|
|
|
}
|
|
}
|
|
|
|
SerializedObjectTagManager.ApplyModifiedProperties();
|
|
for (int i = 0; i < paths.Count; i++)
|
|
{
|
|
GameObject loadedPrefab = PrefabUtility.LoadPrefabContents(paths[i]);
|
|
ProgressBar.Show(ProgressBarPriority.Maintenance, "Updating Prefab Layers", "Updating Layer", i, paths.Count, true, false);
|
|
if (loadedPrefab != null)
|
|
{
|
|
int targetLayer = -99;
|
|
|
|
if (loadedPrefab.layer == GaiaPrefabUtility.m_vfxLayerIndex)
|
|
{
|
|
targetLayer = LayerMask.NameToLayer(GaiaPrefabUtility.m_vfxLayerName);
|
|
}
|
|
else if (loadedPrefab.layer == GaiaPrefabUtility.m_objectSmallLayerIndex)
|
|
{
|
|
targetLayer = LayerMask.NameToLayer(GaiaPrefabUtility.m_objectSmallLayerName);
|
|
}
|
|
else if (loadedPrefab.layer == GaiaPrefabUtility.m_objectMediumLayerIndex)
|
|
{
|
|
targetLayer = LayerMask.NameToLayer(GaiaPrefabUtility.m_objectMediumLayerName);
|
|
}
|
|
else if (loadedPrefab.layer == GaiaPrefabUtility.m_objectLargeLayerIndex)
|
|
{
|
|
targetLayer = LayerMask.NameToLayer(GaiaPrefabUtility.m_objectLargeLayerName);
|
|
|
|
}
|
|
if (targetLayer != -99)
|
|
{
|
|
loadedPrefab.layer = targetLayer;
|
|
foreach (Transform t in loadedPrefab.transform)
|
|
{
|
|
t.gameObject.layer = targetLayer;
|
|
}
|
|
PrefabUtility.SaveAsPrefabAsset(loadedPrefab, paths[i]);
|
|
}
|
|
}
|
|
|
|
PrefabUtility.UnloadPrefabContents(loadedPrefab);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
Debug.LogError(("SerializedProperty is missing from TagManager.asset"));
|
|
}
|
|
}
|
|
else
|
|
{
|
|
Debug.LogError(("Missing TagManager.asset"));
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
Debug.LogError("Error while updating prefab layers. Message: " + ex.Message + " Stack Trace: " +
|
|
ex.StackTrace);
|
|
}
|
|
finally
|
|
{
|
|
ProgressBar.Clear(ProgressBarPriority.Maintenance);
|
|
}
|
|
#endif
|
|
}
|
|
|
|
/// <summary>
|
|
/// Create a mesh for the heightmap
|
|
/// </summary>
|
|
/// <param name="heightmap"></param>
|
|
/// <param name="targetSize"></param>
|
|
/// <param name="resolution"></param>
|
|
/// <returns></returns>
|
|
public static Mesh CreateMesh(float[,] heightmap, Vector3 targetSize)
|
|
{
|
|
//Need to sample these to not blow unity mesh sizes
|
|
int width = heightmap.GetLength(0);
|
|
int height = heightmap.GetLength(1);
|
|
int targetRes = 1;
|
|
|
|
Vector3 targetOffset = Vector3.zero - (targetSize / 2f);
|
|
Vector2 uvScale = new Vector2(1.0f / (width - 1), 1.0f / (height - 1));
|
|
|
|
//Choose best possible target res
|
|
for (targetRes = 1; targetRes < 100; targetRes++)
|
|
{
|
|
if (((width / targetRes) * (height / targetRes)) < 65000)
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
|
|
targetSize = new Vector3(targetSize.x / (width - 1) * targetRes, targetSize.y, targetSize.z / (height - 1) * targetRes);
|
|
width = (width - 1) / targetRes + 1;
|
|
height = (height - 1) / targetRes + 1;
|
|
|
|
Vector3[] vertices = new Vector3[width * height];
|
|
Vector2[] uvs = new Vector2[width * height];
|
|
Vector3[] normals = new Vector3[width * height];
|
|
Color[] colors = new Color[width * height];
|
|
int[] triangles = new int[(width - 1) * (height - 1) * 6];
|
|
|
|
// Build vertices and UVs
|
|
for (int y = 0; y < height; y++)
|
|
{
|
|
for (int x = 0; x < width; x++)
|
|
{
|
|
colors[y * width + x] = Color.black;
|
|
normals[y * width + x] = Vector3.up;
|
|
//vertices[y * w + x] = Vector3.Scale(targetSize, new Vector3(-y, heightmap[x * tRes, y * tRes], x)) + targetOffset;
|
|
vertices[y * width + x] = Vector3.Scale(targetSize, new Vector3(x, heightmap[x * targetRes, y * targetRes], y)) + targetOffset;
|
|
uvs[y * width + x] = Vector2.Scale(new Vector2(x * targetRes, y * targetRes), uvScale);
|
|
}
|
|
}
|
|
|
|
// Build triangle indices: 3 indices into vertex array for each triangle
|
|
int index = 0;
|
|
for (int y = 0; y < height - 1; y++)
|
|
{
|
|
for (int x = 0; x < width - 1; x++)
|
|
{
|
|
triangles[index++] = (y * width) + x;
|
|
triangles[index++] = ((y + 1) * width) + x;
|
|
triangles[index++] = (y * width) + x + 1;
|
|
triangles[index++] = ((y + 1) * width) + x;
|
|
triangles[index++] = ((y + 1) * width) + x + 1;
|
|
triangles[index++] = (y * width) + x + 1;
|
|
}
|
|
}
|
|
|
|
Mesh mesh = new Mesh();
|
|
|
|
mesh.vertices = vertices;
|
|
mesh.colors = colors;
|
|
mesh.normals = normals;
|
|
mesh.uv = uvs;
|
|
mesh.triangles = triangles;
|
|
mesh.RecalculateBounds();
|
|
mesh.RecalculateNormals();
|
|
return mesh;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Return the bounds of both the object and any colliders it has
|
|
/// </summary>
|
|
/// <param name="go">Game object to check</param>
|
|
public static Bounds GetBounds(GameObject go)
|
|
{
|
|
Bounds bounds = new Bounds(go.transform.position, Vector3.zero);
|
|
foreach (Renderer r in go.GetComponentsInChildren<Renderer>())
|
|
{
|
|
bounds.Encapsulate(r.bounds);
|
|
}
|
|
foreach (Collider c in go.GetComponentsInChildren<Collider>())
|
|
{
|
|
bounds.Encapsulate(c.bounds);
|
|
}
|
|
return bounds;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Calculate a normal map for a terrain
|
|
/// </summary>
|
|
/// <returns>Normals for the terrain in a Texture 2D</returns>
|
|
public static Texture2D CalculateNormals(Terrain terrain)
|
|
{
|
|
int width = terrain.terrainData.heightmapResolution;
|
|
int height = terrain.terrainData.heightmapResolution;
|
|
float ux = 1.0f / (width - 1.0f);
|
|
float uy = 1.0f / (height - 1.0f);
|
|
float terrainHeight = width / 2f;
|
|
float scaleX = terrainHeight / (float)width;
|
|
float scaleY = terrainHeight / (float)height;
|
|
float[] heights = new float[width * height];
|
|
Buffer.BlockCopy(terrain.terrainData.GetHeights(0, 0, width, height), 0, heights, 0, heights.Length * sizeof(float));
|
|
Texture2D normalMap = new Texture2D(width, height, TextureFormat.RGBAFloat, false, true);
|
|
|
|
for (int y = 0; y < height; y++)
|
|
{
|
|
for (int x = 0; x < width; x++)
|
|
{
|
|
int xp1 = (x == width - 1) ? x : x + 1;
|
|
int xn1 = (x == 0) ? x : x - 1;
|
|
|
|
int yp1 = (y == height - 1) ? y : y + 1;
|
|
int yn1 = (y == 0) ? y : y - 1;
|
|
|
|
float l = heights[xn1 + y * width] * scaleX;
|
|
float r = heights[xp1 + y * width] * scaleX;
|
|
|
|
float b = heights[x + yn1 * width] * scaleY;
|
|
float t = heights[x + yp1 * width] * scaleY;
|
|
|
|
float dx = (r - l) / (2.0f * ux);
|
|
float dy = (t - b) / (2.0f * uy);
|
|
|
|
Vector3 normal;
|
|
normal.x = -dx;
|
|
normal.y = -dy;
|
|
normal.z = 1;
|
|
normal.Normalize();
|
|
|
|
Color pixel;
|
|
pixel.r = normal.x * 0.5f + 0.5f;
|
|
pixel.g = normal.y * 0.5f + 0.5f;
|
|
pixel.b = normal.z;
|
|
pixel.a = 1.0f;
|
|
|
|
normalMap.SetPixel(x, y, pixel);
|
|
}
|
|
}
|
|
normalMap.Apply();
|
|
return normalMap;
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region Direction helpers
|
|
|
|
/// <summary>
|
|
/// Rotate a direction vector left 90% around X axis
|
|
/// </summary>
|
|
/// <param name="input">Direction vector</param>
|
|
/// <returns>Rotated direction vector</returns>
|
|
Vector3 Rotate90LeftXAxis(Vector3 input)
|
|
{
|
|
return new Vector3(input.x, -input.z, input.y);
|
|
}
|
|
|
|
|
|
|
|
/// <summary>
|
|
/// Rotate a direction vector right 90% around X axis
|
|
/// </summary>
|
|
/// <param name="input">Direction vector</param>
|
|
/// <returns>Rotated direction vector</returns>
|
|
Vector3 Rotate90RightXAxis(Vector3 input)
|
|
{
|
|
return new Vector3(input.x, input.z, -input.y);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Rotate a direction vector left 90% around Y axis
|
|
/// </summary>
|
|
/// <param name="input">Direction vector</param>
|
|
/// <returns>Rotated direction vector</returns>
|
|
Vector3 Rotate90LeftYAxis(Vector3 input)
|
|
{
|
|
return new Vector3(-input.z, input.y, input.x);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Rotate a direction vector right 90% around Y axis
|
|
/// </summary>
|
|
/// <param name="input">Direction vector</param>
|
|
/// <returns>Rotated direction vector</returns>
|
|
Vector3 Rotate90RightYAxis(Vector3 input)
|
|
{
|
|
return new Vector3(input.z, input.y, -input.x);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Rotate a direction vector left 90% around Z axis
|
|
/// </summary>
|
|
/// <param name="input">Direction vector</param>
|
|
/// <returns>Rotated direction vector</returns>
|
|
Vector3 Rotate90LeftZAxis(Vector3 input)
|
|
{
|
|
return new Vector3(input.y, -input.x, input.z);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Rotate a direction vector right 90% around Y axis
|
|
/// </summary>
|
|
/// <param name="input">Direction vector</param>
|
|
/// <returns>Rotated direction vector</returns>
|
|
Vector3 Rotate90RightZAxis(Vector3 input)
|
|
{
|
|
return new Vector3(-input.y, input.x, input.z);
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region Math helpers
|
|
|
|
/// <summary>
|
|
/// Return true if the values are approximately equal
|
|
/// </summary>
|
|
/// <param name="a">Parameter A</param>
|
|
/// <param name="b">Parameter B</param>
|
|
/// <param name="threshold">Threshold to test for</param>
|
|
/// <returns>True if approximately equal</returns>
|
|
public static bool Math_ApproximatelyEqual(float a, float b, float threshold)
|
|
{
|
|
|
|
if (a == b || Mathf.Abs(a - b) < threshold)
|
|
{
|
|
return true;
|
|
}
|
|
else
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Return true if the values are approximately equal
|
|
/// </summary>
|
|
/// <param name="a">Parameter A</param>
|
|
/// <param name="b">Parameter B</param>
|
|
/// <returns>True if approximately equal</returns>
|
|
public static bool Math_ApproximatelyEqual(float a, float b)
|
|
{
|
|
return Math_ApproximatelyEqual(a, b, float.Epsilon);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Return true if the value is a power of 2
|
|
/// </summary>
|
|
/// <param name="value">Value to be checked</param>
|
|
/// <returns>True if a power of 2</returns>
|
|
public static bool Math_IsPowerOf2(int value)
|
|
{
|
|
return (value & (value - 1)) == 0;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Returned value clamped in range of min to max
|
|
/// </summary>
|
|
/// <param name="min">Min value</param>
|
|
/// <param name="max">Max value</param>
|
|
/// <param name="value">Value to check</param>
|
|
/// <returns>Clamped value</returns>
|
|
public static float Math_Clamp(float min, float max, float value)
|
|
{
|
|
if (value < min)
|
|
{
|
|
return min;
|
|
}
|
|
if (value > max)
|
|
{
|
|
return max;
|
|
}
|
|
return value;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Return mod of value
|
|
/// </summary>
|
|
/// <param name="value">Value</param>
|
|
/// <param name="mod">Mod value</param>
|
|
/// <returns>Mode of value</returns>
|
|
public static float Math_Modulo(float value, float mod)
|
|
{
|
|
return value - mod * (float)Math.Floor(value / mod);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Return mod of value
|
|
/// </summary>
|
|
/// <param name="value">Value</param>
|
|
/// <param name="mod">Mod value</param>
|
|
/// <returns>Mode of value</returns>
|
|
public static int Math_Modulo(int value, int mod)
|
|
{
|
|
return (int)(value - mod * (float)Math.Floor((float)value / mod));
|
|
}
|
|
|
|
/// <summary>
|
|
/// Linear interpolation between two values
|
|
/// </summary>
|
|
/// <param name="value1">Value 1</param>
|
|
/// <param name="value2">Value 2</param>
|
|
/// <param name="fraction">Fraction</param>
|
|
/// <returns></returns>
|
|
public static float Math_InterpolateLinear(float value1, float value2, float fraction)
|
|
{
|
|
return value1 * (1f - fraction) + value2 * fraction;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Smooth interpolation between two values
|
|
/// </summary>
|
|
/// <param name="value1">Value 1</param>
|
|
/// <param name="value2">Value 2</param>
|
|
/// <param name="fraction">Fraction</param>
|
|
/// <returns></returns>
|
|
public static float Math_InterpolateSmooth(float value1, float value2, float fraction)
|
|
{
|
|
if (fraction < 0.5f)
|
|
{
|
|
fraction = 2f * fraction * fraction;
|
|
}
|
|
else
|
|
{
|
|
fraction = 1f - 2f * (fraction - 1f) * (fraction - 1f);
|
|
}
|
|
return value1 * (1f - fraction) + value2 * fraction;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Calculate the distance between two points
|
|
/// </summary>
|
|
/// <param name="x1">X1</param>
|
|
/// <param name="y1">Y1</param>
|
|
/// <param name="x2">X2</param>
|
|
/// <param name="y2">Y2</param>
|
|
/// <returns></returns>
|
|
public static float Math_Distance(float x1, float y1, float x2, float y2)
|
|
{
|
|
return Mathf.Sqrt(((x1 - x2) * (x1 - x2)) + ((y1 - y2) * (y1 - y2)));
|
|
}
|
|
|
|
public static float Math_InterpolateSmooth2(float v1, float v2, float fraction)
|
|
{
|
|
float fraction2 = fraction * fraction;
|
|
fraction = 3 * fraction2 - 2f * fraction * fraction2;
|
|
return v1 * (1f - fraction) + v2 * fraction;
|
|
}
|
|
|
|
public static float Math_InterpolateCubic(float v0, float v1, float v2, float v3, float fraction)
|
|
{
|
|
float p = (v3 - v2) - (v0 - v1);
|
|
float q = (v0 - v1) - p;
|
|
float r = v2 - v0;
|
|
float fraction2 = fraction * fraction;
|
|
return p * fraction * fraction2 + q * fraction2 + r * fraction + v1;
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
/// Rotate the point around the pivot - used to handle rotation
|
|
/// </summary>
|
|
/// <param name="point">Point to move</param>
|
|
/// <param name="pivot">Pivot</param>
|
|
/// <param name="angle">Angle to pivot</param>
|
|
/// <returns>New location</returns>
|
|
public static Vector3 RotatePointAroundPivot(Vector3 point, Vector3 pivot, Vector3 angle)
|
|
{
|
|
Vector3 dir = point - pivot;
|
|
dir = Quaternion.Euler(angle) * dir;
|
|
point = dir + pivot;
|
|
return point;
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
/// Outputs a Render texture as a .png file for debug purposes
|
|
/// </summary>
|
|
/// <param name="path">The path to write to, including filename ending in .png</param>
|
|
/// <param name="sourceRenderTexture">The render texture to export</param>
|
|
public static void DebugWriteRenderTexture(string path, RenderTexture sourceRenderTexture)
|
|
{
|
|
RenderTexture origTex = RenderTexture.active;
|
|
RenderTexture.active = sourceRenderTexture;
|
|
Texture2D exportTexture = new Texture2D(RenderTexture.active.width, RenderTexture.active.height, TextureFormat.RFloat, false, true);
|
|
exportTexture.ReadPixels(new Rect(0, 0, RenderTexture.active.width, RenderTexture.active.height), 0, 0);
|
|
exportTexture.Apply();
|
|
byte[] exrBytes = ImageConversion.EncodeToPNG(exportTexture);//, Texture2D.EXRFlags.CompressZIP);
|
|
PWCommon3.Utils.WriteAllBytes(path, exrBytes);
|
|
RenderTexture.active = origTex;
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region Programming helpers
|
|
|
|
/// <summary>
|
|
/// Copies all fields from one object to the other, as long as they are from the same type.
|
|
/// </summary>
|
|
/// <param name="sourceOBJ">The source.</param>
|
|
/// <param name="destOBJ">The destination.</param>
|
|
public static void CopyFields(object sourceOBJ, object destOBJ)
|
|
{
|
|
|
|
if (sourceOBJ == null || destOBJ == null)
|
|
{
|
|
Debug.LogError("Error while copying object properties, source / destination not filled!");
|
|
return;
|
|
}
|
|
|
|
Type typeDest = destOBJ.GetType();
|
|
Type typeSrc = sourceOBJ.GetType();
|
|
|
|
if (typeSrc != typeDest)
|
|
{
|
|
Debug.LogError("Type mismatch when trying to copy fields");
|
|
}
|
|
|
|
|
|
FieldInfo[] srcFields = typeSrc.GetFields();
|
|
foreach (FieldInfo srcField in srcFields)
|
|
{
|
|
FieldInfo targetField = typeDest.GetField(srcField.Name);
|
|
if (targetField == null)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
//Check for common unity reference types to create a deep copy of the object whose fields we are copying.
|
|
//if-else chain for the sake of type safety
|
|
if (srcField.FieldType == typeof(Gradient))
|
|
{
|
|
Gradient newGradient = new Gradient();
|
|
GradientAlphaKey[] sourceAlphaKeys = ((Gradient)srcField.GetValue(sourceOBJ)).alphaKeys;
|
|
GradientAlphaKey[] targetAlphaKeys = new GradientAlphaKey[sourceAlphaKeys.Length];
|
|
for (int i = 0; i < sourceAlphaKeys.Length; i++)
|
|
{
|
|
targetAlphaKeys[i].alpha = sourceAlphaKeys[i].alpha;
|
|
targetAlphaKeys[i].time = sourceAlphaKeys[i].time;
|
|
}
|
|
GradientColorKey[] sourceColorKeys= ((Gradient)srcField.GetValue(sourceOBJ)).colorKeys;
|
|
GradientColorKey[] targetColorKeys = new GradientColorKey[sourceColorKeys.Length];
|
|
for (int i = 0; i < sourceColorKeys.Length; i++)
|
|
{
|
|
targetColorKeys[i].color = new Color(sourceColorKeys[i].color.r, sourceColorKeys[i].color.g, sourceColorKeys[i].color.b, sourceColorKeys[i].color.a);
|
|
targetColorKeys[i].time = sourceColorKeys[i].time;
|
|
}
|
|
newGradient.mode = ((Gradient)srcField.GetValue(sourceOBJ)).mode;
|
|
newGradient.SetKeys(targetColorKeys,targetAlphaKeys);
|
|
targetField.SetValue(destOBJ, newGradient);
|
|
}
|
|
else if(srcField.FieldType == typeof(AnimationCurve))
|
|
{
|
|
targetField.SetValue(destOBJ, new AnimationCurve(((AnimationCurve)srcField.GetValue(sourceOBJ)).keys));
|
|
}
|
|
else if (srcField.FieldType == typeof(Color))
|
|
{
|
|
Color sourceColor = ((Color)srcField.GetValue(sourceOBJ));
|
|
targetField.SetValue(destOBJ, new Color(sourceColor.r, sourceColor.g, sourceColor.b, sourceColor.a));
|
|
}
|
|
else
|
|
{
|
|
targetField.SetValue(destOBJ, srcField.GetValue(sourceOBJ));
|
|
}
|
|
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Returns the order number of an enum (this is NOT the enum int value, but the position in the definition of possible enum values)
|
|
/// </summary>
|
|
/// <param name="State"></param>
|
|
/// <returns></returns>
|
|
public static int GetEnumOrder<T>(T enumValue) where T : Enum
|
|
{
|
|
return Enum.GetValues(typeof(T)).Cast<T>().Select((x, i) => new { item = x, index = i }).Single(x => (Enum)x.item == (Enum)enumValue).index;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Perform a deep Copy of the object.
|
|
/// </summary>
|
|
/// <typeparam name="T">The type of object being copied.</typeparam>
|
|
/// <param name="source">The object instance to copy.</param>
|
|
/// <returns>The copied object.</returns>
|
|
public static T Clone<T>(T source)
|
|
{
|
|
if (!typeof(T).IsSerializable)
|
|
{
|
|
throw new ArgumentException("The type must be serializable.", nameof(source));
|
|
}
|
|
|
|
// Don't serialize a null object, simply return the default for that object
|
|
if (UnityEngine.Object.ReferenceEquals(source, null))
|
|
{
|
|
return default(T);
|
|
}
|
|
|
|
IFormatter formatter = new BinaryFormatter();
|
|
Stream stream = new MemoryStream();
|
|
using (stream)
|
|
{
|
|
formatter.Serialize(stream, source);
|
|
stream.Seek(0, SeekOrigin.Begin);
|
|
return (T)formatter.Deserialize(stream);
|
|
}
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
/// Generic Function to remove an array element at a certain index
|
|
/// </summary>
|
|
/// <typeparam name="T"></typeparam>
|
|
/// <param name="inputArray"></param>
|
|
/// <param name="indexToRemove"></param>
|
|
/// <returns></returns>
|
|
public static T[] RemoveArrayIndexAt<T>(T[] inputArray, int indexToRemove)
|
|
{
|
|
T[] newArray = new T[inputArray.Length - 1];
|
|
for (int i = 0; i < newArray.Length; ++i)
|
|
{
|
|
if (i < indexToRemove)
|
|
{
|
|
newArray[i] = inputArray[i];
|
|
}
|
|
else if (i >= indexToRemove)
|
|
{
|
|
newArray[i] = inputArray[i + 1];
|
|
}
|
|
}
|
|
return newArray;
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
/// Generic Function to add a new array element at the end of an array.
|
|
/// </summary>
|
|
/// <typeparam name="T"></typeparam>
|
|
/// <param name="inputArray"></param>
|
|
/// <param name="newElement"></param>
|
|
/// <returns></returns>
|
|
public static T[] AddElementToArray<T>(T[] inputArray, T newElement)
|
|
{
|
|
T[] newArray = new T[inputArray.Length + 1];
|
|
for (int i = 0; i < inputArray.Length; ++i)
|
|
{
|
|
newArray[i] = inputArray[i];
|
|
}
|
|
newArray[newArray.Length - 1] = newElement;
|
|
return newArray;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Generic Function to insert a new array element at a certain index position in an array
|
|
/// </summary>
|
|
/// <typeparam name="T"></typeparam>
|
|
/// <param name="inputArray"></param>
|
|
/// <param name="newElement"></param>
|
|
/// <param name="indexToInsertAt"></param>
|
|
/// <returns></returns>
|
|
public static T[] InsertElementInArray<T>(T[] inputArray, T newElement, int indexToInsertAt)
|
|
{
|
|
T[] newArray = new T[inputArray.Length + 1];
|
|
for (int i = 0; i < newArray.Length; ++i)
|
|
{
|
|
if (i < indexToInsertAt)
|
|
{
|
|
newArray[i] = inputArray[i];
|
|
}
|
|
else if (i > indexToInsertAt)
|
|
{
|
|
newArray[i] = inputArray[i - 1];
|
|
}
|
|
else
|
|
{
|
|
newArray[i] = newElement;
|
|
}
|
|
}
|
|
|
|
return newArray;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Generic Function to swap the position of two array elements
|
|
/// </summary>
|
|
/// <param name="m_reorderableRuleMasksLists"></param>
|
|
/// <param name="firstIndex"></param>
|
|
/// <param name="secondIndex"></param>
|
|
/// <returns></returns>
|
|
public static T[] SwapElementsInArray<T>(T[] inputArray, int firstIndex, int secondIndex)
|
|
{
|
|
//sanity check
|
|
int maxIndex = inputArray.Length - 1;
|
|
if (firstIndex > maxIndex || secondIndex > maxIndex || firstIndex < 0 || secondIndex < 0)
|
|
{
|
|
Debug.LogError("Could not swap array elements: First Index " + firstIndex.ToString() + " or Second Index " + secondIndex.ToString() + " are out of bounds.");
|
|
return inputArray;
|
|
}
|
|
|
|
T temp = inputArray[firstIndex];
|
|
inputArray[firstIndex] = inputArray[secondIndex];
|
|
inputArray[secondIndex] = temp;
|
|
|
|
return inputArray;
|
|
}
|
|
|
|
|
|
#endregion
|
|
|
|
#region Adhoc helpers
|
|
|
|
/// <summary>
|
|
/// Inverts an animation curve
|
|
/// </summary>
|
|
/// <param name="curve">The curve to invert</param>
|
|
public static void InvertAnimationCurve(ref AnimationCurve curve)
|
|
{
|
|
float minValue = float.MaxValue;
|
|
float maxValue = float.MinValue;
|
|
|
|
for (int i = 0; i < curve.keys.Length; i += curve.keys.Length - 1)
|
|
{
|
|
if (curve.keys[i].value > maxValue)
|
|
{
|
|
maxValue = curve.keys[i].value;
|
|
}
|
|
if (curve.keys[i].value < minValue)
|
|
{
|
|
minValue = curve.keys[i].value;
|
|
}
|
|
}
|
|
|
|
float middleValue = (maxValue + minValue) * 0.5f;
|
|
|
|
Keyframe[] keys = curve.keys;
|
|
for (int i = 0; i < keys.Length; i++)
|
|
{
|
|
keys[i].value = keys[i].value + 2 * (middleValue - keys[i].value);
|
|
keys[i].inTangent *= -1f;
|
|
keys[i].inWeight *= -1f;
|
|
keys[i].outTangent *= -1f;
|
|
keys[i].outWeight *= -1f;
|
|
}
|
|
curve.keys = keys;
|
|
}
|
|
|
|
|
|
public static Transform GetGOSpawnTarget(SpawnRule rule, string protoName, Terrain currentTerrain)
|
|
{
|
|
//If spawn mode is set to single transform, and we do have a transform, we are done already
|
|
if (rule.m_goSpawnTargetMode == GaiaConstants.SpawnerTargetMode.SingleTransform && rule.m_goSpawnTarget != null)
|
|
{
|
|
return rule.m_goSpawnTarget;
|
|
}
|
|
|
|
//No transform yet? We might need to build it first then
|
|
|
|
//The "container" is either the Gaia Game Object or the current terrain
|
|
Transform containerTransform;
|
|
|
|
if (rule.m_goSpawnTargetMode == GaiaConstants.SpawnerTargetMode.SingleTransform)
|
|
{
|
|
containerTransform = GaiaUtils.GetGaiaGameObject().transform;
|
|
}
|
|
else
|
|
{
|
|
containerTransform = currentTerrain.transform;
|
|
}
|
|
|
|
//The "parent" transform is the parent under which the target transforms for all spawn rules are collected under
|
|
string parentName = GaiaConstants.defaultGOSpawnTarget;
|
|
|
|
//Default name may be overridden by user input
|
|
if (rule.m_goSpawnTargetMode == GaiaConstants.SpawnerTargetMode.Terrain)
|
|
{
|
|
parentName = rule.m_terrainGOSpawnTargetName;
|
|
}
|
|
|
|
Transform parentTransform = containerTransform.Find(parentName);
|
|
|
|
if (parentTransform == null)
|
|
{
|
|
GameObject newParent = new GameObject();
|
|
newParent.name = parentName;
|
|
newParent.transform.parent = containerTransform;
|
|
parentTransform = newParent.transform;
|
|
}
|
|
|
|
GaiaHierarchyUtils hierarchyUtils = parentTransform.GetComponent<GaiaHierarchyUtils>();
|
|
if (hierarchyUtils == null)
|
|
{
|
|
hierarchyUtils = parentTransform.gameObject.AddComponent<GaiaHierarchyUtils>();
|
|
}
|
|
GaiaHierarchyVisibility ghv = hierarchyUtils.m_visibilityEntries.Find(x => x.m_name == protoName);
|
|
if (ghv != null)
|
|
{
|
|
ghv.m_isVisible = rule.m_visibleInSceneHierarchy;
|
|
}
|
|
{
|
|
hierarchyUtils.m_visibilityEntries.Add(new GaiaHierarchyVisibility() { m_name = protoName, m_isVisible = rule.m_visibleInSceneHierarchy });
|
|
}
|
|
|
|
|
|
Transform ruleTransform = parentTransform.Find(protoName);
|
|
|
|
if (ruleTransform == null)
|
|
{
|
|
GameObject newGO = new GameObject();
|
|
newGO.name = protoName;
|
|
newGO.transform.parent = parentTransform;
|
|
if (rule.m_goSpawnTargetMode == GaiaConstants.SpawnerTargetMode.SingleTransform)
|
|
{
|
|
rule.m_goSpawnTarget = newGO.transform;
|
|
}
|
|
ruleTransform = newGO.transform;
|
|
}
|
|
|
|
return ruleTransform;
|
|
|
|
}
|
|
|
|
/// <summary>
|
|
/// Function used to set the value of the camera layer culling based on valued provided
|
|
/// </summary>
|
|
/// <param name="terrain"></param>
|
|
/// <param name="targetQuality"></param>
|
|
/// <param name="extraValue"></param>
|
|
/// <param name="maxValue"></param>
|
|
/// <returns></returns>
|
|
public static float CalculateCameraCullingLayerValue(Terrain terrain, GaiaConstants.EnvironmentTarget targetQuality, float extraValue = 1f, float maxValue = 2000f)
|
|
{
|
|
try
|
|
{
|
|
float returningValue = maxValue;
|
|
if (terrain == null)
|
|
{
|
|
return returningValue;
|
|
}
|
|
|
|
switch (targetQuality)
|
|
{
|
|
case EnvironmentTarget.UltraLight:
|
|
returningValue = terrain.terrainData.size.x / (16f * extraValue);
|
|
break;
|
|
case EnvironmentTarget.MobileAndVR:
|
|
returningValue = terrain.terrainData.size.x / (12f * extraValue);
|
|
break;
|
|
case EnvironmentTarget.Desktop:
|
|
returningValue = terrain.terrainData.size.x / (4f * extraValue);
|
|
break;
|
|
case EnvironmentTarget.PowerfulDesktop:
|
|
returningValue = terrain.terrainData.size.x / (2f * extraValue);
|
|
break;
|
|
case EnvironmentTarget.Custom:
|
|
returningValue = terrain.terrainData.size.x / extraValue;
|
|
break;
|
|
}
|
|
|
|
return Mathf.Round(returningValue);
|
|
}
|
|
catch (Exception e)
|
|
{
|
|
Console.WriteLine(e);
|
|
return maxValue;
|
|
}
|
|
}
|
|
/// <summary>
|
|
/// Function used to set the value of the shadow layer culling based on valued provided
|
|
/// </summary>
|
|
/// <param name="terrain"></param>
|
|
/// <param name="targetQuality"></param>
|
|
/// <param name="extraValue"></param>
|
|
/// <param name="maxValue"></param>
|
|
/// <returns></returns>
|
|
public static float CalculateShadowCullingLayerValue(Terrain terrain, GaiaConstants.EnvironmentTarget targetQuality, float extraValue = 1f, float maxValue = 2000f)
|
|
{
|
|
try
|
|
{
|
|
float returningValue = maxValue;
|
|
if (terrain == null)
|
|
{
|
|
return returningValue;
|
|
}
|
|
|
|
switch (targetQuality)
|
|
{
|
|
case EnvironmentTarget.UltraLight:
|
|
returningValue = terrain.terrainData.size.x / (32f * extraValue);
|
|
break;
|
|
case EnvironmentTarget.MobileAndVR:
|
|
returningValue = terrain.terrainData.size.x / (24f * extraValue);
|
|
break;
|
|
case EnvironmentTarget.Desktop:
|
|
returningValue = terrain.terrainData.size.x / (8f * extraValue);
|
|
break;
|
|
case EnvironmentTarget.PowerfulDesktop:
|
|
returningValue = terrain.terrainData.size.x / (4f * extraValue);
|
|
break;
|
|
case EnvironmentTarget.Custom:
|
|
returningValue = terrain.terrainData.size.x / extraValue;
|
|
break;
|
|
}
|
|
|
|
return Mathf.Round(returningValue);
|
|
}
|
|
catch (Exception e)
|
|
{
|
|
Console.WriteLine(e);
|
|
return maxValue;
|
|
}
|
|
}
|
|
/// <summary>
|
|
/// Get a color from a html string
|
|
/// </summary>
|
|
/// <param name="htmlString">Color in RRGGBB or RRGGBBBAA or #RRGGBB or #RRGGBBAA format.</param>
|
|
/// <returns>Color or white if unable to parse it.</returns>
|
|
public static Color GetColorFromHTML(string htmlString)
|
|
{
|
|
Color color = Color.white;
|
|
if (!htmlString.StartsWith("#"))
|
|
{
|
|
htmlString = "#" + htmlString;
|
|
}
|
|
if (!ColorUtility.TryParseHtmlString(htmlString, out color))
|
|
{
|
|
color = Color.white;
|
|
}
|
|
return color;
|
|
}
|
|
/// <summary>
|
|
/// Converts the kelvin to a color
|
|
/// </summary>
|
|
public static Color ExecuteKelvinColor(float value)
|
|
{
|
|
return Mathf.CorrelatedColorTemperatureToRGB(value);
|
|
}
|
|
/// <summary>
|
|
/// Checks if all the keys have the same check value
|
|
/// </summary>
|
|
/// <param name="colorKeys"></param>
|
|
/// <param name="checkColor"></param>
|
|
/// <returns></returns>
|
|
public static bool CheckGradientColorKeys(GradientColorKey[] colorKeys, Color checkColor)
|
|
{
|
|
if (checkColor == null || colorKeys.Length < 1)
|
|
{
|
|
return true;
|
|
}
|
|
|
|
int checkCount = 0;
|
|
for (int i = 0; i < colorKeys.Length; i++)
|
|
{
|
|
if (colorKeys[i].color == checkColor)
|
|
{
|
|
checkCount++;
|
|
}
|
|
}
|
|
|
|
if (checkCount == colorKeys.Length)
|
|
{
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
/// <summary>
|
|
/// Checks if 2 gradient color and time values are not the same
|
|
/// </summary>
|
|
/// <param name="colorKeys"></param>
|
|
/// <param name="checkKeys"></param>
|
|
/// <returns></returns>
|
|
public static bool CheckGradientColorKeys(GradientColorKey[] colorKeys, GradientColorKey[] checkKeys)
|
|
{
|
|
if (checkKeys.Length < 1 || colorKeys.Length < 1)
|
|
{
|
|
return true;
|
|
}
|
|
|
|
if (colorKeys.Length != checkKeys.Length)
|
|
{
|
|
return true;
|
|
}
|
|
|
|
for (int i = 0; i < colorKeys.Length; i++)
|
|
{
|
|
if (colorKeys[i].color.r != checkKeys[i].color.r)
|
|
{
|
|
return true;
|
|
}
|
|
if (colorKeys[i].color.g != checkKeys[i].color.g)
|
|
{
|
|
return true;
|
|
}
|
|
if (colorKeys[i].color.b != checkKeys[i].color.b)
|
|
{
|
|
return true;
|
|
}
|
|
if (colorKeys[i].time != checkKeys[i].time)
|
|
{
|
|
return true;
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
/// <summary>
|
|
/// Checks if all the keys have the same check value
|
|
/// </summary>
|
|
/// <param name="keys"></param>
|
|
/// <param name="checkValue"></param>
|
|
/// <returns></returns>
|
|
public static bool CheckAnimationCurveKeys(Keyframe[] keys, float checkValue)
|
|
{
|
|
if (keys == null || keys.Length < 1)
|
|
{
|
|
return true;
|
|
}
|
|
|
|
int checkCount = 0;
|
|
for (int i = 0; i < keys.Length; i++)
|
|
{
|
|
if (keys[i].value == checkValue)
|
|
{
|
|
checkCount++;
|
|
}
|
|
}
|
|
|
|
if (checkCount == keys.Length)
|
|
{
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
/// <summary>
|
|
/// Checks if the color is not null or does not equal the color check value
|
|
/// </summary>
|
|
/// <param name="checkColor"></param>
|
|
/// <param name="colorValue"></param>
|
|
/// <returns></returns>
|
|
public static bool CheckColorKey(Color checkColor, Color colorValue)
|
|
{
|
|
if (checkColor == null || checkColor.r == colorValue.r && checkColor.g == colorValue.g && checkColor.b == colorValue.b)
|
|
{
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
public static Texture2D GetBGTexture(Color backgroundColor, List<Texture2D> tempTextureList)
|
|
{
|
|
int res = 1;
|
|
|
|
Color[] colors = new Color[res * res];
|
|
|
|
for (int i = 0; i < colors.Length; i++)
|
|
{
|
|
colors[i] = backgroundColor;
|
|
}
|
|
|
|
Texture2D tex = new Texture2D(res, res);
|
|
tex.SetPixels(colors);
|
|
tex.Apply(true);
|
|
tempTextureList.Add(tex);
|
|
|
|
return tex;
|
|
}
|
|
|
|
|
|
public static Texture2D GetBGTexture(Color backgroundColor, Color borderColor, List<Texture2D> tempTextureList)
|
|
{
|
|
int res = 6;
|
|
|
|
Color[] colors = new Color[res * res];
|
|
|
|
for (int x = 0; x < res; x++)
|
|
{
|
|
for (int y = 0; y < res; y++)
|
|
{
|
|
int i = x * res + y;
|
|
|
|
if (x == 0 || x == res - 1 || y == 0 || y == res - 1)
|
|
{
|
|
// Apply the border color
|
|
colors[i] = borderColor;
|
|
}
|
|
else
|
|
{
|
|
// Apply the background color
|
|
colors[i] = backgroundColor;
|
|
}
|
|
}
|
|
}
|
|
|
|
Texture2D tex = new Texture2D(res, res);
|
|
tex.SetPixels(colors);
|
|
tex.Apply(true);
|
|
tempTextureList.Add(tex);
|
|
|
|
return tex;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Converts a Render Texture to texture 2D by reading the pixels from it.
|
|
/// </summary>
|
|
/// <param name="renderTexture"></param>
|
|
/// <param name="texture"></param>
|
|
public static Texture2D ConvertRenderTextureToTexture2D(RenderTexture renderTexture)
|
|
{
|
|
Texture2D output = new Texture2D(renderTexture.width, renderTexture.height, TextureFormat.R16, false);
|
|
RenderTexture currentRT = RenderTexture.active;
|
|
RenderTexture.active = renderTexture;
|
|
output.ReadPixels(new Rect(0, 0, renderTexture.width, renderTexture.height), 0, 0);
|
|
output.Apply();
|
|
RenderTexture.active = currentRT;
|
|
return output;
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
/// Checks if two colors are equal or "look the same" according to their argb color values.
|
|
/// A regular comparison with "==" or .Equals does not work to compare if two colors are "the same" since the objects can still have different fields beyond the argb values.
|
|
/// </summary>
|
|
/// <param name="firstColor">first color to compare</param>
|
|
/// <param name="secondColor">second color to compare</param>
|
|
/// <returns></returns>
|
|
public static bool ColorsEqual(Color firstColor, Color secondColor)
|
|
{
|
|
return (firstColor.r == secondColor.r) &&
|
|
(firstColor.g == secondColor.g) &&
|
|
(firstColor.b == secondColor.b) &&
|
|
(firstColor.a == secondColor.a);
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
/// Workaround to release all temporary render textures. Even when Releasing temporary render textures in code, it can still
|
|
/// happen that additional temp render textures stay in memory, this goes over all temporary render textures and releases them.
|
|
/// </summary>
|
|
public static void ReleaseAllTempRenderTextures()
|
|
{
|
|
var rendTex = (RenderTexture[])Resources.FindObjectsOfTypeAll(typeof(RenderTexture));
|
|
for (int i = rendTex.Length - 1; i >= 0; i--)
|
|
{
|
|
if (rendTex[i].name.StartsWith("TempBuffer"))
|
|
{
|
|
RenderTexture.ReleaseTemporary(rendTex[i]);
|
|
}
|
|
}
|
|
GC.Collect();
|
|
}
|
|
|
|
/// <summary>
|
|
/// Calculates the scalar u/v position on a terrain from a world space position
|
|
/// </summary>
|
|
/// <param name="terrain">The terrain for which to perform the calculation.</param>
|
|
/// <param name="worldSpacePosition">The world space position to transform to UV space.</param>
|
|
/// <returns></returns>
|
|
public static Vector2 ConvertPositonToTerrainUV(Terrain terrain, Vector2 worldSpacePosition)
|
|
{
|
|
float u = (worldSpacePosition.x - terrain.transform.position.x) / terrain.terrainData.size.x;
|
|
float v = (worldSpacePosition.y - terrain.transform.position.z) / terrain.terrainData.size.z;
|
|
return new Vector2(u, v);
|
|
}
|
|
|
|
public static long GetUnixTimestamp()
|
|
{
|
|
return new System.DateTimeOffset(System.DateTime.UtcNow).ToUnixTimeMilliseconds();
|
|
}
|
|
|
|
/// <summary>
|
|
/// Returns true if the given operation is a stamping operation
|
|
/// </summary>
|
|
/// <param name="operation">The operation to check against</param>
|
|
/// <returns></returns>
|
|
public static bool IsStampOperation(GaiaConstants.FeatureOperation operation)
|
|
{
|
|
return operation == GaiaConstants.FeatureOperation.RaiseHeight ||
|
|
operation == GaiaConstants.FeatureOperation.LowerHeight ||
|
|
operation == GaiaConstants.FeatureOperation.BlendHeight ||
|
|
operation == GaiaConstants.FeatureOperation.SetHeight ||
|
|
operation == GaiaConstants.FeatureOperation.AddHeight ||
|
|
operation == GaiaConstants.FeatureOperation.SubtractHeight;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Return GaiaSettings or null;
|
|
/// </summary>
|
|
/// <returns>Gaia settings or null if not found</returns>
|
|
public static GaiaSettings GetGaiaSettings()
|
|
{
|
|
return GetAsset("GaiaSettings.asset", typeof(Gaia.GaiaSettings)) as Gaia.GaiaSettings;
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
/// Returns the default Gaia Game Object from the scene hierarchy or creates it if it does not exist
|
|
/// </summary>
|
|
/// <returns></returns>
|
|
public static GameObject GetGaiaGameObject()
|
|
{
|
|
GameObject gaiaObj = GameObject.Find(GaiaConstants.gaiaToolsObject);
|
|
if (gaiaObj == null)
|
|
{
|
|
gaiaObj = GameObject.Find("Gaia");
|
|
if (gaiaObj != null)
|
|
{
|
|
gaiaObj.name = GaiaConstants.gaiaToolsObject;
|
|
}
|
|
}
|
|
if (gaiaObj == null)
|
|
{
|
|
gaiaObj = new GameObject(GaiaConstants.gaiaToolsObject);
|
|
gaiaObj.tag = "EditorOnly";
|
|
}
|
|
return gaiaObj;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Returns the default Game Object for Global Gaia Objects (Water, Wind, etc.) from the scene hierarchy or creates it if it does not exist
|
|
/// </summary>
|
|
/// <returns></returns>
|
|
public static GameObject GetRuntimeSceneObject()
|
|
{
|
|
GameObject gaiaObj = GameObject.Find(GaiaConstants.gaiaRuntimeObject);
|
|
if (gaiaObj == null)
|
|
{
|
|
gaiaObj = GameObject.Find("Gaia Global");
|
|
if (gaiaObj != null)
|
|
{
|
|
gaiaObj.name = GaiaConstants.gaiaRuntimeObject;
|
|
}
|
|
}
|
|
if (gaiaObj == null)
|
|
{
|
|
gaiaObj = new GameObject(GaiaConstants.gaiaRuntimeObject);
|
|
}
|
|
|
|
GaiaGlobal gaiaGlobal = gaiaObj.GetComponent<GaiaGlobal>();
|
|
if (gaiaGlobal == null)
|
|
{
|
|
gaiaGlobal = gaiaObj.AddComponent<GaiaGlobal>();
|
|
}
|
|
return gaiaObj;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Returns the default Game Object for Temporary Session Tools from the scene hierarchy or creates it if it does not exist
|
|
/// </summary>
|
|
/// <returns></returns>
|
|
public static GameObject GetTempSessionToolsObject()
|
|
{
|
|
GameObject gaiaObj = GameObject.Find(GaiaConstants.gaiaTempSessionToolsObject);
|
|
if (gaiaObj == null)
|
|
{
|
|
gaiaObj = new GameObject(GaiaConstants.gaiaTempSessionToolsObject);
|
|
gaiaObj.transform.SetParent(GetGaiaGameObject().transform);
|
|
}
|
|
return gaiaObj;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Returns the default Game Object for Stopwatch Data from the scene hierarchy or creates it if it does not exist
|
|
/// </summary>
|
|
/// <returns></returns>
|
|
public static GameObject GetStopwatchDataObject()
|
|
{
|
|
GameObject gaiaObj = GameObject.Find(GaiaConstants.gaiaStopWatchDataObject);
|
|
if (gaiaObj == null)
|
|
{
|
|
gaiaObj = new GameObject(GaiaConstants.gaiaStopWatchDataObject);
|
|
}
|
|
return gaiaObj;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Returns the default Game Object for Terrain Objects from the scene hierarchy or creates it if it does not exist
|
|
/// </summary>
|
|
/// <returns></returns>
|
|
public static GameObject GetTerrainObject(bool create = true)
|
|
{
|
|
GameObject gaiaObj = GameObject.Find(GaiaConstants.gaiaTerrainObjects);
|
|
//still null? lets search deactivated objects as well
|
|
if (gaiaObj == null)
|
|
{
|
|
gaiaObj = GaiaUtils.FindObjectDeactivated(GaiaConstants.gaiaTerrainObjects, true);
|
|
}
|
|
//still null? lets create
|
|
if (gaiaObj == null && create)
|
|
{
|
|
gaiaObj = new GameObject(GaiaConstants.gaiaTerrainObjects);
|
|
}
|
|
return gaiaObj;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Returns the default Game Object for Terrain Loader Manager Objects from the scene hierarchy or creates it if it does not exist
|
|
/// </summary>
|
|
/// <returns></returns>
|
|
public static GameObject GetTerrainLoaderManagerObject()
|
|
{
|
|
GameObject loaderMgrObj = GameObject.Find(GaiaConstants.gaiaTerrainLoaderManagerObjects);
|
|
if (loaderMgrObj == null)
|
|
{
|
|
//Legacy Renaming
|
|
loaderMgrObj = GameObject.Find("Terrain Loading");
|
|
if (loaderMgrObj != null)
|
|
{
|
|
loaderMgrObj.name = GaiaConstants.gaiaTerrainLoaderManagerObjects;
|
|
}
|
|
}
|
|
if (loaderMgrObj == null)
|
|
{
|
|
GameObject gaiaObject = GetRuntimeSceneObject();
|
|
loaderMgrObj = new GameObject(GaiaConstants.gaiaTerrainLoaderManagerObjects);
|
|
loaderMgrObj.transform.parent = gaiaObject.transform;
|
|
//Add the overview script per default
|
|
loaderMgrObj.AddComponent<TerrainLoaderManager>();
|
|
}
|
|
return loaderMgrObj;
|
|
}
|
|
|
|
public static GameObject GetPlayerObject()
|
|
{
|
|
GameObject gaiaObj = GameObject.Find(GaiaConstants.gaiaPlayerObject);
|
|
if (gaiaObj == null)
|
|
{
|
|
gaiaObj = new GameObject(GaiaConstants.gaiaPlayerObject);
|
|
gaiaObj.transform.SetParent(GetRuntimeSceneObject().transform);
|
|
}
|
|
|
|
if (gaiaObj.GetComponent<GaiaScenePlayer>() == null)
|
|
{
|
|
gaiaObj.AddComponent<GaiaScenePlayer>();
|
|
}
|
|
|
|
return gaiaObj;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Gets the player and returns transform
|
|
/// </summary>
|
|
/// <returns></returns>
|
|
public static Transform GetPlayerTransform()
|
|
{
|
|
GameObject playerObject = GameObject.Find("ThirdPersonController");
|
|
if (playerObject != null)
|
|
{
|
|
return playerObject.transform;
|
|
}
|
|
|
|
playerObject = GameObject.Find("FPSController");
|
|
if (playerObject != null)
|
|
{
|
|
return playerObject.transform;
|
|
}
|
|
|
|
playerObject = GameObject.Find("FlyCam");
|
|
if (playerObject != null)
|
|
{
|
|
return playerObject.transform;
|
|
}
|
|
|
|
playerObject = GameObject.Find("Player");
|
|
if (playerObject != null)
|
|
{
|
|
return playerObject.transform;
|
|
}
|
|
|
|
Camera camera = FindObjectOfType<Camera>();
|
|
if (camera != null)
|
|
{
|
|
return camera.gameObject.transform;
|
|
}
|
|
|
|
return null;
|
|
}
|
|
/// <summary>
|
|
/// Gets the player and returns transform
|
|
/// </summary>
|
|
/// <returns></returns>
|
|
public static GameObject GetPlayerGameObject()
|
|
{
|
|
GameObject playerObject = GameObject.Find("ThirdPersonController");
|
|
if (playerObject != null)
|
|
{
|
|
return playerObject;
|
|
}
|
|
|
|
playerObject = GameObject.Find("FPSController");
|
|
if (playerObject != null)
|
|
{
|
|
return playerObject;
|
|
}
|
|
|
|
playerObject = GameObject.Find("FlyCam");
|
|
if (playerObject != null)
|
|
{
|
|
return playerObject;
|
|
}
|
|
|
|
playerObject = GameObject.Find("Player");
|
|
if (playerObject != null)
|
|
{
|
|
return playerObject;
|
|
}
|
|
|
|
Camera camera = FindObjectOfType<Camera>();
|
|
if (camera != null)
|
|
{
|
|
return camera.gameObject;
|
|
}
|
|
|
|
return null;
|
|
}
|
|
|
|
public static bool DisplayDialogNoEditor(string title, string message, string ok, string cancel, bool resultIfNoDialog = false, string NoDialogFailedConsoleText = "")
|
|
{
|
|
#if UNITY_EDITOR
|
|
return EditorUtility.DisplayDialog(title, message, ok, cancel);
|
|
#else
|
|
if (!resultIfNoDialog)
|
|
{
|
|
Debug.LogError(NoDialogFailedConsoleText);
|
|
}
|
|
return resultIfNoDialog;
|
|
#endif
|
|
}
|
|
|
|
public static bool UsesFloatingPointFix()
|
|
{
|
|
return TerrainLoaderManager.Instance.TerrainSceneStorage.m_useFloatingPointFix;
|
|
}
|
|
|
|
public static bool HasDynamicLoadedTerrains()
|
|
{
|
|
if (TerrainLoaderManager.TerrainSceneStorageCreated)
|
|
{
|
|
return TerrainLoaderManager.TerrainScenes.Count >= 1;
|
|
}
|
|
else
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
|
|
public static void FocusLightingProfile()
|
|
{
|
|
GaiaSettings settings = GaiaUtils.GetGaiaSettings();
|
|
if (settings != null)
|
|
{
|
|
if (settings.m_gaiaLightingProfile != null)
|
|
{
|
|
#if UNITY_EDITOR
|
|
Selection.activeObject = settings.m_gaiaLightingProfile;
|
|
#endif
|
|
}
|
|
else
|
|
{
|
|
Debug.LogError("Lighting Profile in Gaia Settings has not been assigned");
|
|
}
|
|
}
|
|
else
|
|
{
|
|
Debug.LogError("Unable to find Gaia Settings");
|
|
}
|
|
}
|
|
|
|
public static void FocusWaterProfile()
|
|
{
|
|
/*GaiaSettings settings = GaiaUtils.GetGaiaSettings();
|
|
if (settings != null)
|
|
{
|
|
if (settings.m_gaiaLightingProfile != null)
|
|
{
|
|
#if UNITY_EDITOR
|
|
Selection.activeObject = settings.m_gaiaWaterProfile;
|
|
#endif
|
|
}
|
|
else
|
|
{
|
|
Debug.LogError("Water Profile in Gaia Settings has not been assigned");
|
|
}
|
|
}
|
|
else
|
|
{
|
|
Debug.LogError("Unable to find Gaia Settings");
|
|
}*/
|
|
|
|
GameObject gaiaWater = GameObject.Find(GaiaConstants.gaiaWaterObject);
|
|
if (gaiaWater != null)
|
|
{
|
|
#if UNITY_EDITOR
|
|
EditorGUIUtility.PingObject(gaiaWater);
|
|
Selection.activeObject = gaiaWater;
|
|
#endif
|
|
}
|
|
else
|
|
{
|
|
Debug.LogError("Unable to find Gaia Water object");
|
|
}
|
|
}
|
|
|
|
public static int EnvironmentSizeToInt(EnvironmentSize size)
|
|
{
|
|
switch (size)
|
|
{
|
|
case GaiaConstants.EnvironmentSize.Is256MetersSq:
|
|
return 256;
|
|
case GaiaConstants.EnvironmentSize.Is512MetersSq:
|
|
return 512;
|
|
case GaiaConstants.EnvironmentSize.Is1024MetersSq:
|
|
return 1024;
|
|
case GaiaConstants.EnvironmentSize.Is2048MetersSq:
|
|
return 2048;
|
|
case GaiaConstants.EnvironmentSize.Is4096MetersSq:
|
|
return 4096;
|
|
case GaiaConstants.EnvironmentSize.Is8192MetersSq:
|
|
return 8192;
|
|
case GaiaConstants.EnvironmentSize.Is16384MetersSq:
|
|
return 16384;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Select or create the WorldMapEditor
|
|
/// </summary>
|
|
public static GameObject GetOrCreateWorldDesigner(bool createDesigner = true, bool createWorldMap = true)
|
|
{
|
|
GameObject worldMapObj = GameObject.Find(GaiaConstants.worldDesignerObject);
|
|
if (worldMapObj == null && createDesigner)
|
|
{
|
|
GameObject gaiaObj = GaiaUtils.GetGaiaGameObject();
|
|
worldMapObj = new GameObject(GaiaConstants.worldDesignerObject);
|
|
worldMapObj.transform.parent = gaiaObj.transform;
|
|
worldMapObj.transform.position = Vector3.zero;
|
|
}
|
|
WorldMap worldMap = worldMapObj.GetComponent<WorldMap>();
|
|
if (worldMap == null)
|
|
{
|
|
worldMap = worldMapObj.AddComponent<WorldMap>();
|
|
worldMap.hideFlags = HideFlags.HideInInspector;
|
|
}
|
|
if (createWorldMap)
|
|
{
|
|
if (TerrainHelper.GetWorldMapTerrain() == null)
|
|
{
|
|
worldMap.CreateWorldMapTerrain();
|
|
}
|
|
}
|
|
return worldMapObj;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Select or create the WorldMap Temp tools object
|
|
/// </summary>
|
|
public static GameObject GetOrCreateWorldMapTempTools()
|
|
{
|
|
GameObject worldMapTempTools = GameObject.Find(GaiaConstants.worldTempTools);
|
|
if (worldMapTempTools == null)
|
|
{
|
|
GameObject worldMapObj = GetOrCreateWorldDesigner();
|
|
worldMapTempTools = new GameObject(GaiaConstants.worldTempTools);
|
|
worldMapTempTools.transform.parent = worldMapObj.transform;
|
|
}
|
|
return worldMapTempTools;
|
|
}
|
|
|
|
public static void SetSettingsForEnvironment(GaiaSettings settings, EnvironmentTarget targetEnv)
|
|
{
|
|
switch (targetEnv)
|
|
{
|
|
case GaiaConstants.EnvironmentTarget.UltraLight:
|
|
settings.m_currentDefaults.m_spawnDensity = 0.4f;
|
|
settings.m_currentDefaults.m_heightmapResolution = 33;
|
|
settings.m_currentDefaults.m_baseMapDist = Mathf.Clamp(settings.m_currentDefaults.m_terrainSize / 8, 256, 512);
|
|
settings.m_currentDefaults.m_detailResolution = Mathf.Clamp(settings.m_currentDefaults.m_terrainSize / 8, 128, 512);
|
|
settings.m_currentDefaults.m_controlTextureResolution = Mathf.Clamp(settings.m_currentDefaults.m_terrainSize / 8, 64, 512);
|
|
settings.m_currentDefaults.m_baseMapSize = Mathf.Clamp(settings.m_currentDefaults.m_terrainSize / 8, 64, 512);
|
|
break;
|
|
case GaiaConstants.EnvironmentTarget.MobileAndVR:
|
|
settings.m_currentDefaults.m_spawnDensity = 0.6f;
|
|
settings.m_currentDefaults.m_heightmapResolution = Mathf.Clamp(settings.m_currentDefaults.m_terrainSize / 4, 64, 512) + 1;
|
|
settings.m_currentDefaults.m_baseMapDist = Mathf.Clamp(settings.m_currentDefaults.m_terrainSize / 4, 256, 512);
|
|
settings.m_currentDefaults.m_detailResolution = Mathf.Clamp(settings.m_currentDefaults.m_terrainSize / 4, 64, 512);
|
|
settings.m_currentDefaults.m_controlTextureResolution = Mathf.Clamp(settings.m_currentDefaults.m_terrainSize / 4, 64, 512);
|
|
settings.m_currentDefaults.m_baseMapSize = Mathf.Clamp(settings.m_currentDefaults.m_terrainSize / 4, 64, 512);
|
|
break;
|
|
case GaiaConstants.EnvironmentTarget.Desktop:
|
|
settings.m_currentDefaults.m_spawnDensity = 0.8f;
|
|
settings.m_currentDefaults.m_heightmapResolution = Mathf.Clamp(settings.m_currentDefaults.m_terrainSize * 2, 256, 4096) + 1;
|
|
settings.m_currentDefaults.m_baseMapDist = Mathf.Clamp(settings.m_currentDefaults.m_terrainSize, 256, 2048);
|
|
settings.m_currentDefaults.m_detailResolution = Mathf.Clamp(settings.m_currentDefaults.m_terrainSize / 2, 128, 4096);
|
|
settings.m_currentDefaults.m_controlTextureResolution = Mathf.Clamp(settings.m_currentDefaults.m_terrainSize, 256, 2048);
|
|
settings.m_currentDefaults.m_baseMapSize = Mathf.Clamp(settings.m_currentDefaults.m_terrainSize, 256, 2048);
|
|
break;
|
|
case GaiaConstants.EnvironmentTarget.PowerfulDesktop:
|
|
settings.m_currentDefaults.m_spawnDensity = 1.0f;
|
|
settings.m_currentDefaults.m_heightmapResolution = Mathf.Clamp(settings.m_currentDefaults.m_terrainSize * 4, 256, 4096) + 1;
|
|
settings.m_currentDefaults.m_baseMapDist = Mathf.Clamp(settings.m_currentDefaults.m_terrainSize * 2, 256, 2048);
|
|
settings.m_currentDefaults.m_detailResolution = Mathf.Clamp(settings.m_currentDefaults.m_terrainSize, 256, 4096);
|
|
settings.m_currentDefaults.m_controlTextureResolution = Mathf.Clamp(settings.m_currentDefaults.m_terrainSize * 2, 256, 2048);
|
|
settings.m_currentDefaults.m_baseMapSize = Mathf.Clamp(settings.m_currentDefaults.m_terrainSize * 2, 256, 2048);
|
|
break;
|
|
case GaiaConstants.EnvironmentTarget.Custom:
|
|
break;
|
|
default:
|
|
throw new ArgumentOutOfRangeException();
|
|
}
|
|
}
|
|
|
|
public static void ResetBiomePresets(bool forceReset=false)
|
|
{
|
|
#if UNITY_EDITOR
|
|
//Read in the Biome Preset files and spawner setting files that come with the Gaia installation
|
|
UserFiles userFiles = GaiaUtils.GetOrCreateUserFiles();
|
|
if (userFiles.m_updateFilesWithGaiaUpdate || forceReset)
|
|
{
|
|
string[] allSpawnerPresetGUIDs = AssetDatabase.FindAssets("t:BiomePreset", new string[1] { GaiaDirectories.GetGaiaDirectory() });
|
|
|
|
for (int i = 0; i < allSpawnerPresetGUIDs.Length; i++)
|
|
if (allSpawnerPresetGUIDs[i] != null)
|
|
{
|
|
BiomePreset sp = (BiomePreset)AssetDatabase.LoadAssetAtPath(AssetDatabase.GUIDToAssetPath(allSpawnerPresetGUIDs[i]), typeof(BiomePreset));
|
|
if (sp != null && !userFiles.m_gaiaManagerBiomePresets.Contains(sp))
|
|
{
|
|
userFiles.m_gaiaManagerBiomePresets.Add(sp);
|
|
}
|
|
}
|
|
|
|
string[] allSpawnerGUIDs = AssetDatabase.FindAssets("t:SpawnerSettings l:" + GaiaConstants.gaiaManagerSpawnerLabel, new string[1] { GaiaDirectories.GetGaiaDirectory() });
|
|
|
|
for (int i = 0; i < allSpawnerGUIDs.Length; i++)
|
|
if (allSpawnerGUIDs[i] != null)
|
|
{
|
|
string assetPath = AssetDatabase.GUIDToAssetPath(allSpawnerGUIDs[i]);
|
|
SpawnerSettings spawnerSettings = (SpawnerSettings)AssetDatabase.LoadAssetAtPath(assetPath, typeof(SpawnerSettings));
|
|
if (spawnerSettings != null && !userFiles.m_gaiaManagerSpawnerSettings.Contains(spawnerSettings))
|
|
{
|
|
userFiles.m_gaiaManagerSpawnerSettings.Add(spawnerSettings);
|
|
}
|
|
}
|
|
EditorUtility.SetDirty(userFiles);
|
|
AssetDatabase.SaveAssets();
|
|
}
|
|
#endif
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#endregion
|
|
}
|
|
} |