using System;
using UnityEditor;
using UnityEngine.Serialization;
namespace UnityEngine.Rendering.Universal
{
///
/// Universal Render Pipeline's Global Settings.
/// Global settings are unique per Render Pipeline type. In URP, Global Settings contain:
/// - light layer names
///
[URPHelpURL("URP-Global-Settings")]
partial class UniversalRenderPipelineGlobalSettings : RenderPipelineGlobalSettings, ISerializationCallbackReceiver
{
#region Version system
#pragma warning disable CS0414
[SerializeField] int k_AssetVersion = 2;
#pragma warning restore CS0414
public void OnBeforeSerialize()
{
}
public void OnAfterDeserialize()
{
#if UNITY_EDITOR
if (k_AssetVersion != 2)
{
EditorApplication.delayCall += () => UpgradeAsset(this.GetInstanceID());
}
#endif
}
#if UNITY_EDITOR
static void UpgradeAsset(int assetInstanceID)
{
UniversalRenderPipelineGlobalSettings asset = EditorUtility.InstanceIDToObject(assetInstanceID) as UniversalRenderPipelineGlobalSettings;
if (asset.k_AssetVersion < 2)
{
#pragma warning disable 618 // Obsolete warning
// Renamed supportRuntimeDebugDisplay => stripDebugVariants, which results in inverted logic
asset.m_StripDebugVariants = !asset.supportRuntimeDebugDisplay;
asset.k_AssetVersion = 2;
#pragma warning restore 618 // Obsolete warning
// For old test projects lets keep post processing stripping enabled, as huge chance they did not used runtime profile creating
#if UNITY_INCLUDE_TESTS
asset.m_StripUnusedPostProcessingVariants = true;
#endif
}
EditorUtility.SetDirty(asset);
}
#endif
#endregion
private static UniversalRenderPipelineGlobalSettings cachedInstance = null;
///
/// Active URP Global Settings asset. If the value is null then no UniversalRenderPipelineGlobalSettings has been registered to the Graphics Settings with the UniversalRenderPipeline.
///
public static UniversalRenderPipelineGlobalSettings instance
{
get
{
#if !UNITY_EDITOR
// The URP Global Settings could have been changed by script, undo/redo (case 1342987), or file update - file versioning, let us make sure we display the correct one
// In a Player, we do not need to worry about those changes as we only support loading one
if (cachedInstance == null)
#endif
cachedInstance = GraphicsSettings.GetSettingsForRenderPipeline() as UniversalRenderPipelineGlobalSettings;
return cachedInstance;
}
}
static internal void UpdateGraphicsSettings(UniversalRenderPipelineGlobalSettings newSettings)
{
if (newSettings == cachedInstance)
return;
if (newSettings != null)
GraphicsSettings.RegisterRenderPipelineSettings(newSettings as RenderPipelineGlobalSettings);
else
GraphicsSettings.UnregisterRenderPipelineSettings();
cachedInstance = newSettings;
}
/// Default name when creating an URP Global Settings asset.
public static readonly string defaultAssetName = "UniversalRenderPipelineGlobalSettings";
#if UNITY_EDITOR
//Making sure there is at least one UniversalRenderPipelineGlobalSettings instance in the project
internal static UniversalRenderPipelineGlobalSettings Ensure(string folderPath = "", bool canCreateNewAsset = true)
{
if (UniversalRenderPipelineGlobalSettings.instance)
return UniversalRenderPipelineGlobalSettings.instance;
UniversalRenderPipelineGlobalSettings assetCreated = null;
string path = $"Assets/{folderPath}/{defaultAssetName}.asset";
assetCreated = AssetDatabase.LoadAssetAtPath(path);
if (assetCreated == null)
{
var guidGlobalSettingsAssets = AssetDatabase.FindAssets("t:UniversalRenderPipelineGlobalSettings");
//If we could not find the asset at the default path, find the first one
if (guidGlobalSettingsAssets.Length > 0)
{
var curGUID = guidGlobalSettingsAssets[0];
path = AssetDatabase.GUIDToAssetPath(curGUID);
assetCreated = AssetDatabase.LoadAssetAtPath(path);
}
else if (canCreateNewAsset)// or create one altogether
{
if (!AssetDatabase.IsValidFolder("Assets/" + folderPath))
AssetDatabase.CreateFolder("Assets", folderPath);
assetCreated = Create(path);
// TODO: Reenable after next urp template is published
//Debug.LogWarning("No URP Global Settings Asset is assigned. One will be created for you. If you want to modify it, go to Project Settings > Graphics > URP Settings.");
}
else
{
Debug.LogError("If you are building a Player, make sure to save an URP Global Settings asset by opening the project in the Editor first.");
return null;
}
}
Debug.Assert(assetCreated, "Could not create URP's Global Settings - URP may not work correctly - Open Project Settings > Graphics > URP Settings for additional help.");
UpdateGraphicsSettings(assetCreated);
return UniversalRenderPipelineGlobalSettings.instance;
}
internal static UniversalRenderPipelineGlobalSettings Create(string path, UniversalRenderPipelineGlobalSettings src = null)
{
UniversalRenderPipelineGlobalSettings assetCreated = null;
// make sure the asset does not already exists
assetCreated = AssetDatabase.LoadAssetAtPath(path);
if (assetCreated == null)
{
assetCreated = ScriptableObject.CreateInstance();
if (assetCreated != null)
{
assetCreated.name = System.IO.Path.GetFileName(path);
}
AssetDatabase.CreateAsset(assetCreated, path);
Debug.Assert(assetCreated);
}
if (assetCreated)
{
if (src != null)
{
assetCreated.lightLayerName0 = System.String.Copy(src.lightLayerName0);
assetCreated.lightLayerName1 = System.String.Copy(src.lightLayerName1);
assetCreated.lightLayerName2 = System.String.Copy(src.lightLayerName2);
assetCreated.lightLayerName3 = System.String.Copy(src.lightLayerName3);
assetCreated.lightLayerName4 = System.String.Copy(src.lightLayerName4);
assetCreated.lightLayerName5 = System.String.Copy(src.lightLayerName5);
assetCreated.lightLayerName6 = System.String.Copy(src.lightLayerName6);
assetCreated.lightLayerName7 = System.String.Copy(src.lightLayerName7);
}
AssetDatabase.SaveAssets();
AssetDatabase.Refresh();
}
return assetCreated;
}
#endif
void Reset()
{
UpdateRenderingLayerNames();
}
[System.NonSerialized]
string[] m_RenderingLayerNames;
string[] renderingLayerNames
{
get
{
if (m_RenderingLayerNames == null)
UpdateRenderingLayerNames();
return m_RenderingLayerNames;
}
}
[System.NonSerialized]
string[] m_PrefixedRenderingLayerNames;
string[] prefixedRenderingLayerNames
{
get
{
if (m_PrefixedRenderingLayerNames == null)
UpdateRenderingLayerNames();
return m_PrefixedRenderingLayerNames;
}
}
/// Names used for display of rendering layer masks.
public string[] renderingLayerMaskNames => renderingLayerNames;
/// Names used for display of rendering layer masks with a prefix.
public string[] prefixedRenderingLayerMaskNames => prefixedRenderingLayerNames;
/// Regenerate Rendering Layer names and their prefixed versions.
internal void UpdateRenderingLayerNames()
{
if (m_RenderingLayerNames == null)
m_RenderingLayerNames = new string[32];
int index = 0;
m_RenderingLayerNames[index++] = lightLayerName0;
m_RenderingLayerNames[index++] = lightLayerName1;
m_RenderingLayerNames[index++] = lightLayerName2;
m_RenderingLayerNames[index++] = lightLayerName3;
m_RenderingLayerNames[index++] = lightLayerName4;
m_RenderingLayerNames[index++] = lightLayerName5;
m_RenderingLayerNames[index++] = lightLayerName6;
m_RenderingLayerNames[index++] = lightLayerName7;
// Unused
for (int i = index; i < m_RenderingLayerNames.Length; ++i)
{
m_RenderingLayerNames[i] = string.Format("Unused {0}", i);
}
// Update prefixed
if (m_PrefixedRenderingLayerNames == null)
m_PrefixedRenderingLayerNames = new string[32];
if (m_PrefixedLightLayerNames == null)
m_PrefixedLightLayerNames = new string[8];
for (int i = 0; i < m_PrefixedRenderingLayerNames.Length; ++i)
{
m_PrefixedRenderingLayerNames[i] = string.Format("{0}: {1}", i, m_RenderingLayerNames[i]);
if (i < 8)
m_PrefixedLightLayerNames[i] = m_PrefixedRenderingLayerNames[i];
}
}
[System.NonSerialized]
string[] m_PrefixedLightLayerNames = null;
///
/// Names used for display of light layers with Layer's index as prefix.
/// For example: "0: Light Layer Default"
///
public string[] prefixedLightLayerNames
{
get
{
if (m_PrefixedLightLayerNames == null)
UpdateRenderingLayerNames();
return m_PrefixedLightLayerNames;
}
}
#region Light Layer Names [3D]
static readonly string[] k_DefaultLightLayerNames = { "Light Layer default", "Light Layer 1", "Light Layer 2", "Light Layer 3", "Light Layer 4", "Light Layer 5", "Light Layer 6", "Light Layer 7" };
/// Name for light layer 0.
public string lightLayerName0 = k_DefaultLightLayerNames[0];
/// Name for light layer 1.
public string lightLayerName1 = k_DefaultLightLayerNames[1];
/// Name for light layer 2.
public string lightLayerName2 = k_DefaultLightLayerNames[2];
/// Name for light layer 3.
public string lightLayerName3 = k_DefaultLightLayerNames[3];
/// Name for light layer 4.
public string lightLayerName4 = k_DefaultLightLayerNames[4];
/// Name for light layer 5.
public string lightLayerName5 = k_DefaultLightLayerNames[5];
/// Name for light layer 6.
public string lightLayerName6 = k_DefaultLightLayerNames[6];
/// Name for light layer 7.
public string lightLayerName7 = k_DefaultLightLayerNames[7];
[System.NonSerialized]
string[] m_LightLayerNames = null;
///
/// Names used for display of light layers.
///
public string[] lightLayerNames
{
get
{
if (m_LightLayerNames == null)
{
m_LightLayerNames = new string[8];
}
m_LightLayerNames[0] = lightLayerName0;
m_LightLayerNames[1] = lightLayerName1;
m_LightLayerNames[2] = lightLayerName2;
m_LightLayerNames[3] = lightLayerName3;
m_LightLayerNames[4] = lightLayerName4;
m_LightLayerNames[5] = lightLayerName5;
m_LightLayerNames[6] = lightLayerName6;
m_LightLayerNames[7] = lightLayerName7;
return m_LightLayerNames;
}
}
internal void ResetRenderingLayerNames()
{
lightLayerName0 = k_DefaultLightLayerNames[0];
lightLayerName1 = k_DefaultLightLayerNames[1];
lightLayerName2 = k_DefaultLightLayerNames[2];
lightLayerName3 = k_DefaultLightLayerNames[3];
lightLayerName4 = k_DefaultLightLayerNames[4];
lightLayerName5 = k_DefaultLightLayerNames[5];
lightLayerName6 = k_DefaultLightLayerNames[6];
lightLayerName7 = k_DefaultLightLayerNames[7];
}
#endregion
#region Misc Settings
[SerializeField] bool m_StripDebugVariants = true;
[SerializeField] bool m_StripUnusedPostProcessingVariants = false;
[SerializeField] bool m_StripUnusedVariants = true;
///
/// Controls whether debug display shaders for Rendering Debugger are available in Player builds.
///
[Obsolete("Please use stripRuntimeDebugShaders instead.", false)]
public bool supportRuntimeDebugDisplay = false;
///
/// Controls whether debug display shaders for Rendering Debugger are available in Player builds.
///
public bool stripDebugVariants { get => m_StripDebugVariants; set { m_StripDebugVariants = value; } }
///
/// Controls whether strips automatically post processing shader variants based on components.
/// It strips based on VolumeProfiles in project and not scenes that actually uses it.
///
public bool stripUnusedPostProcessingVariants { get => m_StripUnusedPostProcessingVariants; set { m_StripUnusedPostProcessingVariants = value; } }
///
/// Controls whether strip off variants if the feature is enabled.
///
public bool stripUnusedVariants { get => m_StripUnusedVariants; set { m_StripUnusedVariants = value; } }
#endregion
}
}