avatar/Assets/VRCSDK/Dependencies/VRChat/Editor/EnvConfig.cs
2022-09-27 20:47:45 -07:00

1281 lines
47 KiB
C#

#define ENV_SET_INCLUDED_SHADERS
using UnityEngine;
using UnityEditor;
using System.Collections;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using UnityEngine.Rendering;
using VRC.SDKBase.Validation.Performance.Stats;
using Object = UnityEngine.Object;
namespace VRC.Editor
{
/// <summary>
/// Setup up SDK env on editor launch
/// </summary>
[InitializeOnLoad]
public class EnvConfig
{
private static readonly BuildTarget[] relevantBuildTargets =
{
BuildTarget.Android,
BuildTarget.iOS,
BuildTarget.StandaloneLinux64,
BuildTarget.StandaloneWindows, BuildTarget.StandaloneWindows64,
BuildTarget.StandaloneOSX
};
#if !VRC_CLIENT
private static readonly BuildTarget[] allowedBuildtargets = {
BuildTarget.StandaloneWindows64,
BuildTarget.Android
};
#endif
private static readonly Dictionary<BuildTarget, GraphicsDeviceType[]> allowedGraphicsAPIs = new Dictionary<BuildTarget, GraphicsDeviceType[]>()
{
{BuildTarget.Android, new[] {GraphicsDeviceType.OpenGLES3, /* GraphicsDeviceType.Vulkan */}},
{BuildTarget.iOS, null},
{BuildTarget.StandaloneLinux64, null},
{BuildTarget.StandaloneWindows, new[] {GraphicsDeviceType.Direct3D11}},
{BuildTarget.StandaloneWindows64, new[] {GraphicsDeviceType.Direct3D11}},
{BuildTarget.StandaloneOSX, null}
};
#if ENV_SET_INCLUDED_SHADERS && VRC_CLIENT
private static readonly string[] ensureTheseShadersAreAvailable =
{
"Hidden/CubeBlend",
"Hidden/CubeBlur",
"Hidden/CubeCopy",
"Hidden/VideoDecode",
"Legacy Shaders/Bumped Diffuse",
"Legacy Shaders/Bumped Specular",
"Legacy Shaders/Decal",
"Legacy Shaders/Diffuse Detail",
"Legacy Shaders/Diffuse Fast",
"Legacy Shaders/Diffuse",
"Legacy Shaders/Diffuse",
"Legacy Shaders/Lightmapped/Diffuse",
"Legacy Shaders/Lightmapped/Specular",
"Legacy Shaders/Lightmapped/VertexLit",
"Legacy Shaders/Parallax Diffuse",
"Legacy Shaders/Parallax Specular",
"Legacy Shaders/Reflective/Bumped Diffuse",
"Legacy Shaders/Reflective/Bumped Specular",
"Legacy Shaders/Reflective/Bumped Unlit",
"Legacy Shaders/Reflective/Bumped VertexLit",
"Legacy Shaders/Reflective/Diffuse",
"Legacy Shaders/Reflective/Parallax Diffuse",
"Legacy Shaders/Reflective/Parallax Specular",
"Legacy Shaders/Reflective/Specular",
"Legacy Shaders/Reflective/VertexLit",
"Legacy Shaders/Self-Illumin/Bumped Diffuse",
"Legacy Shaders/Self-Illumin/Bumped Specular",
"Legacy Shaders/Self-Illumin/Diffuse",
"Legacy Shaders/Self-Illumin/Parallax Diffuse",
"Legacy Shaders/Self-Illumin/Parallax Specular",
"Legacy Shaders/Self-Illumin/Specular",
"Legacy Shaders/Self-Illumin/VertexLit",
"Legacy Shaders/Specular",
"Legacy Shaders/Transparent/Bumped Diffuse",
"Legacy Shaders/Transparent/Bumped Specular",
"Legacy Shaders/Transparent/Cutout/Bumped Diffuse",
"Legacy Shaders/Transparent/Cutout/Bumped Specular",
"Legacy Shaders/Transparent/Cutout/Diffuse",
"Legacy Shaders/Transparent/Cutout/Soft Edge Unlit",
"Legacy Shaders/Transparent/Cutout/Specular",
"Legacy Shaders/Transparent/Cutout/VertexLit",
"Legacy Shaders/Transparent/Diffuse",
"Legacy Shaders/Transparent/Parallax Diffuse",
"Legacy Shaders/Transparent/Parallax Specular",
"Legacy Shaders/Transparent/Specular",
"Legacy Shaders/Transparent/VertexLit",
"Legacy Shaders/VertexLit",
"Legacy Shaders/Particles/Additive",
"Legacy Shaders/Particles/~Additive-Multiply",
"Legacy Shaders/Particles/Additive (Soft)",
"Legacy Shaders/Particles/Alpha Blended",
"Legacy Shaders/Particles/Anim Alpha Blended",
"Legacy Shaders/Particles/Multiply",
"Legacy Shaders/Particles/Multiply (Double)",
"Legacy Shaders/Particles/Alpha Blended Premultiply",
"Legacy Shaders/Particles/VertexLit Blended",
"Mobile/Particles/Additive",
"Mobile/Particles/Alpha Blended",
"Mobile/Particles/Multiply",
"Mobile/Particles/VertexLit Blended",
"Mobile/Skybox",
"Nature/Terrain/Diffuse",
"Nature/Terrain/Specular",
"Nature/Terrain/Standard",
"Particles/Additive (Soft)",
"Particles/Additive",
"Particles/Alpha Blended Premultiply",
"Particles/Alpha Blended",
"Particles/Anim Alpha Blended",
"Particles/Multiply (Double)",
"Particles/Multiply",
"Particles/VertexLit Blended",
"Particles/~Additive-Multiply",
"Skybox/Cubemap",
"Skybox/Procedural",
"Skybox/6 Sided",
"Sprites/Default",
"Sprites/Diffuse",
"UI/Default",
"VRChat/UI/Unlit/WebPanelTransparent",
"Toon/Lit",
"Toon/Lit (Double)",
"Toon/Lit Cutout",
"Toon/Lit Cutout (Double)",
"Toon/Lit Outline",
"VRChat/Mobile/Diffuse",
"Video/RealtimeEmissiveGamma",
"VRChat/PC/Toon Lit",
"VRChat/PC/Toon Lit (Double)",
"VRChat/PC/Toon Lit Cutout",
"VRChat/PC/Toon Lit Cutout (Double)",
"Unlit/Color",
"Unlit/Transparent",
"Unlit/Transparent Cutout",
"Unlit/Texture",
"MatCap/Vertex/Textured Lit",
"VRChat/Mobile/Bumped Uniform Diffuse",
"VRChat/Mobile/Bumped Uniform Specular",
"VRChat/Mobile/Toon Lit",
"VRChat/Mobile/MatCap Lit",
"VRChat/Mobile/Skybox",
"VRChat/Mobile/Lightmapped",
"VRChat/Mobile/Bumped Mapped Specular",
"VRChat/Mobile/Diffuse",
"VRChat/Mobile/Particles/Additive",
"VRChat/Mobile/Particles/Multiply",
"VRChat/Mobile/Standard Lite",
"TextMeshPro/Distance Field (Surface)",
"TextMeshPro/Mobile/Distance Field (No ZTest)",
"TextMeshPro/Distance Field Overlay",
"TextMeshPro/Sprite",
"TextMeshPro/Mobile/Distance Field - Masking",
"TextMeshPro/Mobile/Distance Field Overlay",
"TextMeshPro/Mobile/Distance Field (Surface)",
"TextMeshPro/Mobile/Distance Field",
"TextMeshPro/Distance Field",
"TextMeshPro/Bitmap Custom Atlas",
"VRChat/UI/TextMeshPro/Mobile/Distance Field",
"TextMeshPro/Mobile/Bitmap",
"TextMeshPro/Bitmap",
"TextMeshPro/Mobile/Distance Field - Masking (NoZTest)"
};
#endif
private static bool _requestConfigureSettings = true;
static EnvConfig()
{
EditorApplication.update += EditorUpdate;
}
private static void EditorUpdate()
{
if(!_requestConfigureSettings)
{
return;
}
if(ConfigureSettings())
{
_requestConfigureSettings = false;
}
}
private static void RequestConfigureSettings()
{
_requestConfigureSettings = true;
}
[UnityEditor.Callbacks.DidReloadScripts(int.MaxValue)]
private static void DidReloadScripts()
{
RequestConfigureSettings();
}
private static bool ConfigureSettings()
{
CheckForFirstInit();
if(EditorApplication.isPlayingOrWillChangePlaymode || EditorApplication.isUpdating)
{
return false;
}
ConfigurePlayerSettings();
if(!VRC.Core.ConfigManager.RemoteConfig.IsInitialized())
{
VRC.Core.API.SetOnlineMode(true, "vrchat");
VRC.Core.ConfigManager.RemoteConfig.Init();
}
ConfigureAssets();
LoadEditorResources();
return true;
}
#if !VRC_CLIENT
private static void SetDLLPlatforms(string dllName, bool active)
{
string[] assetGuids = AssetDatabase.FindAssets(dllName);
foreach(string guid in assetGuids)
{
string dllPath = AssetDatabase.GUIDToAssetPath(guid);
if(string.IsNullOrEmpty(dllPath) || dllPath.ToLower().EndsWith(".dll") == false)
{
return;
}
PluginImporter importer = AssetImporter.GetAtPath(dllPath) as PluginImporter;
if(importer == null)
{
return;
}
bool allCorrect = true;
if(importer.GetCompatibleWithAnyPlatform() != active)
{
allCorrect = false;
}
else
{
if(importer.GetCompatibleWithAnyPlatform())
{
if(importer.GetExcludeEditorFromAnyPlatform() != !active ||
importer.GetExcludeFromAnyPlatform(BuildTarget.StandaloneWindows) != !active)
{
allCorrect = false;
}
}
else
{
if(importer.GetCompatibleWithEditor() != active ||
importer.GetCompatibleWithPlatform(BuildTarget.StandaloneWindows) != active)
{
allCorrect = false;
}
}
}
if(allCorrect)
{
continue;
}
if(active)
{
importer.SetCompatibleWithAnyPlatform(true);
importer.SetExcludeEditorFromAnyPlatform(false);
importer.SetExcludeFromAnyPlatform(BuildTarget.Android, false);
importer.SetExcludeFromAnyPlatform(BuildTarget.StandaloneWindows, false);
importer.SetExcludeFromAnyPlatform(BuildTarget.StandaloneWindows64, false);
importer.SetExcludeFromAnyPlatform(BuildTarget.StandaloneLinux64, false);
}
else
{
importer.SetCompatibleWithAnyPlatform(false);
importer.SetCompatibleWithEditor(false);
importer.SetCompatibleWithPlatform(BuildTarget.Android, false);
importer.SetCompatibleWithPlatform(BuildTarget.StandaloneWindows, false);
importer.SetCompatibleWithPlatform(BuildTarget.StandaloneWindows64, false);
importer.SetCompatibleWithPlatform(BuildTarget.StandaloneLinux64, false);
}
importer.SaveAndReimport();
}
}
#endif
[MenuItem("VRChat SDK/Utilities/Force Configure Player Settings")]
public static void ConfigurePlayerSettings()
{
VRC.Core.Logger.Log("Setting required PlayerSettings...", VRC.Core.DebugLevel.All);
SetBuildTarget();
// Needed for Microsoft.CSharp namespace in DLLMaker
// Doesn't seem to work though
if(PlayerSettings.GetApiCompatibilityLevel(EditorUserBuildSettings.selectedBuildTargetGroup) != ApiCompatibilityLevel.NET_4_6)
{
PlayerSettings.SetApiCompatibilityLevel(EditorUserBuildSettings.selectedBuildTargetGroup, ApiCompatibilityLevel.NET_4_6);
}
if(!PlayerSettings.runInBackground)
{
PlayerSettings.runInBackground = true;
}
#if !VRC_CLIENT
SetDLLPlatforms("VRCCore-Standalone", false);
SetDLLPlatforms("VRCCore-Editor", true);
#endif
SetDefaultGraphicsAPIs();
SetGraphicsSettings();
SetQualitySettings();
SetAudioSettings();
SetPlayerSettings();
#if VRC_CLIENT
AssetDatabase.SaveAssets();
AssetDatabase.Refresh();
PlatformSwitcher.RefreshRequiredPackages(EditorUserBuildSettings.selectedBuildTargetGroup);
#else
// SDK
// default to steam runtime in sdk (shouldn't matter)
SetVRSDKs(EditorUserBuildSettings.selectedBuildTargetGroup, new string[] { "None", "OpenVR", "Oculus" });
VRC.Core.AnalyticsSDK.Initialize(VRC.Core.SDKClientUtilities.GetSDKVersionDate());
#endif
#if VRC_CLIENT
// VRCLog should handle disk writing
PlayerSettings.usePlayerLog = false;
foreach(LogType logType in Enum.GetValues(typeof(LogType)).Cast<LogType>())
{
switch(logType)
{
case LogType.Assert:
case LogType.Exception:
{
PlayerSettings.SetStackTraceLogType(logType, StackTraceLogType.ScriptOnly);
break;
}
case LogType.Error:
case LogType.Warning:
case LogType.Log:
{
#if UNITY_EDITOR
PlayerSettings.SetStackTraceLogType(logType, StackTraceLogType.ScriptOnly);
#else
PlayerSettings.SetStackTraceLogType(logType, StackTraceLogType.None);
#endif
break;
}
default:
{
throw new ArgumentOutOfRangeException();
}
}
}
#endif
}
private static void EnableBatching(bool enable)
{
PlayerSettings[] playerSettings = Resources.FindObjectsOfTypeAll<PlayerSettings>();
if(playerSettings == null)
{
return;
}
SerializedObject playerSettingsSerializedObject = new SerializedObject(playerSettings.Cast<Object>().ToArray());
SerializedProperty batchingSettings = playerSettingsSerializedObject.FindProperty("m_BuildTargetBatching");
if(batchingSettings == null)
{
return;
}
for(int i = 0; i < batchingSettings.arraySize; i++)
{
SerializedProperty batchingArrayValue = batchingSettings.GetArrayElementAtIndex(i);
IEnumerator batchingEnumerator = batchingArrayValue?.GetEnumerator();
if(batchingEnumerator == null)
{
continue;
}
while(batchingEnumerator.MoveNext())
{
SerializedProperty property = (SerializedProperty)batchingEnumerator.Current;
if(property != null && property.name == "m_BuildTarget")
{
// only change setting on "Standalone" entry
if(property.stringValue != "Standalone")
{
break;
}
}
if(property != null && property.name == "m_StaticBatching")
{
property.boolValue = enable;
}
if(property != null && property.name == "m_DynamicBatching")
{
property.boolValue = enable;
}
}
}
playerSettingsSerializedObject.ApplyModifiedProperties();
}
public static void SetVRSDKs(BuildTargetGroup buildTargetGroup, string[] sdkNames)
{
VRC.Core.Logger.Log("Setting virtual reality SDKs in PlayerSettings: ", VRC.Core.DebugLevel.All);
if(sdkNames != null)
{
foreach(string s in sdkNames)
{
VRC.Core.Logger.Log("- " + s, VRC.Core.DebugLevel.All);
}
}
if (!EditorApplication.isPlaying)
{
#pragma warning disable 618
PlayerSettings.SetVirtualRealitySDKs(buildTargetGroup, sdkNames);
#pragma warning restore 618
}
}
private static void CheckForFirstInit()
{
bool firstLaunch = SessionState.GetBool("EnvConfigFirstLaunch", true);
if(firstLaunch)
{
SessionState.SetBool("EnvConfigFirstLaunch", false);
}
}
private static void SetDefaultGraphicsAPIs()
{
VRC.Core.Logger.Log("Setting Graphics APIs", VRC.Core.DebugLevel.All);
foreach(BuildTarget target in relevantBuildTargets)
{
GraphicsDeviceType[] apis = allowedGraphicsAPIs[target];
if(apis == null)
{
SetGraphicsAPIs(target, true);
}
else
{
SetGraphicsAPIs(target, false, apis);
}
}
}
private static void SetGraphicsAPIs(BuildTarget platform, bool auto, GraphicsDeviceType[] allowedTypes = null)
{
try
{
if(auto != PlayerSettings.GetUseDefaultGraphicsAPIs(platform))
{
PlayerSettings.SetUseDefaultGraphicsAPIs(platform, auto);
}
}
catch
{
// ignored
}
try
{
if(allowedTypes == null || allowedTypes.Length == 0)
{
return;
}
GraphicsDeviceType[] graphicsAPIs = PlayerSettings.GetGraphicsAPIs(platform);
if(graphicsAPIs == null || graphicsAPIs.Length == 0)
{
return;
}
if(allowedTypes.SequenceEqual(graphicsAPIs))
{
return;
}
PlayerSettings.SetGraphicsAPIs(platform, allowedTypes);
}
catch
{
// ignored
}
}
private static void SetQualitySettings()
{
VRC.Core.Logger.Log("Setting Graphics Settings", VRC.Core.DebugLevel.All);
const string qualitySettingsAssetPath = "ProjectSettings/QualitySettings.asset";
SerializedObject qualitySettings = new SerializedObject(AssetDatabase.LoadAllAssetsAtPath(qualitySettingsAssetPath)[0]);
SerializedProperty qualitySettingsPresets = qualitySettings.FindProperty("m_QualitySettings");
qualitySettingsPresets.arraySize = _graphicsPresets.Length;
bool changedProperty = false;
for(int index = 0; index < _graphicsPresets.Length; index++)
{
SerializedProperty currentQualityLevel = qualitySettingsPresets.GetArrayElementAtIndex(index);
Dictionary<string, object> graphicsPreset = _graphicsPresets[index];
foreach(KeyValuePair<string, object> setting in graphicsPreset)
{
SerializedProperty property = currentQualityLevel.FindPropertyRelative(setting.Key);
if(property == null)
{
Debug.LogWarning($"Serialized property for quality setting '{setting.Key}' could not be found.");
continue;
}
object settingValue = setting.Value;
#if !VRC_CLIENT
if(setting.Key == "name")
{
settingValue = $"VRC {setting.Value}";
}
#endif
switch(settingValue)
{
case null:
{
if(property.objectReferenceValue == setting.Value as Object)
{
continue;
}
property.objectReferenceValue = null;
break;
}
case string settingAsString:
{
if(property.stringValue == settingAsString)
{
continue;
}
property.stringValue = settingAsString;
break;
}
case bool settingAsBool:
{
if(property.boolValue == settingAsBool)
{
continue;
}
property.boolValue = settingAsBool;
break;
}
case int settingAsInt:
{
if(property.intValue == settingAsInt)
{
continue;
}
property.intValue = settingAsInt;
break;
}
case float settingAsFloat:
{
if(Mathf.Approximately(property.floatValue, settingAsFloat))
{
continue;
}
property.floatValue = settingAsFloat;
break;
}
case double settingAsDouble:
{
if(Mathf.Approximately((float)property.doubleValue, (float)settingAsDouble))
{
continue;
}
property.doubleValue = settingAsDouble;
break;
}
case Vector3 settingAsVector3:
{
if(property.vector3Value == settingAsVector3)
{
continue;
}
property.vector3Value = settingAsVector3;
break;
}
case string[] settingAsStringArray:
{
property.arraySize = settingAsStringArray.Length;
bool changedArrayEntry = false;
for(int settingIndex = 0; settingIndex < settingAsStringArray.Length; settingIndex++)
{
SerializedProperty entry = property.GetArrayElementAtIndex(settingIndex);
if(entry.stringValue == settingAsStringArray[settingIndex])
{
continue;
}
entry.stringValue = settingAsStringArray[settingIndex];
changedArrayEntry = true;
}
if(!changedArrayEntry)
{
continue;
}
break;
}
}
#if !VRC_CLIENT
string levelName = _graphicsPresets[index]["name"] as string;
if(Application.isMobilePlatform)
{
if(levelName == "Mobile")
{
Debug.Log($"Set incorrect quality setting '{setting.Key}' in level '{levelName}' to value '{setting.Value}'.");
}
}
else
{
if(levelName != "Mobile")
{
Debug.Log($"Set incorrect quality setting '{setting.Key}' in level '{levelName}' to value '{setting.Value}'.");
}
}
#endif
changedProperty = true;
}
}
if(!changedProperty)
{
return;
}
int defaultQuality = !Application.isMobilePlatform ? 3 : 4;
#if !VRC_CLIENT
Debug.Log($"A quality setting was changed resetting to the default quality: {_graphicsPresets[defaultQuality]["name"]}.");
#endif
SerializedProperty currentGraphicsQuality = qualitySettings.FindProperty("m_CurrentQuality");
currentGraphicsQuality.intValue = defaultQuality;
qualitySettings.ApplyModifiedPropertiesWithoutUndo();
AssetDatabase.SaveAssets();
}
private static void SetGraphicsSettings()
{
VRC.Core.Logger.Log("Setting Graphics Settings", VRC.Core.DebugLevel.All);
const string graphicsSettingsAssetPath = "ProjectSettings/GraphicsSettings.asset";
SerializedObject graphicsManager = new SerializedObject(AssetDatabase.LoadAllAssetsAtPath(graphicsSettingsAssetPath)[0]);
SerializedProperty deferred = graphicsManager.FindProperty("m_Deferred.m_Mode");
deferred.enumValueIndex = 1;
SerializedProperty deferredReflections = graphicsManager.FindProperty("m_DeferredReflections.m_Mode");
deferredReflections.enumValueIndex = 1;
SerializedProperty screenSpaceShadows = graphicsManager.FindProperty("m_ScreenSpaceShadows.m_Mode");
screenSpaceShadows.enumValueIndex = 1;
SerializedProperty legacyDeferred = graphicsManager.FindProperty("m_LegacyDeferred.m_Mode");
legacyDeferred.enumValueIndex = 1;
SerializedProperty depthNormals = graphicsManager.FindProperty("m_DepthNormals.m_Mode");
depthNormals.enumValueIndex = 1;
SerializedProperty motionVectors = graphicsManager.FindProperty("m_MotionVectors.m_Mode");
motionVectors.enumValueIndex = 1;
SerializedProperty lightHalo = graphicsManager.FindProperty("m_LightHalo.m_Mode");
lightHalo.enumValueIndex = 1;
SerializedProperty lensFlare = graphicsManager.FindProperty("m_LensFlare.m_Mode");
lensFlare.enumValueIndex = 1;
#if ENV_SET_INCLUDED_SHADERS && VRC_CLIENT
// clear GraphicsSettings->Always Included Shaders - these cause a +5s app startup time increase on Quest.
// include Shader objects as resources instead
SerializedProperty alwaysIncluded = graphicsManager.FindProperty("m_AlwaysIncludedShaders");
alwaysIncluded.arraySize = 0;
#if ENV_SEARCH_FOR_SHADERS
Resources.LoadAll("", typeof(Shader));
System.Collections.Generic.List<Shader> foundShaders = Resources.FindObjectsOfTypeAll<Shader>()
.Where(s => { string name = s.name.ToLower(); return 0 == (s.hideFlags & HideFlags.DontSave); })
.GroupBy(s => s.name)
.Select(g => g.First())
.ToList();
#else
List<Shader> foundShaders = new List<Shader>();
#endif
foreach(string shader in ensureTheseShadersAreAvailable.OrderBy(s => s, StringComparer.Ordinal))
{
if(foundShaders.Any(s => s.name == shader))
{
continue;
}
Shader namedShader = Shader.Find(shader);
if(namedShader != null)
{
foundShaders.Add(namedShader);
}
}
foundShaders.Sort((s1, s2) => string.Compare(s1.name, s2.name, StringComparison.Ordinal));
// populate Resources list of "always included shaders"
ShaderAssetList alwaysIncludedShaders = AssetDatabase.LoadAssetAtPath<ShaderAssetList>("Assets/Resources/AlwaysIncludedShaders.asset");
alwaysIncludedShaders.Shaders = new Shader[foundShaders.Count];
for(int shaderIdx = 0; shaderIdx < foundShaders.Count; ++shaderIdx)
{
alwaysIncludedShaders.Shaders[shaderIdx] = foundShaders[shaderIdx];
}
EditorUtility.SetDirty(alwaysIncludedShaders);
#endif
SerializedProperty preloaded = graphicsManager.FindProperty("m_PreloadedShaders");
preloaded.ClearArray();
preloaded.arraySize = 0;
SerializedProperty spritesDefaultMaterial = graphicsManager.FindProperty("m_SpritesDefaultMaterial");
spritesDefaultMaterial.objectReferenceValue = Shader.Find("Sprites/Default");
SerializedProperty renderPipeline = graphicsManager.FindProperty("m_CustomRenderPipeline");
renderPipeline.objectReferenceValue = null;
SerializedProperty transparencySortMode = graphicsManager.FindProperty("m_TransparencySortMode");
transparencySortMode.enumValueIndex = 0;
SerializedProperty transparencySortAxis = graphicsManager.FindProperty("m_TransparencySortAxis");
transparencySortAxis.vector3Value = Vector3.forward;
SerializedProperty defaultRenderingPath = graphicsManager.FindProperty("m_DefaultRenderingPath");
defaultRenderingPath.intValue = 1;
SerializedProperty defaultMobileRenderingPath = graphicsManager.FindProperty("m_DefaultMobileRenderingPath");
defaultMobileRenderingPath.intValue = 1;
SerializedProperty tierSettings = graphicsManager.FindProperty("m_TierSettings");
tierSettings.ClearArray();
tierSettings.arraySize = 0;
#if ENV_SET_LIGHTMAP
SerializedProperty lightmapStripping = graphicsManager.FindProperty("m_LightmapStripping");
lightmapStripping.enumValueIndex = 1;
SerializedProperty instancingStripping = graphicsManager.FindProperty("m_InstancingStripping");
instancingStripping.enumValueIndex = 2;
SerializedProperty lightmapKeepPlain = graphicsManager.FindProperty("m_LightmapKeepPlain");
lightmapKeepPlain.boolValue = true;
SerializedProperty lightmapKeepDirCombined = graphicsManager.FindProperty("m_LightmapKeepDirCombined");
lightmapKeepDirCombined.boolValue = true;
SerializedProperty lightmapKeepDynamicPlain = graphicsManager.FindProperty("m_LightmapKeepDynamicPlain");
lightmapKeepDynamicPlain.boolValue = true;
SerializedProperty lightmapKeepDynamicDirCombined = graphicsManager.FindProperty("m_LightmapKeepDynamicDirCombined");
lightmapKeepDynamicDirCombined.boolValue = true;
SerializedProperty lightmapKeepShadowMask = graphicsManager.FindProperty("m_LightmapKeepShadowMask");
lightmapKeepShadowMask.boolValue = true;
SerializedProperty lightmapKeepSubtractive = graphicsManager.FindProperty("m_LightmapKeepSubtractive");
lightmapKeepSubtractive.boolValue = true;
#endif
SerializedProperty albedoSwatchInfos = graphicsManager.FindProperty("m_AlbedoSwatchInfos");
albedoSwatchInfos.ClearArray();
albedoSwatchInfos.arraySize = 0;
SerializedProperty lightsUseLinearIntensity = graphicsManager.FindProperty("m_LightsUseLinearIntensity");
lightsUseLinearIntensity.boolValue = true;
SerializedProperty lightsUseColorTemperature = graphicsManager.FindProperty("m_LightsUseColorTemperature");
lightsUseColorTemperature.boolValue = true;
graphicsManager.ApplyModifiedProperties();
}
public static FogSettings GetFogSettings()
{
VRC.Core.Logger.Log("Force-enabling Fog", VRC.Core.DebugLevel.All);
const string graphicsSettingsAssetPath = "ProjectSettings/GraphicsSettings.asset";
SerializedObject graphicsManager = new SerializedObject(AssetDatabase.LoadAllAssetsAtPath(graphicsSettingsAssetPath)[0]);
SerializedProperty fogStrippingSerializedProperty = graphicsManager.FindProperty("m_FogStripping");
FogSettings.FogStrippingMode fogStripping = (FogSettings.FogStrippingMode)fogStrippingSerializedProperty.enumValueIndex;
SerializedProperty fogKeepLinearSerializedProperty = graphicsManager.FindProperty("m_FogKeepLinear");
bool keepLinear = fogKeepLinearSerializedProperty.boolValue;
SerializedProperty fogKeepExpSerializedProperty = graphicsManager.FindProperty("m_FogKeepExp");
bool keepExp = fogKeepExpSerializedProperty.boolValue;
SerializedProperty fogKeepExp2SerializedProperty = graphicsManager.FindProperty("m_FogKeepExp2");
bool keepExp2 = fogKeepExp2SerializedProperty.boolValue;
FogSettings fogSettings = new FogSettings(fogStripping, keepLinear, keepExp, keepExp2);
return fogSettings;
}
public static void SetFogSettings(FogSettings fogSettings)
{
VRC.Core.Logger.Log("Force-enabling Fog", VRC.Core.DebugLevel.All);
const string graphicsSettingsAssetPath = "ProjectSettings/GraphicsSettings.asset";
SerializedObject graphicsManager = new SerializedObject(AssetDatabase.LoadAllAssetsAtPath(graphicsSettingsAssetPath)[0]);
SerializedProperty fogStripping = graphicsManager.FindProperty("m_FogStripping");
fogStripping.enumValueIndex = (int)fogSettings.fogStrippingMode;
SerializedProperty fogKeepLinear = graphicsManager.FindProperty("m_FogKeepLinear");
fogKeepLinear.boolValue = fogSettings.keepLinear;
SerializedProperty fogKeepExp = graphicsManager.FindProperty("m_FogKeepExp");
fogKeepExp.boolValue = fogSettings.keepExp;
SerializedProperty fogKeepExp2 = graphicsManager.FindProperty("m_FogKeepExp2");
fogKeepExp2.boolValue = fogSettings.keepExp2;
graphicsManager.ApplyModifiedProperties();
}
private static void SetAudioSettings()
{
Object audioManager = AssetDatabase.LoadMainAssetAtPath("ProjectSettings/AudioManager.asset");
SerializedObject audioManagerSerializedObject = new SerializedObject(audioManager);
audioManagerSerializedObject.Update();
SerializedProperty sampleRateSerializedProperty = audioManagerSerializedObject.FindProperty("m_SampleRate");
sampleRateSerializedProperty.intValue = 48000; // forcing 48k seems to avoid sample rate conversion problems
SerializedProperty dspBufferSizeSerializedProperty = audioManagerSerializedObject.FindProperty("m_RequestedDSPBufferSize");
dspBufferSizeSerializedProperty.intValue = 0;
SerializedProperty defaultSpeakerModeSerializedProperty = audioManagerSerializedObject.FindProperty("Default Speaker Mode");
defaultSpeakerModeSerializedProperty.intValue = 2; // 2 = Stereo
SerializedProperty virtualVoiceCountSerializedProperty = audioManagerSerializedObject.FindProperty("m_VirtualVoiceCount");
SerializedProperty realVoiceCountSerializedProperty = audioManagerSerializedObject.FindProperty("m_RealVoiceCount");
if(EditorUserBuildSettings.selectedBuildTargetGroup == BuildTargetGroup.Android)
{
virtualVoiceCountSerializedProperty.intValue = 32;
realVoiceCountSerializedProperty.intValue = 24;
}
else
{
virtualVoiceCountSerializedProperty.intValue = 64;
realVoiceCountSerializedProperty.intValue = 32;
}
audioManagerSerializedObject.ApplyModifiedPropertiesWithoutUndo();
AssetDatabase.SaveAssets();
}
private static void SetPlayerSettings()
{
// asset bundles MUST be built with settings that are compatible with VRC client
#if VRC_OVERRIDE_COLORSPACE_GAMMA
PlayerSettings.colorSpace = ColorSpace.Gamma;
#else
PlayerSettings.colorSpace = ColorSpace.Linear;
#endif
#if !VRC_CLIENT // In client rely on platform-switcher
if (!EditorApplication.isPlaying)
{
#pragma warning disable 618
PlayerSettings.SetVirtualRealitySupported(EditorUserBuildSettings.selectedBuildTargetGroup, true);
#pragma warning restore 618
}
#endif
PlayerSettings.graphicsJobs = true;
PlayerSettings.gpuSkinning = true;
#if UNITY_2019_3_OR_NEWER
PlayerSettings.gcIncremental = true;
#endif
#if VRC_VR_WAVE
PlayerSettings.stereoRenderingPath = StereoRenderingPath.MultiPass; // Need to use Multi-pass on Wave SDK otherwise mirrors break
#else
PlayerSettings.stereoRenderingPath = StereoRenderingPath.SinglePass;
#endif
#if UNITY_2018_4_OR_NEWER && !UNITY_2019_3_OR_NEWER
PlayerSettings.scriptingRuntimeVersion = ScriptingRuntimeVersion.Latest;
#endif
#if UNITY_ANDROID
PlayerSettings.Android.forceSDCardPermission = true; // Need access to SD card for saving images
PlayerSettings.Android.targetArchitectures = AndroidArchitecture.ARM64;
if(PlayerSettings.Android.targetArchitectures.HasFlag(AndroidArchitecture.ARM64))
{
// Since we need different IL2CPP args we can't build ARM64 with other Architectures.
PlayerSettings.Android.targetArchitectures = AndroidArchitecture.ARM64;
PlayerSettings.SetAdditionalIl2CppArgs("");
}
else
{
PlayerSettings.SetAdditionalIl2CppArgs("--linker-flags=\"-long-plt\"");
}
#if UNITY_2019_3_OR_NEWER
PlayerSettings.Android.targetSdkVersion = AndroidSdkVersions.AndroidApiLevel29;
#else
PlayerSettings.Android.targetSdkVersion = AndroidSdkVersions.AndroidApiLevel26;
#endif
#if VRC_VR_OCULUS
#pragma warning disable CS0618
PlayerSettings.VROculus.v2Signing = true;
#pragma warning restore CS0618
#endif
#else
PlayerSettings.SetAdditionalIl2CppArgs("");
#endif
SetActiveSDKDefines();
EnableBatching(true);
}
public static void SetActiveSDKDefines()
{
bool definesChanged = false;
BuildTargetGroup buildTargetGroup = BuildPipeline.GetBuildTargetGroup(EditorUserBuildSettings.activeBuildTarget);
List<string> defines = PlayerSettings.GetScriptingDefineSymbolsForGroup(buildTargetGroup).Split(';').ToList();
Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies();
if(assemblies.Any(assembly => assembly.GetType("VRC.Udon.UdonBehaviour") != null))
{
if(!defines.Contains("UDON", StringComparer.OrdinalIgnoreCase))
{
defines.Add("UDON");
definesChanged = true;
}
}
else if(defines.Contains("UDON"))
{
defines.Remove("UDON");
}
if(VRCSdk3Analysis.IsSdkDllActive(VRCSdk3Analysis.SdkVersion.VRCSDK2))
{
if(!defines.Contains("VRC_SDK_VRCSDK2", StringComparer.OrdinalIgnoreCase))
{
defines.Add("VRC_SDK_VRCSDK2");
definesChanged = true;
}
}
else if(defines.Contains("VRC_SDK_VRCSDK2"))
{
defines.Remove("VRC_SDK_VRCSDK2");
}
if(VRCSdk3Analysis.IsSdkDllActive(VRCSdk3Analysis.SdkVersion.VRCSDK3))
{
if(!defines.Contains("VRC_SDK_VRCSDK3", StringComparer.OrdinalIgnoreCase))
{
defines.Add("VRC_SDK_VRCSDK3");
definesChanged = true;
}
}
else if(defines.Contains("VRC_SDK_VRCSDK3"))
{
defines.Remove("VRC_SDK_VRCSDK3");
}
if(definesChanged)
{
PlayerSettings.SetScriptingDefineSymbolsForGroup(buildTargetGroup, string.Join(";", defines.ToArray()));
}
}
private static void SetBuildTarget()
{
#if !VRC_CLIENT
VRC.Core.Logger.Log("Setting build target", VRC.Core.DebugLevel.All);
BuildTarget target = UnityEditor.EditorUserBuildSettings.activeBuildTarget;
if (!allowedBuildtargets.Contains(target))
{
Debug.LogError("Target not supported, switching to one that is.");
target = allowedBuildtargets[0];
#pragma warning disable CS0618 // Type or member is obsolete
EditorUserBuildSettings.SwitchActiveBuildTarget(target);
#pragma warning restore CS0618 // Type or member is obsolete
}
#endif
}
public static void ConfigureAssets(bool forStandaloneBuild = false)
{
#if VRC_CLIENT
VRC.UI.Client.Editor.VRCUIManagerEditorHelpers.ConfigureNewUIAssets(forStandaloneBuild);
#endif
}
private static void LoadEditorResources()
{
AvatarPerformanceStats.Initialize();
}
public readonly struct FogSettings
{
public enum FogStrippingMode
{
Automatic,
Custom
}
public readonly FogStrippingMode fogStrippingMode;
public readonly bool keepLinear;
public readonly bool keepExp;
public readonly bool keepExp2;
public FogSettings(FogStrippingMode fogStrippingMode)
{
this.fogStrippingMode = fogStrippingMode;
keepLinear = true;
keepExp = true;
keepExp2 = true;
}
public FogSettings(FogStrippingMode fogStrippingMode, bool keepLinear, bool keepExp, bool keepExp2)
{
this.fogStrippingMode = fogStrippingMode;
this.keepLinear = keepLinear;
this.keepExp = keepExp;
this.keepExp2 = keepExp2;
}
}
private static readonly Dictionary<string, object>[] _graphicsPresets =
{
new Dictionary<string, object>
{
{"name", "Low"},
{"pixelLightCount", 4},
{"shadows", 2},
{"shadowResolution", 2},
{"shadowProjection", 1},
{"shadowCascades", 2},
{"shadowDistance", 75f},
{"shadowNearPlaneOffset", 2f},
{"shadowCascade2Split", 0.33333334},
{"shadowCascade4Split", new Vector3(0.06666667f, 0.19999999f, 0.46666664f)},
{"shadowmaskMode", 0},
{"skinWeights", 4},
{"textureQuality", 0},
{"anisotropicTextures", 2},
{"antiAliasing", 0},
{"softParticles", true},
{"softVegetation", true},
{"realtimeReflectionProbes", true},
{"billboardsFaceCameraPosition", true},
{"vSyncCount", 0},
{"lodBias", 1f},
{"maximumLODLevel", 0},
{"streamingMipmapsActive", false},
{"streamingMipmapsAddAllCameras", true},
{"streamingMipmapsMemoryBudget", 512f},
{"streamingMipmapsRenderersPerFrame", 512},
{"streamingMipmapsMaxLevelReduction", 2},
{"streamingMipmapsMaxFileIORequests", 1024},
{"particleRaycastBudget", 1024},
{"asyncUploadTimeSlice", 2},
{"asyncUploadBufferSize", 64},
{"asyncUploadPersistentBuffer", true},
{"resolutionScalingFixedDPIFactor", 1f},
{"customRenderPipeline", null},
{"excludedTargetPlatforms", new[] {"Android"}}
},
new Dictionary<string, object>
{
{"name", "Medium"},
{"pixelLightCount", 4},
{"shadows", 2},
{"shadowResolution", 2},
{"shadowProjection", 1},
{"shadowCascades", 2},
{"shadowDistance", 75f},
{"shadowNearPlaneOffset", 2f},
{"shadowCascade2Split", 0.33333334},
{"shadowCascade4Split", new Vector3(0.06666667f, 0.19999999f, 0.46666664f)},
{"shadowmaskMode", 0},
{"skinWeights", 4},
{"textureQuality", 0},
{"anisotropicTextures", 2},
{"antiAliasing", 4},
{"softParticles", true},
{"softVegetation", true},
{"realtimeReflectionProbes", true},
{"billboardsFaceCameraPosition", true},
{"vSyncCount", 0},
{"lodBias", 1.5f},
{"maximumLODLevel", 0},
{"streamingMipmapsActive", false},
{"streamingMipmapsAddAllCameras", true},
{"streamingMipmapsMemoryBudget", 512f},
{"streamingMipmapsRenderersPerFrame", 512},
{"streamingMipmapsMaxLevelReduction", 2},
{"streamingMipmapsMaxFileIORequests", 1024},
{"particleRaycastBudget", 2048},
{"asyncUploadTimeSlice", 2},
{"asyncUploadBufferSize", 64},
{"asyncUploadPersistentBuffer", true},
{"resolutionScalingFixedDPIFactor", 1f},
{"customRenderPipeline", null},
{"excludedTargetPlatforms", new[] {"Android"}}
},
new Dictionary<string, object>
{
{"name", "High"},
{"pixelLightCount", 8},
{"shadows", 2},
{"shadowResolution", 3},
{"shadowProjection", 1},
{"shadowCascades", 2},
{"shadowDistance", 75f},
{"shadowNearPlaneOffset", 2f},
{"shadowCascade2Split", 0.33333334},
{"shadowCascade4Split", new Vector3(0.06666667f, 0.19999999f, 0.46666664f)},
{"shadowmaskMode", 0},
{"skinWeights", 4},
{"textureQuality", 0},
{"anisotropicTextures", 2},
{"antiAliasing", 4},
{"softParticles", true},
{"softVegetation", true},
{"realtimeReflectionProbes", true},
{"billboardsFaceCameraPosition", true},
{"vSyncCount", 0},
{"lodBias", 2f},
{"maximumLODLevel", 0},
{"streamingMipmapsActive", false},
{"streamingMipmapsAddAllCameras", true},
{"streamingMipmapsMemoryBudget", 512f},
{"streamingMipmapsRenderersPerFrame", 512},
{"streamingMipmapsMaxLevelReduction", 2},
{"streamingMipmapsMaxFileIORequests", 1024},
{"particleRaycastBudget", 4096},
{"asyncUploadTimeSlice", 2},
{"asyncUploadBufferSize", 128},
{"asyncUploadPersistentBuffer", true},
{"resolutionScalingFixedDPIFactor", 1f},
{"customRenderPipeline", null},
{"excludedTargetPlatforms", new []{"Android"}}
},
new Dictionary<string, object>
{
{"name", "Ultra"},
{"pixelLightCount", 8},
{"shadows", 2},
{"shadowResolution", 3},
{"shadowProjection", 1},
{"shadowCascades", 4},
{"shadowDistance", 150f},
{"shadowNearPlaneOffset", 2f},
{"shadowCascade2Split", 0.33333334},
{"shadowCascade4Split", new Vector3(0.06666667f, 0.19999999f, 0.46666664f)},
{"shadowmaskMode", 0},
{"skinWeights", 4},
{"textureQuality", 0},
{"anisotropicTextures", 2},
{"antiAliasing", 4},
{"softParticles", true},
{"softVegetation", true},
{"realtimeReflectionProbes", true},
{"billboardsFaceCameraPosition", true},
{"vSyncCount", 0},
{"lodBias", 2f},
{"maximumLODLevel", 0},
{"streamingMipmapsActive", false},
{"streamingMipmapsAddAllCameras", true},
{"streamingMipmapsMemoryBudget", 512f},
{"streamingMipmapsRenderersPerFrame", 512},
{"streamingMipmapsMaxLevelReduction", 2},
{"streamingMipmapsMaxFileIORequests", 1024},
{"particleRaycastBudget", 4096},
{"asyncUploadTimeSlice", 2},
{"asyncUploadBufferSize", 128},
{"asyncUploadPersistentBuffer", true},
{"resolutionScalingFixedDPIFactor", 1f},
{"customRenderPipeline", null},
{"excludedTargetPlatforms", new[]{"Android"}}
},
new Dictionary<string, object>
{
{"name", "Mobile"},
{"pixelLightCount", 4},
{"shadows", 0},
{"shadowResolution", 1},
{"shadowProjection", 1},
{"shadowCascades", 1},
{"shadowDistance", 50f},
{"shadowNearPlaneOffset", 2f},
{"shadowCascade2Split", 0.33333334},
{"shadowCascade4Split", new Vector3(0.06666667f, 0.19999999f, 0.46666664f)},
{"shadowmaskMode", 0},
{"skinWeights", 4},
{"textureQuality", 0},
{"anisotropicTextures", 2},
{"antiAliasing", 2},
{"softParticles", false},
{"softVegetation", false},
{"realtimeReflectionProbes", false},
{"billboardsFaceCameraPosition", true},
{"vSyncCount", 0},
{"lodBias", 2f},
{"maximumLODLevel", 0},
{"streamingMipmapsActive", false},
{"streamingMipmapsAddAllCameras", true},
{"streamingMipmapsMemoryBudget", 512f},
{"streamingMipmapsRenderersPerFrame", 512},
{"streamingMipmapsMaxLevelReduction", 2},
{"streamingMipmapsMaxFileIORequests", 1024},
{"particleRaycastBudget", 1024},
{"asyncUploadTimeSlice", 1},
{"asyncUploadBufferSize", 32},
{"asyncUploadPersistentBuffer", true},
{"resolutionScalingFixedDPIFactor", 1f},
{"customRenderPipeline", null},
{"excludedTargetPlatforms", new []{"Standalone"}}
}
};
}
}