diff --git a/Editor/Mono/Audio/AudioContainerWindow.cs b/Editor/Mono/Audio/AudioContainerWindow.cs
index be0861dcae..55e043b889 100644
--- a/Editor/Mono/Audio/AudioContainerWindow.cs
+++ b/Editor/Mono/Audio/AudioContainerWindow.cs
@@ -965,6 +965,11 @@ void OnAudioClipListChanged(SerializedProperty property)
// Force a list rebuild when the list has changed or it will not always render correctly
m_ClipsListView.Rebuild();
+ // This function is the first entry-point in `AudioContainerWindow` after an undo-event that alters the
+ // audio clip list has been triggered. And, whenever the list is altered, we need to make sure the state is stopped.
+ State.Stop();
+ ClearClipFieldProgressBars();
+
UpdateTransportButtonStates();
SetTitle();
}
diff --git a/Editor/Mono/BuildPipeline.bindings.cs b/Editor/Mono/BuildPipeline.bindings.cs
index f159eb1b07..a114434beb 100644
--- a/Editor/Mono/BuildPipeline.bindings.cs
+++ b/Editor/Mono/BuildPipeline.bindings.cs
@@ -393,6 +393,24 @@ private static BuildReport BuildPlayer(string[] scenes, string locationPathName,
scenes[i] = scenes[i].Replace('\\', '/').Replace("//", "/");
}
+ if ((options & BuildOptions.Development) == 0)
+ {
+ if ((options & BuildOptions.AllowDebugging) != 0)
+ {
+ throw new ArgumentException("Non-development build cannot allow debugging. Either add the Development build option, or remove the AllowDebugging build option.");
+ }
+
+ if ((options & BuildOptions.EnableDeepProfilingSupport) != 0)
+ {
+ throw new ArgumentException("Non-development build cannot allow deep profiling support. Either add the Development build option, or remove the EnableDeepProfilingSupport build option.");
+ }
+
+ if ((options & BuildOptions.ConnectWithProfiler) != 0)
+ {
+ throw new ArgumentException("Non-development build cannot allow auto-connecting the profiler. Either add the Development build option, or remove the ConnectWithProfiler build option.");
+ }
+ }
+
try
{
return BuildPlayerInternal(scenes, locationPathName, assetBundleManifestPath, buildTargetGroup, target, subtarget, options, extraScriptingDefines);
diff --git a/Editor/Mono/BuildProfile/BuildProfile.cs b/Editor/Mono/BuildProfile/BuildProfile.cs
index baac9a08a6..9098b2e5ab 100644
--- a/Editor/Mono/BuildProfile/BuildProfile.cs
+++ b/Editor/Mono/BuildProfile/BuildProfile.cs
@@ -153,14 +153,23 @@ internal PlayerSettings playerSettings
[VisibleToOtherModules]
internal Action OnPlayerSettingsUpdatedFromYAML;
+ ///
+ /// Cross-pipeline graphics settings overrides in build profile
+ ///
+ [VisibleToOtherModules]
+ internal BuildProfileGraphicsSettings graphicsSettings;
+
[VisibleToOtherModules]
internal Action OnGraphicsSettingsSubAssetRemoved;
///
- /// Cross-pipeline graphics settings overrides in build profile
+ /// Quality settings overrides in build profile
///
[VisibleToOtherModules]
- internal BuildProfileGraphicsSettings graphicsSettings;
+ internal BuildProfileQualitySettings qualitySettings;
+
+ [VisibleToOtherModules]
+ internal Action OnQualitySettingsSubAssetRemoved;
// TODO: Return server IBuildTargets for server build profiles. (https://jira.unity3d.com/browse/PLAT-6612)
///
@@ -235,6 +244,7 @@ void OnEnable()
LoadPlayerSettings();
TryLoadGraphicsSettings();
+ TryLoadQualitySettings();
if (!EditorUserBuildSettings.isBuildProfileAvailable
|| BuildProfileContext.activeProfile != this)
@@ -266,6 +276,21 @@ void TryLoadGraphicsSettings()
graphicsSettings = data;
}
+ void TryLoadQualitySettings()
+ {
+ if (qualitySettings != null)
+ return;
+
+ var path = AssetDatabase.GetAssetPath(this);
+ var objects = AssetDatabase.LoadAllAssetsAtPath(path);
+
+ var data = Array.Find(objects, obj => obj is BuildProfileQualitySettings) as BuildProfileQualitySettings;
+ if (data == null)
+ return;
+
+ qualitySettings = data;
+ }
+
void OnDisable()
{
if (BuildProfileContext.activeProfile == this)
@@ -297,6 +322,7 @@ static void ContextMenuReset(MenuCommand menuCommand)
targetBuildProfile.scriptingDefines = Array.Empty();
BuildProfileModuleUtil.RemovePlayerSettings(targetBuildProfile);
+ targetBuildProfile.RemoveQualitySettings();
targetBuildProfile.RemoveGraphicsSettings();
AssetDatabase.SaveAssetIfDirty(targetBuildProfile);
diff --git a/Editor/Mono/BuildProfile/BuildProfileContext.cs b/Editor/Mono/BuildProfile/BuildProfileContext.cs
index 1c78527f6f..567fc10bba 100644
--- a/Editor/Mono/BuildProfile/BuildProfileContext.cs
+++ b/Editor/Mono/BuildProfile/BuildProfileContext.cs
@@ -314,6 +314,17 @@ internal static bool ActiveProfileHasGraphicsSettings()
return activeProfile.graphicsSettings != null;
}
+ ///
+ /// Check if the active build profile has quality settings
+ ///
+ internal static bool ActiveProfileHasQualitySettings()
+ {
+ if (activeProfile == null)
+ return false;
+
+ return activeProfile.qualitySettings != null;
+ }
+
///
/// Sync the active build profile to EditorUserBuildSettings to ensure they are in a consistent state.
///
@@ -734,6 +745,24 @@ static bool SetActiveShaderVariantCollections(ShaderVariantCollection[] collecti
return true;
}
+ [RequiredByNativeCode, UsedImplicitly]
+ static string[] GetActiveProfileQualityLevels()
+ {
+ if (!ActiveProfileHasQualitySettings())
+ return Array.Empty();
+
+ return activeProfile.qualitySettings.qualityLevels;
+ }
+
+ [RequiredByNativeCode, UsedImplicitly]
+ static string GetActiveProfileDefaultQualityLevel()
+ {
+ if (!ActiveProfileHasQualitySettings())
+ return string.Empty;
+
+ return activeProfile.qualitySettings.defaultQualityLevel;
+ }
+
[RequiredByNativeCode]
static string GetActiveBuildProfilePath()
{
diff --git a/Editor/Mono/BuildProfile/BuildProfileCreate.cs b/Editor/Mono/BuildProfile/BuildProfileCreate.cs
index abdb4e306a..a3c0acd8e5 100644
--- a/Editor/Mono/BuildProfile/BuildProfileCreate.cs
+++ b/Editor/Mono/BuildProfile/BuildProfileCreate.cs
@@ -102,5 +102,20 @@ internal void RemoveGraphicsSettings()
OnGraphicsSettingsSubAssetRemoved?.Invoke();
}
+
+ ///
+ /// Remove the Quality Settings overrides from the build profile.
+ ///
+ internal void RemoveQualitySettings()
+ {
+ if (qualitySettings == null)
+ return;
+
+ AssetDatabase.RemoveObjectFromAsset(qualitySettings);
+ qualitySettings = null;
+ EditorUtility.SetDirty(this);
+
+ OnQualitySettingsSubAssetRemoved?.Invoke();
+ }
}
}
diff --git a/Editor/Mono/BuildProfile/BuildProfileModuleUtil.cs b/Editor/Mono/BuildProfile/BuildProfileModuleUtil.cs
index ae9f2df67c..d61c6de0e0 100644
--- a/Editor/Mono/BuildProfile/BuildProfileModuleUtil.cs
+++ b/Editor/Mono/BuildProfile/BuildProfileModuleUtil.cs
@@ -608,9 +608,81 @@ public static void OnActiveProfileGraphicsSettingsChanged(bool hasGraphicsSettin
GraphicsSettingsInspector.OnActiveProfileGraphicsSettingsChanged?.Invoke();
}
+ internal static void RemoveQualityLevelFromAllProfiles(string qualityLevelName)
+ {
+ var profiles = GetAllBuildProfiles();
+ foreach (var profile in profiles)
+ {
+ if (profile.qualitySettings == null)
+ continue;
+
+ profile.qualitySettings.RemoveQualityLevel(qualityLevelName);
+ }
+ }
+
+ internal static void RenameQualityLevelInAllProfiles(string oldName, string newName)
+ {
+ var profiles = GetAllBuildProfiles();
+ foreach (var profile in profiles)
+ {
+ if (profile.qualitySettings == null)
+ continue;
+
+ profile.qualitySettings.RenameQualityLevel(oldName, newName);
+ }
+ }
+
+ ///
+ /// Get all custom build profiles in the project.
+ ///
+ public static List GetAllBuildProfiles()
+ {
+ var alreadyLoadedBuildProfiles = Resources.FindObjectsOfTypeAll();
+
+ const string buildProfileAssetSearchString = $"t:{nameof(BuildProfile)}";
+ var assetsGuids = AssetDatabase.FindAssets(buildProfileAssetSearchString);
+ var result = new List(assetsGuids.Length);
+
+ // Suppress missing type warning thrown by serialization. This could happen
+ // when the build profile window is opened, then entering play mode and the
+ // module for that profile is not installed.
+ BuildProfileModuleUtil.SuppressMissingTypeWarning();
+
+ foreach (var guid in assetsGuids)
+ {
+ string path = AssetDatabase.GUIDToAssetPath(guid);
+ BuildProfile profile = AssetDatabase.LoadAssetAtPath(path);
+ if (profile == null)
+ {
+ Debug.LogWarning($"[BuildProfile] Failed to load asset at path: {path}");
+ continue;
+ }
+
+ result.Add(profile);
+ }
+
+ foreach (var buildProfile in alreadyLoadedBuildProfiles)
+ {
+ // Asset database will not give us any build profiles that get created in memory
+ // and we need to include them in this list as we use it to detect that build profiles
+ // have been destroyed and destroy their resources like PlayerSettings afterwards.
+ // Skipping the in-memory build profiles will result in us deleting their associated
+ // player settings object while it's being used and will lead to a crash (UUM-77423)
+ if (buildProfile &&
+ !BuildProfileContext.IsClassicPlatformProfile(buildProfile) &&
+ !BuildProfileContext.IsSharedProfile(buildProfile.buildTarget) &&
+ !EditorUtility.IsPersistent(buildProfile))
+ {
+ result.Add(buildProfile);
+ }
+ }
+
+ return result;
+ }
+
public static string[] GetSettingsRequiringRestart(PlayerSettings previousProfileSettings, PlayerSettings newProfileSettings, BuildTarget oldBuildTarget, BuildTarget newBuildTarget)
{
- return PlayerSettings.GetSettingsRequiringRestart(previousProfileSettings, newProfileSettings, oldBuildTarget, newBuildTarget);
+ return PlayerSettings.GetSettingsRequiringRestart(previousProfileSettings, newProfileSettings, oldBuildTarget, newBuildTarget);
}
public static PlayerSettings GetGlobalPlayerSettings()
diff --git a/Editor/Mono/BuildProfile/BuildProfileQualitySettings.cs b/Editor/Mono/BuildProfile/BuildProfileQualitySettings.cs
new file mode 100644
index 0000000000..7d841df0ad
--- /dev/null
+++ b/Editor/Mono/BuildProfile/BuildProfileQualitySettings.cs
@@ -0,0 +1,66 @@
+// Unity C# reference source
+// Copyright (c) Unity Technologies. For terms of use, see
+// https://unity3d.com/legal/licenses/Unity_Reference_Only_License
+
+using System;
+using UnityEngine;
+using UnityEngine.Bindings;
+
+namespace UnityEditor.Build.Profile
+{
+ [VisibleToOtherModules("UnityEditor.BuildProfileModule")]
+ sealed class BuildProfileQualitySettings : ScriptableObject
+ {
+ [SerializeField] string m_DefaultQualityLevel = string.Empty;
+ [SerializeField] string[] m_QualityLevels = Array.Empty();
+
+ public string defaultQualityLevel
+ {
+ get => m_DefaultQualityLevel;
+ set => m_DefaultQualityLevel = value;
+ }
+
+ public string[] qualityLevels
+ {
+ get => m_QualityLevels;
+ set => m_QualityLevels = value;
+ }
+
+ public void Instantiate()
+ {
+ name = "Quality Settings";
+ hideFlags = HideFlags.HideInHierarchy | HideFlags.HideInInspector;
+ }
+
+ public void RemoveQualityLevel(string qualityLevel)
+ {
+ var index = Array.IndexOf(qualityLevels, qualityLevel);
+ if (index == -1)
+ return;
+
+ var newQualityLevels = new string[qualityLevels.Length - 1];
+ Array.Copy(qualityLevels, 0, newQualityLevels, 0, index);
+ Array.Copy(qualityLevels, index + 1, newQualityLevels, index, qualityLevels.Length - index - 1);
+ qualityLevels = newQualityLevels;
+
+ if (defaultQualityLevel == qualityLevel)
+ defaultQualityLevel = qualityLevels.Length > 0 ? qualityLevels[0] : string.Empty;
+
+ EditorUtility.SetDirty(this);
+ }
+
+ public void RenameQualityLevel(string oldName, string newName)
+ {
+ var index = Array.IndexOf(qualityLevels, oldName);
+ if (index == -1)
+ return;
+
+ qualityLevels[index] = newName;
+
+ if (defaultQualityLevel == oldName)
+ defaultQualityLevel = newName;
+
+ EditorUtility.SetDirty(this);
+ }
+ }
+}
diff --git a/Editor/Mono/BuildProfile/BuildProfileQualitySettingsEditor.cs b/Editor/Mono/BuildProfile/BuildProfileQualitySettingsEditor.cs
new file mode 100644
index 0000000000..a6fa7ad028
--- /dev/null
+++ b/Editor/Mono/BuildProfile/BuildProfileQualitySettingsEditor.cs
@@ -0,0 +1,293 @@
+// Unity C# reference source
+// Copyright (c) Unity Technologies. For terms of use, see
+// https://unity3d.com/legal/licenses/Unity_Reference_Only_License
+
+using System;
+using UnityEditor.UIElements;
+using UnityEngine;
+using UnityEngine.Bindings;
+using UnityEngine.UIElements;
+
+namespace UnityEditor.Build.Profile
+{
+ [VisibleToOtherModules("UnityEditor.BuildProfileModule")]
+ [CustomEditor(typeof(BuildProfileQualitySettings))]
+ sealed class BuildProfileQualitySettingsEditor : Editor
+ {
+ const string k_Uxml = "BuildProfile/UXML/BuildProfileQualitySettings.uxml";
+ const string k_StyleSheet = "BuildProfile/StyleSheets/BuildProfile.uss";
+ const string k_QualitySettingsWindow = "Project/Quality";
+ static readonly GUIContent k_qualitySettingsWindow = EditorGUIUtility.TrTextContent("Quality...");
+ static readonly string k_InvalidQualityLevelWarning =
+ L10n.Tr("The Quality levels in this profile do not match those that exist in the project. This may result in unexpected results on build.");
+ static readonly string k_EmptyQualitySettingsWarning =
+ L10n.Tr("When no Quality levels are listed, the build will take from the global list of Quality levels.");
+ static readonly string k_SetDefaultQualityLevelMenuText = L10n.Tr("Set as Default");
+
+ SerializedProperty m_QualityLevels;
+ SerializedProperty m_DefaultQualityLevel;
+ HelpBox warning;
+
+ public override VisualElement CreateInspectorGUI()
+ {
+ var root = new VisualElement();
+ var visualTree = EditorGUIUtility.LoadRequired(k_Uxml) as VisualTreeAsset;
+ var windowUss = EditorGUIUtility.LoadRequired(k_StyleSheet) as StyleSheet;
+ visualTree.CloneTree(root);
+ root.styleSheets.Add(windowUss);
+
+ m_QualityLevels = serializedObject.FindProperty("m_QualityLevels");
+ m_DefaultQualityLevel = serializedObject.FindProperty("m_DefaultQualityLevel");
+
+ root.Bind(serializedObject);
+ SetupQualityLevelsList(root);
+
+ return root;
+ }
+
+ void SetupQualityLevelsList(VisualElement root)
+ {
+ warning = root.Q("invalid-quality-levels-warning-help-box");
+ UpdateInvalidQualityLevelsWarning();
+
+ var qualityLevelsList = root.Q("quality-levels");
+ root.TrackPropertyValue(m_QualityLevels, sp => {
+ UpdateInvalidQualityLevelsWarning();
+ qualityLevelsList.RefreshItems();
+ });
+ root.TrackPropertyValue(m_DefaultQualityLevel, sp => qualityLevelsList.RefreshItems());
+
+ qualityLevelsList.makeItem = () => new QualityLevelItem(SetDefaultQualityLevelContextMenu());
+ qualityLevelsList.bindItem = (element, index) =>
+ {
+ if (m_QualityLevels.arraySize == 0 || index >= m_QualityLevels.arraySize)
+ return;
+
+ var item = element as QualityLevelItem;
+ var qualityLevelName = m_QualityLevels.GetArrayElementAtIndex(index).stringValue;
+
+ item.text = qualityLevelName;
+ if (IsDefaultQualityLevel(qualityLevelName))
+ item.SetDefaultIndicator(true);
+ else
+ item.SetDefaultIndicator(false);
+ };
+ qualityLevelsList.onAdd = list =>
+ {
+ var menu = new GenericMenu();
+ var allQualityLevels = QualitySettings.names;
+ foreach (var level in allQualityLevels)
+ {
+ if (!IsQualityLevelAdded(level))
+ menu.AddItem(new GUIContent(level), false, () => AddQualityLevel(level));
+ }
+
+ menu.AddSeparator(string.Empty);
+ menu.AddItem(k_qualitySettingsWindow, false, () => SettingsService.OpenProjectSettings(k_QualitySettingsWindow));
+ menu.ShowAsContext();
+ };
+ qualityLevelsList.onRemove = list =>
+ {
+ RemoveQualityLevel();
+ };
+
+ void AddQualityLevel(string newLevel)
+ {
+ m_QualityLevels.InsertArrayElementAtIndex(m_QualityLevels.arraySize);
+ m_QualityLevels.GetArrayElementAtIndex(m_QualityLevels.arraySize - 1).stringValue = newLevel;
+
+ if (m_QualityLevels.arraySize == 1)
+ m_DefaultQualityLevel.stringValue = newLevel;
+
+ serializedObject.ApplyModifiedProperties();
+ }
+
+ void RemoveQualityLevel()
+ {
+ if (m_QualityLevels.arraySize == 0)
+ return;
+
+ var selectedIndex = qualityLevelsList.selectedIndex;
+
+ if (selectedIndex < 0 || selectedIndex >= m_QualityLevels.arraySize)
+ selectedIndex = m_QualityLevels.arraySize - 1;
+
+ if (selectedIndex >= 0)
+ {
+ var deletedQualityLevel = m_QualityLevels.GetArrayElementAtIndex(selectedIndex).stringValue;
+ m_QualityLevels.DeleteArrayElementAtIndex(selectedIndex);
+
+ if (IsDefaultQualityLevel(deletedQualityLevel))
+ m_DefaultQualityLevel.stringValue = m_QualityLevels.arraySize > 0 ?
+ m_QualityLevels.GetArrayElementAtIndex(0).stringValue : string.Empty;
+
+ serializedObject.ApplyModifiedProperties();
+ }
+ }
+ }
+
+ bool IsDefaultQualityLevel(string qualityLevel) => m_DefaultQualityLevel.stringValue == qualityLevel;
+
+ bool IsQualityLevelAdded(string level)
+ {
+ for (var i = 0; i < m_QualityLevels.arraySize; i++)
+ {
+ if (m_QualityLevels.GetArrayElementAtIndex(i).stringValue == level)
+ return true;
+ }
+
+ return false;
+ }
+
+ void UpdateInvalidQualityLevelsWarning()
+ {
+ if (m_QualityLevels.arraySize == 0)
+ {
+ warning.text = k_EmptyQualitySettingsWarning;
+ warning.style.display = DisplayStyle.Flex;
+ }
+ else if (HasInvalidQualityLevels())
+ {
+ warning.text = k_InvalidQualityLevelWarning;
+ warning.style.display = DisplayStyle.Flex;
+ }
+ else
+ warning.style.display = DisplayStyle.None;
+ }
+
+ bool HasInvalidQualityLevels()
+ {
+ var allQualityLevels = QualitySettings.names;
+ for (var i = 0; i < m_QualityLevels.arraySize; i++)
+ {
+ var level = m_QualityLevels.GetArrayElementAtIndex(i).stringValue;
+ if (Array.IndexOf(allQualityLevels, level) == -1)
+ return true;
+ }
+
+ return false;
+ }
+
+ ContextualMenuManipulator SetDefaultQualityLevelContextMenu()
+ {
+ var menu = new ContextualMenuManipulator(evt =>
+ {
+ var selectedQualityLevel = evt.target as QualityLevelItem;
+ if (selectedQualityLevel == null)
+ return;
+
+ evt.menu.AppendAction(k_SetDefaultQualityLevelMenuText, action =>
+ {
+ m_DefaultQualityLevel.stringValue = selectedQualityLevel.text;
+ serializedObject.ApplyModifiedProperties();
+ });
+ });
+
+ return menu;
+ }
+
+ public bool IsDataEqualToGlobalQualitySettings(BuildProfile profile)
+ {
+ var buildTarget = profile.buildTarget;
+ var buildTargetGroupString = BuildPipeline.GetBuildTargetGroup(buildTarget).ToString();
+
+ var globalQualityLevels = QualitySettings.GetActiveQualityLevelsForPlatform(buildTargetGroupString);
+ if (m_QualityLevels.arraySize != globalQualityLevels.Length)
+ return false;
+
+ var allQualityLevels = QualitySettings.names;
+ for (var i = 0; i < m_QualityLevels.arraySize; i++)
+ {
+ var levelIndex = globalQualityLevels[i];
+ if (m_QualityLevels.GetArrayElementAtIndex(i).stringValue != allQualityLevels[levelIndex])
+ return false;
+ }
+
+ var globalDefaultQualityLevelIndex = GetDefaultQualityForPlatform(buildTargetGroupString);
+ if (globalDefaultQualityLevelIndex != -1)
+ {
+ var globalDefaultQualityLevel = allQualityLevels[globalDefaultQualityLevelIndex];
+ if (m_DefaultQualityLevel.stringValue != globalDefaultQualityLevel)
+ return false;
+ }
+
+ return true;
+ }
+
+ public void ResetToGlobalQualitySettingsValues(BuildProfile profile)
+ {
+ var qualityLevels = serializedObject.FindProperty("m_QualityLevels");
+ var defaultQualityLevel = serializedObject.FindProperty("m_DefaultQualityLevel");
+ var buildTarget = profile.buildTarget;
+ var buildTargetGroupString = BuildPipeline.GetBuildTargetGroup(buildTarget).ToString();
+
+ var globalQualityLevels = QualitySettings.GetActiveQualityLevelsForPlatform(buildTargetGroupString);
+ qualityLevels.ClearArray();
+ foreach (var level in globalQualityLevels)
+ {
+ qualityLevels.InsertArrayElementAtIndex(qualityLevels.arraySize);
+ qualityLevels.GetArrayElementAtIndex(qualityLevels.arraySize - 1).stringValue = QualitySettings.names[level];
+ }
+
+ var globalDefaultQualityLevelIndex = GetDefaultQualityForPlatform(buildTargetGroupString);
+ if (globalDefaultQualityLevelIndex != -1)
+ defaultQualityLevel.stringValue = QualitySettings.names[globalDefaultQualityLevelIndex];
+ else
+ defaultQualityLevel.stringValue = qualityLevels.arraySize > 0 ? QualitySettings.names[globalQualityLevels[0]] : string.Empty;
+
+ serializedObject.ApplyModifiedProperties();
+ }
+
+ int GetDefaultQualityForPlatform(string buildTargetGroupName)
+ {
+ var qualitySettings = QualitySettings.GetQualitySettings();
+ var qualitySettingsSO = new SerializedObject(qualitySettings);
+ var perPlatformDefaultQualityProperty = qualitySettingsSO.FindProperty("m_PerPlatformDefaultQuality");
+
+ foreach (SerializedProperty prop in perPlatformDefaultQualityProperty)
+ {
+ if (prop.FindPropertyRelative("first").stringValue == buildTargetGroupName)
+ return prop.FindPropertyRelative("second").intValue;
+ }
+ return -1;
+ }
+
+ class QualityLevelItem : VisualElement
+ {
+ const string k_Uxml = "BuildProfile/UXML/BuildProfileQualitySettingsListElement.uxml";
+ const string k_StyleSheet = "BuildProfile/StyleSheets/BuildProfile.uss";
+ static readonly string k_DefaultIndicatorText = L10n.Tr("Default");
+ protected readonly Label m_Text;
+ protected readonly Label m_DefaultIndicator;
+
+ internal string text
+ {
+ get => m_Text.text;
+ set => m_Text.text = value;
+ }
+
+ internal QualityLevelItem(IManipulator manipulator)
+ {
+ var uxml = EditorGUIUtility.LoadRequired(k_Uxml) as VisualTreeAsset;
+ var stylesheet = EditorGUIUtility.LoadRequired(k_StyleSheet) as StyleSheet;
+ styleSheets.Add(stylesheet);
+ uxml.CloneTree(this);
+
+ m_Text = this.Q